* removed tone_indicate, we genrate only the dialtone by ourself (and the hanguptone of course)

* removed the state handling from release_chan, and simplified the ast_hangup/ast_queue_hangup stuff
* added pp_l2_check option, for pp lines where the pbx does not initially gets the L2 up
* simplified and fixed a bug in the pid generation code 
* fixed a bug in empty_chan, which might cause segfaults and memorry corruptions
* added prepare_bc function, which is sort of the opposite of empty_bc



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@37172 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Christian Richter 20 years ago
parent ebc9c3765b
commit bd0b801a0d

@ -148,6 +148,9 @@ struct chan_list {
char allowed_bearers[BUFFERSIZE+1]; char allowed_bearers[BUFFERSIZE+1];
enum misdn_chan_state state; enum misdn_chan_state state;
int need_queue_hangup;
int need_hangup;
int holded; int holded;
int orginator; int orginator;
@ -260,6 +263,9 @@ static void chan_misdn_log(int level, int port, char *tmpl, ...);
static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c); static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
static void send_digit_to_chan(struct chan_list *cl, char digit ); static void send_digit_to_chan(struct chan_list *cl, char digit );
static void hangup_chan(struct chan_list *ch);
static int pbx_start_chan(struct chan_list *ch);
#define AST_CID_P(ast) ast->cid.cid_num #define AST_CID_P(ast) ast->cid.cid_num
#define AST_BRIDGED_P(ast) ast_bridged_channel(ast) #define AST_BRIDGED_P(ast) ast_bridged_channel(ast)
@ -309,8 +315,9 @@ static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
static int dialtone_indicate(struct chan_list *cl);
static int tone_indicate( struct chan_list *cl, enum tone_e tone); static int hanguptone_indicate(struct chan_list *cl);
static int stop_indicate(struct chan_list *cl);
static int start_bc_tones(struct chan_list *cl); static int start_bc_tones(struct chan_list *cl);
static int stop_bc_tones(struct chan_list *cl); static int stop_bc_tones(struct chan_list *cl);
@ -1826,7 +1833,7 @@ static int misdn_answer(struct ast_channel *ast)
p->state = MISDN_CONNECTED; p->state = MISDN_CONNECTED;
misdn_lib_echo(p->bc,0); misdn_lib_echo(p->bc,0);
tone_indicate(p, TONE_NONE); stop_indicate(p);
if ( ast_strlen_zero(p->bc->cad) ) { if ( ast_strlen_zero(p->bc->cad) ) {
chan_misdn_log(2,p->bc->port," --> empty cad using dad\n"); chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
@ -1939,15 +1946,18 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
p->bc->out_cause=17; p->bc->out_cause=17;
if (p->state != MISDN_CONNECTED) { if (p->state != MISDN_CONNECTED) {
start_bc_tones(p);
misdn_lib_send_event( p->bc, EVENT_DISCONNECT); misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
return -1;
} else { } else {
chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name); chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
} }
return -1;
break; break;
case AST_CONTROL_RING: case AST_CONTROL_RING:
chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1); chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
return -1;
break; break;
case AST_CONTROL_RINGING: case AST_CONTROL_RINGING:
switch (p->state) { switch (p->state) {
case MISDN_ALERTING: case MISDN_ALERTING:
@ -1972,13 +1982,6 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n"); chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
break; break;
} }
#if 0
if (p->other_ch->bc->nt) {
chan_misdn_log(1,p->bc->port, " --> other End is mISDN NT .. \n");
break;
}
#endif
} }
chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1); chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
@ -1996,9 +1999,11 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
break; break;
case AST_CONTROL_TAKEOFFHOOK: case AST_CONTROL_TAKEOFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1); chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
return -1;
break; break;
case AST_CONTROL_OFFHOOK: case AST_CONTROL_OFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1); chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
return -1;
break; break;
case AST_CONTROL_FLASH: case AST_CONTROL_FLASH:
chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1); chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
@ -2023,13 +2028,13 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
} }
if (p->bc->nt) { if (p->bc->nt) {
tone_indicate(p, TONE_BUSY); hanguptone_indicate(p);
} }
break; break;
case -1 : case -1 :
chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1); chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
tone_indicate(p, TONE_NONE); stop_indicate(p);
if (p->state == MISDN_CONNECTED) if (p->state == MISDN_CONNECTED)
start_bc_tones(p); start_bc_tones(p);
@ -2124,9 +2129,8 @@ static int misdn_hangup(struct ast_channel *ast)
break; break;
case MISDN_HOLDED: case MISDN_HOLDED:
case MISDN_DIALING: case MISDN_DIALING:
case MISDN_CALLING_ACKNOWLEDGE:
start_bc_tones(p); start_bc_tones(p);
tone_indicate(p, TONE_HANGUP); hanguptone_indicate(p);
if (bc->nt) { if (bc->nt) {
misdn_lib_send_event( bc, EVENT_DISCONNECT); misdn_lib_send_event( bc, EVENT_DISCONNECT);
@ -2136,11 +2140,18 @@ static int misdn_hangup(struct ast_channel *ast)
} }
break; break;
case MISDN_CALLING_ACKNOWLEDGE:
start_bc_tones(p);
hanguptone_indicate(p);
misdn_lib_send_event( bc, EVENT_DISCONNECT);
break;
case MISDN_ALERTING: case MISDN_ALERTING:
case MISDN_PROGRESS: case MISDN_PROGRESS:
case MISDN_PROCEEDING: case MISDN_PROCEEDING:
if (p->orginator != ORG_AST) if (p->orginator != ORG_AST)
tone_indicate(p, TONE_HANGUP); hanguptone_indicate(p);
/*p->state=MISDN_CLEANING;*/ /*p->state=MISDN_CLEANING;*/
misdn_lib_send_event( bc, EVENT_DISCONNECT); misdn_lib_send_event( bc, EVENT_DISCONNECT);
@ -2149,7 +2160,7 @@ static int misdn_hangup(struct ast_channel *ast)
/* Alerting or Disconect */ /* Alerting or Disconect */
if (p->bc->nt) { if (p->bc->nt) {
start_bc_tones(p); start_bc_tones(p);
tone_indicate(p, TONE_HANGUP); hanguptone_indicate(p);
p->bc->progress_indicator=8; p->bc->progress_indicator=8;
} }
misdn_lib_send_event( bc, EVENT_DISCONNECT); misdn_lib_send_event( bc, EVENT_DISCONNECT);
@ -2249,9 +2260,18 @@ static struct ast_frame *misdn_read(struct ast_channel *ast)
struct chan_list *tmp; struct chan_list *tmp;
int len; int len;
if (!ast) return NULL; if (!ast) {
if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL; chan_misdn_log(1,0,"misdn_read called without ast\n");
if (!tmp->bc) return NULL; return NULL;
}
if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) {
chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
return NULL;
}
if (!tmp->bc) {
chan_misdn_log(1,0,"misdn_read called without bc\n");
return NULL;
}
len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf)); len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
@ -2487,51 +2507,12 @@ static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
/** AST INDICATIONS END **/ /** AST INDICATIONS END **/
static int tone_indicate( struct chan_list *cl, enum tone_e tone) static int dialtone_indicate(struct chan_list *cl)
{ {
const struct tone_zone_sound *ts= NULL; const struct tone_zone_sound *ts= NULL;
struct ast_channel *ast=cl->ast; struct ast_channel *ast=cl->ast;
chan_misdn_log(3,cl->bc->port,"Tone Indicate:\n");
if (!cl->ast) {
chan_misdn_log(3,cl->bc->port,"Ast Ptr Not existing anymore.. we need to generate tones ourselves now (tbd)\n");
misdn_lib_send_tone(cl->bc,tone);
misdn_lib_tone_generator_start(cl->bc);
return 0;
}
switch (tone) {
case TONE_DIAL:
chan_misdn_log(3,cl->bc->port," --> Dial\n"); chan_misdn_log(3,cl->bc->port," --> Dial\n");
ts=ast_get_indication_tone(ast->zone,"dial"); ts=ast_get_indication_tone(ast->zone,"dial");
break;
case TONE_ALERTING:
chan_misdn_log(3,cl->bc->port," --> Ring\n");
ts=ast_get_indication_tone(ast->zone,"ring");
break;
case TONE_FAR_ALERTING:
/* VERY UGLY HACK, BECAUSE CHAN_SIP DOES NOT GENERATE TONES */
chan_misdn_log(3,cl->bc->port," --> Ring\n");
ts=ast_get_indication_tone(ast->zone,"ring");
misdn_lib_echo(cl->bc,1);
break;
case TONE_BUSY:
chan_misdn_log(3,cl->bc->port," --> Busy\n");
ts=ast_get_indication_tone(ast->zone,"busy");
break;
case TONE_FILE:
break;
case TONE_NONE:
chan_misdn_log(3,cl->bc->port," --> None\n");
misdn_lib_tone_generator_stop(cl->bc);
ast_playtones_stop(ast);
break;
default:
chan_misdn_log(0,cl->bc->port,"Don't know how to handle tone: %d\n",tone);
}
cl->ts=ts; cl->ts=ts;
if (ts) { if (ts) {
@ -2545,9 +2526,27 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone)
return 0; return 0;
} }
static int hanguptone_indicate(struct chan_list *cl)
{
misdn_lib_send_tone(cl->bc,TONE_HANGUP);
misdn_lib_tone_generator_start(cl->bc);
return 0;
}
static int stop_indicate(struct chan_list *cl)
{
struct ast_channel *ast=cl->ast;
chan_misdn_log(3,cl->bc->port," --> None\n");
misdn_lib_tone_generator_stop(cl->bc);
ast_playtones_stop(ast);
/*ast_deactivate_generator(ast);*/
return 0;
}
static int start_bc_tones(struct chan_list* cl) static int start_bc_tones(struct chan_list* cl)
{ {
/* manager_bchannel_activate(cl->bc); */
misdn_lib_tone_generator_stop(cl->bc); misdn_lib_tone_generator_stop(cl->bc);
cl->notxtone=0; cl->notxtone=0;
cl->norxtone=0; cl->norxtone=0;
@ -2556,10 +2555,8 @@ static int start_bc_tones(struct chan_list* cl)
static int stop_bc_tones(struct chan_list *cl) static int stop_bc_tones(struct chan_list *cl)
{ {
/* if (cl->bc) { if (!cl) return -1;
manager_bchannel_deactivate(cl->bc);
}
*/
cl->notxtone=1; cl->notxtone=1;
cl->norxtone=1; cl->norxtone=1;
@ -2579,6 +2576,8 @@ static struct chan_list *init_chan_list(int orig)
memset(cl,0,sizeof(struct chan_list)); memset(cl,0,sizeof(struct chan_list));
cl->orginator=orig; cl->orginator=orig;
cl->need_queue_hangup=1;
cl->need_hangup=1;
return cl; return cl;
@ -2667,8 +2666,11 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
if (!strcasecmp(cfg_group, group)) { if (!strcasecmp(cfg_group, group)) {
int port_up; int port_up;
int check; int check,checkl2;
misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int)); misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
misdn_cfg_get(port, MISDN_CFG_PP_L2_CHECK, &checkl2, sizeof(int));
check=checkl2?2:check;
port_up = misdn_lib_port_up(port, check); port_up = misdn_lib_port_up(port, check);
if (check && !port_up) if (check && !port_up)
@ -2703,8 +2705,10 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port); chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
if (!strcasecmp(cfg_group, group)) { if (!strcasecmp(cfg_group, group)) {
int port_up; int port_up;
int check; int check,checkl2;
misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int)); misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
misdn_cfg_get(port, MISDN_CFG_PP_L2_CHECK, &checkl2, sizeof(int));
check=checkl2?2:check;
port_up = misdn_lib_port_up(port, check); port_up = misdn_lib_port_up(port, check);
chan_misdn_log(4, port, "portup:%d\n", port_up); chan_misdn_log(4, port, "portup:%d\n", port_up);
@ -2741,6 +2745,8 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
/* fill in the config into the objects */ /* fill in the config into the objects */
read_config(cl, ORG_AST); read_config(cl, ORG_AST);
/* important */
cl->need_hangup=0;
return tmp; return tmp;
} }
@ -2987,11 +2993,52 @@ static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
/** Channel Queue End **/ /** Channel Queue End **/
int pbx_start_chan(struct chan_list *ch)
{
int ret=ast_pbx_start(ch->ast);
if (ret>=0)
ch->need_hangup=0;
else
ch->need_hangup=1;
return ret;
}
static void hangup_chan(struct chan_list *ch)
{
if (!ch) {
cb_log(1,0,"Cannot hangup chan, no ch\n");
return;
}
if (ch->need_hangup)
{
send_cause2ast(ch->ast,ch->bc,ch);
ch->need_hangup=0;
ch->need_queue_hangup=0;
if (ch->ast)
ast_hangup(ch->ast);
return;
}
if (!ch->need_queue_hangup) {
cb_log(1,ch->bc->port,"No need to queue hangup\n");
}
ch->need_queue_hangup=0;
if (ch->ast) {
send_cause2ast(ch->ast,ch->bc,ch);
ast_queue_hangup(ch->ast);
} else {
cb_log(1,ch->bc->port,"Cannot hangup chan, no ast\n");
}
}
/** Isdn asks us to release channel, pendant to misdn_hangup **/ /** Isdn asks us to release channel, pendant to misdn_hangup **/
static void release_chan(struct misdn_bchannel *bc) { static void release_chan(struct misdn_bchannel *bc) {
struct ast_channel *ast=NULL; struct ast_channel *ast=NULL;
{ {
struct chan_list *ch=find_chan_by_bc(cl_te, bc); struct chan_list *ch=find_chan_by_bc(cl_te, bc);
if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id); if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
@ -3033,9 +3080,6 @@ static void release_chan(struct misdn_bchannel *bc) {
if (ast && MISDN_ASTERISK_TECH_PVT(ast)) { if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch)); chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
chan_misdn_log(3, bc->port, " --> * State Down\n"); chan_misdn_log(3, bc->port, " --> * State Down\n");
/* copy cause */
send_cause2ast(ast,bc,ch);
MISDN_ASTERISK_TECH_PVT(ast)=NULL; MISDN_ASTERISK_TECH_PVT(ast)=NULL;
@ -3043,55 +3087,8 @@ static void release_chan(struct misdn_bchannel *bc) {
chan_misdn_log(3, bc->port, " --> Setting AST State to down\n"); chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
ast_setstate(ast, AST_STATE_DOWN); ast_setstate(ast, AST_STATE_DOWN);
} }
switch(ch->state) {
case MISDN_EXTCANTMATCH:
case MISDN_WAITING4DIGS:
{
chan_misdn_log(3, bc->port, " --> * State Wait4dig | ExtCantMatch\n");
ast_hangup(ast);
} }
break;
case MISDN_DIALING:
case MISDN_CALLING_ACKNOWLEDGE:
case MISDN_PROGRESS:
case MISDN_PROCEEDING:
chan_misdn_log(2, bc->port, "* --> In State Dialin\n");
chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
ast_queue_hangup(ast);
break;
case MISDN_CALLING:
chan_misdn_log(2, bc->port, "* --> In State Callin\n");
if (!bc->nt) {
chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
ast_queue_hangup(ast);
} else {
chan_misdn_log(2, bc->port, "* --> Hangup\n");
ast_queue_hangup(ast);
}
break;
case MISDN_CLEANING:
/* this state comes out of ast so we mustnt call a ast function ! */
chan_misdn_log(2, bc->port, "* --> In StateCleaning\n");
break;
case MISDN_HOLD_DISCONNECT:
chan_misdn_log(2, bc->port, "* --> In HOLD_DISC\n");
break;
default:
chan_misdn_log(2, bc->port, "* --> In State Default\n");
chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
if (ast) {
ast_queue_hangup(ast);
} else {
chan_misdn_log (0, bc->port, "!! Not really queued!\n");
}
}
}
ch->state=MISDN_CLEANING; ch->state=MISDN_CLEANING;
cl_dequeue_chan(&cl_te, ch); cl_dequeue_chan(&cl_te, ch);
@ -3144,15 +3141,16 @@ static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch ,
if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio ) if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio )
chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n"); chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
else else
tone_indicate(ch,TONE_DIAL); dialtone_indicate(ch);
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)); 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); strncpy(ast->exten,"s", 2);
if (ast_pbx_start(ast)<0) { if (pbx_start_chan(ch)<0) {
ast=NULL; ast=NULL;
tone_indicate(ch,TONE_BUSY); hangup_chan(ch);
hanguptone_indicate(ch);
if (bc->nt) if (bc->nt)
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
@ -3181,6 +3179,18 @@ static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch ,
static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) { static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
if (!ast) {
chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
return;
}
if (!bc) {
chan_misdn_log(1,0,"send_cause2ast: No BC\n");
return;
}
if (!ch) {
chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
return;
}
ast->hangupcause=bc->cause; ast->hangupcause=bc->cause;
@ -3291,15 +3301,21 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
chan_misdn_log(2,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state)); chan_misdn_log(2,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
} }
if (event != EVENT_SETUP) {
if (!ch) { if (!ch) {
if (event == EVENT_RELEASE_COMPLETE) { switch(event) {
case EVENT_SETUP:
case EVENT_DISCONNECT:
break;
case EVENT_RELEASE_COMPLETE:
chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n"); chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
return 0; break;
} case EVENT_CLEANUP:
case EVENT_TONE_GENERATE:
case EVENT_BCHAN_DATA:
return -1;
if (event != EVENT_CLEANUP && event != EVENT_TONE_GENERATE && event != EVENT_BCHAN_DATA) default:
ast_log(LOG_NOTICE, "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); chan_misdn_log(1,bc->port, "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);
return -1; return -1;
} }
} }
@ -3385,7 +3401,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
int stop_tone; int stop_tone;
misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int)); misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
if ( stop_tone ) { if ( stop_tone ) {
tone_indicate(ch,TONE_NONE); stop_indicate(ch);
} }
if (ch->state == MISDN_WAITING4DIGS ) { if (ch->state == MISDN_WAITING4DIGS ) {
@ -3409,13 +3425,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
int ret;/** Sending SETUP_ACK**/ int ret;/** Sending SETUP_ACK**/
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
if (ast_pickup_call(ch->ast)) { if (ast_pickup_call(ch->ast)) {
ast_hangup(ch->ast); hangup_chan(ch);
} else { } else {
struct ast_channel *chan=ch->ast; struct ast_channel *chan=ch->ast;
ch->state = MISDN_CALLING_ACKNOWLEDGE; ch->state = MISDN_CALLING_ACKNOWLEDGE;
ch->ast=NULL;
ast_setstate(chan, AST_STATE_DOWN); ast_setstate(chan, AST_STATE_DOWN);
ast_hangup(chan); hangup_chan(ch);
ch->ast=NULL;
break; break;
} }
} }
@ -3424,7 +3440,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n"); chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
if (bc->nt) if (bc->nt)
tone_indicate(ch,TONE_BUSY); hanguptone_indicate(ch);
ch->state=MISDN_EXTCANTMATCH; ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1; bc->out_cause=1;
@ -3435,12 +3451,13 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
ch->state=MISDN_DIALING; ch->state=MISDN_DIALING;
tone_indicate(ch,TONE_NONE); stop_indicate(ch);
/* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/ /* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/
if (ast_pbx_start(ch->ast)<0) { if (pbx_start_chan(ch)<0) {
hangup_chan(ch);
chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n"); chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
if (bc->nt) tone_indicate(ch,TONE_BUSY); if (bc->nt) hanguptone_indicate(ch);
misdn_lib_send_event(bc, EVENT_DISCONNECT ); misdn_lib_send_event(bc, EVENT_DISCONNECT );
} }
@ -3568,12 +3585,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
int ret;/** Sending SETUP_ACK**/ int ret;/** Sending SETUP_ACK**/
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
if (ast_pickup_call(chan)) { if (ast_pickup_call(chan)) {
ast_hangup(chan); hangup_chan(ch);
} else { } else {
ch->state = MISDN_CALLING_ACKNOWLEDGE; ch->state = MISDN_CALLING_ACKNOWLEDGE;
ch->ast=NULL;
ast_setstate(chan, AST_STATE_DOWN); ast_setstate(chan, AST_STATE_DOWN);
ast_hangup(chan); hangup_chan(ch);
ch->ast=NULL;
break; break;
} }
} }
@ -3611,7 +3628,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n"); chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
if (bc->nt) if (bc->nt)
tone_indicate(ch,TONE_BUSY); hanguptone_indicate(ch);
ch->state=MISDN_EXTCANTMATCH; ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1; bc->out_cause=1;
@ -3634,13 +3651,14 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ret= misdn_lib_send_event(bc, EVENT_PROCEEDING ); ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
} }
if (ast_pbx_start(chan)<0) { if (pbx_start_chan(ch)<0) {
hangup_chan(ch);
chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n"); chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
chan=NULL; chan=NULL;
if (bc->nt) { if (bc->nt) {
tone_indicate(ch,TONE_BUSY); hanguptone_indicate(ch);
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
} else } else
misdn_lib_send_event(bc, EVENT_RELEASE); misdn_lib_send_event(bc, EVENT_RELEASE);
@ -3673,9 +3691,10 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
int stop_tone; int stop_tone;
misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int)); misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
tone_indicate(ch,TONE_NONE); stop_indicate(ch);
else else {
tone_indicate(ch,TONE_DIAL); dialtone_indicate(ch);
}
ch->state=MISDN_WAITING4DIGS; ch->state=MISDN_WAITING4DIGS;
} }
@ -3759,7 +3778,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
if (ch->far_alerting) { if (ch->far_alerting) {
cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself.."); cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself..");
start_bc_tones(ch); start_bc_tones(ch);
tone_indicate(ch, TONE_FAR_ALERTING); /*tone_indicate(ch, TONE_FAR_ALERTING);*/
} }
} }
} }
@ -3771,7 +3790,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
struct ast_channel *bridged=AST_BRIDGED_P(ch->ast); struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
misdn_lib_echo(bc,0); misdn_lib_echo(bc,0);
tone_indicate(ch, TONE_NONE); stop_indicate(ch);
if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) { if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged); struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
@ -3806,7 +3825,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
break; break;
case EVENT_DISCONNECT: case EVENT_DISCONNECT:
/*we might not have an ch->ast ptr here anymore*/ /*we might not have an ch->ast ptr here anymore*/
{ if (ch) {
struct chan_list *holded_ch=find_holded(cl_te, bc); struct chan_list *holded_ch=find_holded(cl_te, bc);
if (ch->ast) if (ch->ast)
@ -3836,52 +3855,39 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
} }
stop_bc_tones(ch); stop_bc_tones(ch);
bc->out_cause=-1; hangup_chan(ch);
release_chan(bc);
misdn_lib_send_event(bc,EVENT_RELEASE);
} }
bc->out_cause=-1;
if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
break; break;
case EVENT_RELEASE: 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 !!
*/
/*return RESPONSE_OK;*/
if (!bc->nt) release_chan(bc);
break;
}
bc->out_cause=16; bc->out_cause=16;
/*stop_bc_tones(ch); hangup_chan(ch);
release_chan(bc);*/ release_chan(bc);
if (!bc->nt) release_chan(bc);
if (bc->cause >= 0 && bc->need_release_complete)
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
} }
break; break;
case EVENT_RELEASE_COMPLETE: case EVENT_RELEASE_COMPLETE:
{ {
stop_bc_tones(ch); stop_bc_tones(ch);
hangup_chan(ch);
release_chan(bc); release_chan(bc);
if(ch)
ch->state=MISDN_CLEANING; ch->state=MISDN_CLEANING;
} }
break; break;
case EVENT_CLEANUP:
{
stop_bc_tones(ch);
hangup_chan(ch);
release_chan(bc);
}
break;
case EVENT_TONE_GENERATE: case EVENT_TONE_GENERATE:
{ {
@ -3958,6 +3964,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
} }
if (FD_ISSET(ch->pipe[1],&wrfs)) { if (FD_ISSET(ch->pipe[1],&wrfs)) {
chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len); int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
if (ret<=0) { if (ret<=0) {
@ -3975,7 +3982,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch)); chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
switch (ch->state) { switch (ch->state) {
case MISDN_WAITING4DIGS:
case MISDN_CALLING: case MISDN_CALLING:
case MISDN_DIALING: case MISDN_DIALING:
case MISDN_PROGRESS: case MISDN_PROGRESS:
@ -3984,13 +3990,27 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
case MISDN_CALLING_ACKNOWLEDGE: case MISDN_CALLING_ACKNOWLEDGE:
if (bc->nt) { if (bc->nt) {
bc->progress_indicator=8; bc->progress_indicator=8;
tone_indicate(ch, TONE_BUSY); hanguptone_indicate(ch);
} }
bc->out_cause=1; bc->out_cause=1;
misdn_lib_send_event(bc,EVENT_DISCONNECT); misdn_lib_send_event(bc,EVENT_DISCONNECT);
break; break;
case MISDN_WAITING4DIGS:
if (bc->nt) {
bc->progress_indicator=8;
bc->out_cause=1;
hanguptone_indicate(ch);
misdn_lib_send_event(bc,EVENT_DISCONNECT);
} else {
bc->out_cause=16;
misdn_lib_send_event(bc,EVENT_RELEASE);
}
break;
case MISDN_CLEANING: case MISDN_CLEANING:
chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n"); chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
break; break;
@ -4000,12 +4020,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
} }
} }
break; break;
case EVENT_CLEANUP:
{
stop_bc_tones(ch);
release_chan(bc);
}
break;
/***************************/ /***************************/
/** Suplementary Services **/ /** Suplementary Services **/

@ -29,6 +29,7 @@ enum misdn_cfg_elements {
MISDN_CFG_TXGAIN, /* int */ MISDN_CFG_TXGAIN, /* int */
MISDN_CFG_TE_CHOOSE_CHANNEL, /* int (bool) */ MISDN_CFG_TE_CHOOSE_CHANNEL, /* int (bool) */
MISDN_CFG_PMP_L1_CHECK, /* int (bool) */ MISDN_CFG_PMP_L1_CHECK, /* int (bool) */
MISDN_CFG_PP_L2_CHECK, /* int (bool) */
MISDN_CFG_HDLC, /* int (bool) */ MISDN_CFG_HDLC, /* int (bool) */
MISDN_CFG_CONTEXT, /* char[] */ MISDN_CFG_CONTEXT, /* char[] */
MISDN_CFG_LANGUAGE, /* char[] */ MISDN_CFG_LANGUAGE, /* char[] */

@ -418,6 +418,11 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchan
int empty_chan_in_stack(struct misdn_stack *stack, int channel) int empty_chan_in_stack(struct misdn_stack *stack, int channel)
{ {
if (channel<=0) {
cb_log(-1,stack?stack->port:0, "empty_chan_inst_stack: cannot empty channel %d\n",channel);
return -1;
}
cb_log (1, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel); cb_log (1, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel);
stack->channels[channel-1] = 0; stack->channels[channel-1] = 0;
dump_chan_list(stack); dump_chan_list(stack);
@ -814,9 +819,6 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
ncr.len = 0; ncr.len = 0;
bc->l3_id = l3_id; bc->l3_id = l3_id;
if (mypid>5000) mypid=1;
bc->pid=mypid++;
cb_log(3, stack->port, " --> new_l3id %x\n",l3_id); cb_log(3, stack->port, " --> new_l3id %x\n",l3_id);
} else { } else {
@ -847,9 +849,6 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
/* send message */ /* send message */
bc->l3_id = l3_id; bc->l3_id = l3_id;
if (mypid>5000) mypid=1;
bc->pid=mypid++;
cb_log(3, stack->port, "--> new_l3id %x\n",l3_id); cb_log(3, stack->port, "--> new_l3id %x\n",l3_id);
mISDN_write(midev, &ncr, mISDN_HEADER_LEN+ncr.len, TIMEOUT_1SEC); mISDN_write(midev, &ncr, mISDN_HEADER_LEN+ncr.len, TIMEOUT_1SEC);
@ -1466,6 +1465,7 @@ int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
case EVENT_RELEASE_COMPLETE: case EVENT_RELEASE_COMPLETE:
case EVENT_RELEASE: case EVENT_RELEASE:
if (bc->channel>0)
empty_chan_in_stack(stack,bc->channel); empty_chan_in_stack(stack,bc->channel);
empty_bc(bc); empty_bc(bc);
clean_up_bc(bc); clean_up_bc(bc);
@ -1492,9 +1492,6 @@ int handle_new_process(struct misdn_stack *stack, iframe_t *frm)
cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo); cb_log(7, stack->port, " --> new_process: New L3Id: %x\n",frm->dinfo);
bc->l3_id=frm->dinfo; bc->l3_id=frm->dinfo;
if (mypid>5000) mypid=1;
bc->pid=mypid++;
return 0; return 0;
} }
@ -1532,6 +1529,7 @@ int handle_cr ( struct misdn_stack *stack, iframe_t *frm)
if (bc) { if (bc) {
cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo); cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo);
if (bc->channel>0)
empty_chan_in_stack(stack,bc->channel); empty_chan_in_stack(stack,bc->channel);
empty_bc(bc); empty_bc(bc);
@ -1570,10 +1568,10 @@ void misdn_lib_release(struct misdn_bchannel *bc)
return; return;
} }
if (bc->channel>=0) { if (bc->channel>0) {
empty_chan_in_stack(stack,bc->channel); empty_chan_in_stack(stack,bc->channel);
empty_bc(bc);
} }
empty_bc(bc);
clean_up_bc(bc); clean_up_bc(bc);
} }
@ -1649,7 +1647,11 @@ int misdn_lib_port_up(int port, int check)
if (stack->port == port) { if (stack->port == port) {
if (stack->ptp ) { if (stack->ptp ) {
if (stack->l1link && stack->l2link) { if (stack->l1link) {
if (check==2 && !stack->l2link) {
cb_log(-1,port, "Port Down L2 (checked):%d L1:%d\n", stack->l2link, stack->l1link);
return 0;
}
return 1; return 1;
} else { } else {
cb_log(-1,port, "Port Down L2:%d L1:%d\n", cb_log(-1,port, "Port Down L2:%d L1:%d\n",
@ -1996,6 +1998,9 @@ handle_event_nt(void *dat, void *arg)
break; break;
case EVENT_RELEASE: case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE: case EVENT_RELEASE_COMPLETE:
if (bc->channel>0)
empty_chan_in_stack(stack, bc->channel);
empty_bc(bc);
clean_up_bc(bc); clean_up_bc(bc);
break; break;
@ -2526,6 +2531,7 @@ int handle_frm(msg_t *msg)
bc->out_cause=16; bc->out_cause=16;
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
if (bc->channel>0)
empty_chan_in_stack(stack, bc->channel); empty_chan_in_stack(stack, bc->channel);
empty_bc(bc); empty_bc(bc);
bc_state_change(bc,BCHAN_CLEANED); bc_state_change(bc,BCHAN_CLEANED);
@ -2947,6 +2953,25 @@ struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc)
void prepare_bc(struct misdn_bchannel*bc, int channel)
{
bc->channel = channel;
bc->channel_preselected = channel?1:0;
bc->in_use = 1;
bc->need_disconnect=1;
bc->need_release=1;
bc->need_release_complete=1;
if (++mypid>5000) mypid=1;
bc->pid=mypid;
#if 0
bc->addr=0;
bc->b_stid=0;
bc->layer_id=0;
#endif
}
struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel) struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel)
{ {
struct misdn_stack *stack; struct misdn_stack *stack;
@ -2975,9 +3000,7 @@ struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel)
} }
for (i = 0; i < stack->b_num; i++) { for (i = 0; i < stack->b_num; i++) {
if (!stack->bc[i].in_use) { if (!stack->bc[i].in_use) {
stack->bc[i].channel = channel; prepare_bc(&stack->bc[i], channel);
stack->bc[i].channel_preselected = channel?1:0;
stack->bc[i].in_use = 1;
return &stack->bc[i]; return &stack->bc[i];
} }
} }
@ -3155,6 +3178,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
misdn_split_conf(bc->holded_bc,bc->holded_bc->conf_id); misdn_split_conf(bc->holded_bc,bc->holded_bc->conf_id);
} }
if (bc->channel>0)
empty_chan_in_stack(stack,bc->channel); empty_chan_in_stack(stack,bc->channel);
empty_bc(bc); empty_bc(bc);
clean_up_bc(bc); clean_up_bc(bc);
@ -3169,10 +3193,28 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
} }
break; break;
/* finishing the channel eh ? */
case EVENT_DISCONNECT:
if (!bc->need_disconnect) {
cb_log(-1,1," --> we have already send Disconnect\n");
return -1;
}
bc->need_disconnect=0;
break;
case EVENT_RELEASE: case EVENT_RELEASE:
if (!bc->need_release) {
cb_log(-1,bc->port," --> we have already send Release\n");
return -1;
}
bc->need_release=0;
break;
case EVENT_RELEASE_COMPLETE: case EVENT_RELEASE_COMPLETE:
/*we do the cleanup in EVENT_CLEANUP*/ if (!bc->need_release_complete) {
/*clean_up_bc(bc);*/ cb_log(-1,bc->port," --> we have already send Release_complete\n");
return -1;
}
bc->need_release_complete=0;
break; break;
case EVENT_CONNECT_ACKNOWLEDGE: case EVENT_CONNECT_ACKNOWLEDGE:
@ -3948,6 +3990,7 @@ void manager_clean_bc(struct misdn_bchannel *bc )
{ {
struct misdn_stack *stack=get_stack_by_bc(bc); struct misdn_stack *stack=get_stack_by_bc(bc);
if (bc->channel>0)
empty_chan_in_stack(stack, bc->channel); empty_chan_in_stack(stack, bc->channel);
empty_bc(bc); empty_bc(bc);

@ -191,6 +191,10 @@ struct misdn_bchannel {
int layer; int layer;
/*state stuff*/
int need_disconnect;
int need_release;
int need_release_complete;
/** var stuff**/ /** var stuff**/
int l3_id; int l3_id;

@ -112,6 +112,10 @@ static const struct misdn_cfg_spec port_spec[] = {
"\tBut be aware! a broken or plugged off cable might be used for a group call\n" "\tBut be aware! a broken or plugged off cable might be used for a group call\n"
"\tas well, since chan_misdn has no chance to distinguish if the L1 is down\n" "\tas well, since chan_misdn has no chance to distinguish if the L1 is down\n"
"\tbecause of a lost Link or because the Provider shut it down..." }, "\tbecause of a lost Link or because the Provider shut it down..." },
{ "pp_l2_check", MISDN_CFG_PP_L2_CHECK, MISDN_CTYPE_BOOL, "no", NONE ,
"Some PBX's do not turn on the L2 automatically. Turn this to yes\n"
"and we'll ignore that and send out calls on that port anyways\n"
"default: no\n" },
{ "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE, { "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE,
"Set this to yes, if you want to bridge a mISDN data channel to\n" "Set this to yes, if you want to bridge a mISDN data channel to\n"
"\tanother channel type or to an application." }, "\tanother channel type or to an application." },

@ -201,6 +201,7 @@ te_choose_channel=no
; default: yes ; default: yes
; ;
pmp_l1_check=yes pmp_l1_check=yes
pp_l2_check=no
; ;
; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING), ; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),

Loading…
Cancel
Save