* removed tone_indicate, we genrate only the dialtone by ourself (and the hanguptone...
authorChristian Richter <christian.richter@beronet.com>
Thu, 6 Jul 2006 15:11:40 +0000 (15:11 +0000)
committerChristian Richter <christian.richter@beronet.com>
Thu, 6 Jul 2006 15:11:40 +0000 (15:11 +0000)
* 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

channels/chan_misdn.c
channels/misdn/chan_misdn_config.h
channels/misdn/isdn_lib.c
channels/misdn/isdn_lib.h
channels/misdn_config.c
configs/misdn.conf.sample

index daf5448..e5528fa 100644 (file)
@@ -148,6 +148,9 @@ struct chan_list {
        char allowed_bearers[BUFFERSIZE+1];
        
        enum misdn_chan_state state;
+       int need_queue_hangup;
+       int need_hangup;
+       
        int holded; 
        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 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_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 tone_indicate( struct chan_list *cl, enum tone_e tone);
+static int dialtone_indicate(struct chan_list *cl);
+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 stop_bc_tones(struct chan_list *cl);
@@ -1826,7 +1833,7 @@ static int misdn_answer(struct ast_channel *ast)
        
        p->state = MISDN_CONNECTED;
        misdn_lib_echo(p->bc,0);
-       tone_indicate(p, TONE_NONE);
+       stop_indicate(p);
 
        if ( ast_strlen_zero(p->bc->cad) ) {
                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;
                if (p->state != MISDN_CONNECTED) {
+                       start_bc_tones(p);
                        misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
-                       return -1;
                } 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:
                switch (p->state) {
                        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");
                                                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);
@@ -1996,9 +1999,11 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                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);
@@ -2023,13 +2028,13 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                }
 
                if (p->bc->nt) {
-                       tone_indicate(p, TONE_BUSY);
+                       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);
                
-               tone_indicate(p, TONE_NONE);
+               stop_indicate(p);
 
                if (p->state == MISDN_CONNECTED) 
                        start_bc_tones(p);
@@ -2124,9 +2129,8 @@ static int misdn_hangup(struct ast_channel *ast)
                        break;
                case MISDN_HOLDED:
                case MISDN_DIALING:
-               case MISDN_CALLING_ACKNOWLEDGE:
                        start_bc_tones(p);
-                       tone_indicate(p, TONE_HANGUP);
+                       hanguptone_indicate(p);
                
                        if (bc->nt) {
                                misdn_lib_send_event( bc, EVENT_DISCONNECT);
@@ -2135,12 +2139,19 @@ static int misdn_hangup(struct ast_channel *ast)
                                p->state=MISDN_CLEANING;
                        }
                        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_PROGRESS:
                case MISDN_PROCEEDING:
                        if (p->orginator != ORG_AST) 
-                               tone_indicate(p, TONE_HANGUP);
+                               hanguptone_indicate(p);
       
                        /*p->state=MISDN_CLEANING;*/
                        misdn_lib_send_event( bc, EVENT_DISCONNECT);
@@ -2149,7 +2160,7 @@ static int misdn_hangup(struct ast_channel *ast)
                        /*  Alerting or Disconect */
                        if (p->bc->nt) {
                                start_bc_tones(p);
-                               tone_indicate(p, TONE_HANGUP);
+                               hanguptone_indicate(p);
                                p->bc->progress_indicator=8;
                        }
                        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;
        int len;
        
-       if (!ast) return NULL;
-       if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
-       if (!tmp->bc) return NULL;
+       if (!ast) {
+               chan_misdn_log(1,0,"misdn_read called without ast\n");
+               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));
 
@@ -2487,51 +2507,12 @@ static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
 
 /** 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;
        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");
-               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);
-       }
-       
+       chan_misdn_log(3,cl->bc->port," --> Dial\n");
+       ts=ast_get_indication_tone(ast->zone,"dial");
        cl->ts=ts;      
        
        if (ts) {
@@ -2541,13 +2522,31 @@ static int tone_indicate( struct chan_list *cl, enum tone_e tone)
                chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
                misdn_lib_tone_generator_start(cl->bc);
        }
+
+       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)
 {
-/*     manager_bchannel_activate(cl->bc); */
        misdn_lib_tone_generator_stop(cl->bc);
        cl->notxtone=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)
 {
-/*     if (cl->bc) {
-               manager_bchannel_deactivate(cl->bc);
-       }
-*/
+       if (!cl) return -1;
+
        cl->notxtone=1;
        cl->norxtone=1;
        
@@ -2579,6 +2576,8 @@ static struct chan_list *init_chan_list(int orig)
        memset(cl,0,sizeof(struct chan_list));
 
        cl->orginator=orig;
+       cl->need_queue_hangup=1;
+       cl->need_hangup=1;
        
        return cl;
        
@@ -2667,8 +2666,11 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
                                        
                                        if (!strcasecmp(cfg_group, group)) {
                                                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_PP_L2_CHECK, &checkl2, sizeof(int));
+                                               check=checkl2?2:check;
+
                                                port_up = misdn_lib_port_up(port, check);
 
                                                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);
                                if (!strcasecmp(cfg_group, group)) {
                                        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_PP_L2_CHECK, &checkl2, sizeof(int));
+                                       check=checkl2?2:check;
                                        port_up = misdn_lib_port_up(port, check);
                                        
                                        chan_misdn_log(4, port, "portup:%d\n", port_up);
@@ -2740,7 +2744,9 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
        
        /* fill in the config into the objects */
        read_config(cl, ORG_AST);
-       
+
+       /* important */
+       cl->need_hangup=0;
        
        return tmp;
 }
@@ -2987,11 +2993,52 @@ static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
 /** 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 **/
 static void release_chan(struct misdn_bchannel *bc) {
        struct ast_channel *ast=NULL;
-       
        {
                struct chan_list *ch=find_chan_by_bc(cl_te, bc);
                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)) {
                                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");
-                               /* copy cause */
-                               send_cause2ast(ast,bc,ch);
-                               
                                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");
                                        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;
                        cl_dequeue_chan(&cl_te, ch);
                        
@@ -3143,16 +3140,17 @@ static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch ,
 
        if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio ) 
                chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
-        else 
-               tone_indicate(ch,TONE_DIAL);  
+        else  
+               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));
   
        strncpy(ast->exten,"s", 2);
   
-       if (ast_pbx_start(ast)<0) {
+       if (pbx_start_chan(ch)<0) {
                ast=NULL;
-               tone_indicate(ch,TONE_BUSY);
+               hangup_chan(ch);
+               hanguptone_indicate(ch);
 
                if (bc->nt)
                        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) {
+       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;
        
@@ -3291,16 +3301,22 @@ 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));
        }
        
-       if (event != EVENT_SETUP) {
-               if (!ch) {
-                       if (event == EVENT_RELEASE_COMPLETE) {
+       if (!ch) {
+               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");
-                               return 0;
-                       }
-               
-                       if (event != EVENT_CLEANUP && event != EVENT_TONE_GENERATE && event != EVENT_BCHAN_DATA)
-                               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);
-                       return -1;
+                               break;
+                       case EVENT_CLEANUP:
+                       case EVENT_TONE_GENERATE:
+                       case EVENT_BCHAN_DATA:
+                               return -1;
+
+                       default:
+                               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;
                }
        }
        
@@ -3385,7 +3401,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                int stop_tone;
                misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
                if ( stop_tone ) {
-                       tone_indicate(ch,TONE_NONE);
+                       stop_indicate(ch);
                }
                
                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**/
                                ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
                                if (ast_pickup_call(ch->ast)) {
-                                       ast_hangup(ch->ast);
+                                       hangup_chan(ch);
                                } else {
                                        struct ast_channel *chan=ch->ast;
                                        ch->state = MISDN_CALLING_ACKNOWLEDGE;
-                                       ch->ast=NULL;
                                        ast_setstate(chan, AST_STATE_DOWN);
-                                       ast_hangup(chan);
+                                       hangup_chan(ch);
+                                       ch->ast=NULL;
                                        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");
                                if (bc->nt)
-                                       tone_indicate(ch,TONE_BUSY);
+                                       hanguptone_indicate(ch);
                                ch->state=MISDN_EXTCANTMATCH;
                                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)) {
                                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);*/
-                               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");
-                                       if (bc->nt) tone_indicate(ch,TONE_BUSY);
+                                       if (bc->nt) hanguptone_indicate(ch);
 
                                        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**/
                        ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
                        if (ast_pickup_call(chan)) {
-                               ast_hangup(chan);
+                               hangup_chan(ch);
                        } else {
                                ch->state = MISDN_CALLING_ACKNOWLEDGE;
-                               ch->ast=NULL;
                                ast_setstate(chan, AST_STATE_DOWN);
-                               ast_hangup(chan);
+                               hangup_chan(ch);
+                               ch->ast=NULL;
                                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");
 
                        if (bc->nt)
-                               tone_indicate(ch,TONE_BUSY);
+                               hanguptone_indicate(ch);
                        ch->state=MISDN_EXTCANTMATCH;
                        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 );
                        }
        
-                       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=NULL;
 
                                if (bc->nt) {
-                                       tone_indicate(ch,TONE_BUSY);
+                                       hanguptone_indicate(ch);
                                        misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
                                } else
                                        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;
                                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);
-                               else
-                                       tone_indicate(ch,TONE_DIAL);
+                                       stop_indicate(ch);
+                               else {
+                                       dialtone_indicate(ch);
+                               }
                                
                                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) {
                                cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself..");
                                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);
                
                misdn_lib_echo(bc,0);
-               tone_indicate(ch, TONE_NONE);
+               stop_indicate(ch);
 
                if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
                        struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
@@ -3806,9 +3825,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
        break;
        case EVENT_DISCONNECT:
        /*we might not have an ch->ast ptr here anymore*/
-       {
+       if (ch) {
                struct chan_list *holded_ch=find_holded(cl_te, bc);
-               
+       
                if (ch->ast)    
                        send_cause2ast(ch->ast,bc,ch);
 
@@ -3836,52 +3855,39 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                }
                
                stop_bc_tones(ch);
-               bc->out_cause=-1;
-               
-               release_chan(bc);
-               misdn_lib_send_event(bc,EVENT_RELEASE);
+               hangup_chan(ch);
        }
+       bc->out_cause=-1;
+       if (bc->need_release) 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 !!
-                               */
-                               
-                               /*return RESPONSE_OK;*/
-                               if (!bc->nt) release_chan(bc);
-
-                               break;
-                       }
-                       
-                       
                        bc->out_cause=16;
                        
-                       /*stop_bc_tones(ch);
-                         release_chan(bc);*/
-                       
-                       if (!bc->nt) release_chan(bc);
-                       
-                       misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
-
+                       hangup_chan(ch);
+                       release_chan(bc);
+               
+                       if (bc->cause >= 0 && bc->need_release_complete) 
+                               misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
                }
                break;
        case EVENT_RELEASE_COMPLETE:
        {
                stop_bc_tones(ch);
+               hangup_chan(ch);
+               release_chan(bc);
+               if(ch)  
+                       ch->state=MISDN_CLEANING;
+       }
+       break;
+       case EVENT_CLEANUP:
+       {
+               stop_bc_tones(ch);
+               hangup_chan(ch);
                release_chan(bc);
-               ch->state=MISDN_CLEANING;
        }
        break;
-
 
        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)) {
+                               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);
                                
                                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));
 
                switch (ch->state) {
-                       case MISDN_WAITING4DIGS:
                        case MISDN_CALLING:
                        case MISDN_DIALING:
                        case MISDN_PROGRESS:
@@ -3984,13 +3990,27 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        case MISDN_CALLING_ACKNOWLEDGE:
                                if (bc->nt) {
                                        bc->progress_indicator=8;
-                                       tone_indicate(ch, TONE_BUSY);
+                                       hanguptone_indicate(ch);
                                }
                                
                                bc->out_cause=1;
                                misdn_lib_send_event(bc,EVENT_DISCONNECT);
                        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: 
                                chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
                        break;
@@ -4000,12 +4020,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                        }
                }
                break;
-       case EVENT_CLEANUP:
-       {
-               stop_bc_tones(ch);
-               release_chan(bc);
-       }
-       break;
+
     
        /***************************/
        /** Suplementary Services **/
index 9f9e7ab..c05f07c 100644 (file)
@@ -29,6 +29,7 @@ enum misdn_cfg_elements {
        MISDN_CFG_TXGAIN,              /* int */
        MISDN_CFG_TE_CHOOSE_CHANNEL,   /* int (bool) */
        MISDN_CFG_PMP_L1_CHECK,        /* int (bool) */
+       MISDN_CFG_PP_L2_CHECK,        /* int (bool) */
        MISDN_CFG_HDLC,                /* int (bool) */
        MISDN_CFG_CONTEXT,             /* char[] */
        MISDN_CFG_LANGUAGE,            /* char[] */
index f45f670..5287363 100644 (file)
@@ -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)
 {
+       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); 
        stack->channels[channel-1] = 0;
        dump_chan_list(stack);
@@ -814,9 +819,6 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
                ncr.len = 0;
 
                bc->l3_id = l3_id;
-               if (mypid>5000) mypid=1;
-               bc->pid=mypid++;
-      
                cb_log(3, stack->port, " --> new_l3id %x\n",l3_id);
     
        } else { 
@@ -847,9 +849,6 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
                /* send message */
 
                bc->l3_id = l3_id;
-               if (mypid>5000) mypid=1;
-               bc->pid=mypid++;
-    
                cb_log(3, stack->port, "--> new_l3id %x\n",l3_id);
     
                mISDN_write(midev, &ncr, mISDN_HEADER_LEN+ncr.len, TIMEOUT_1SEC);
@@ -1466,7 +1465,8 @@ int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
 
                case EVENT_RELEASE_COMPLETE:
                case EVENT_RELEASE:
-                       empty_chan_in_stack(stack,bc->channel);
+                       if (bc->channel>0)
+                               empty_chan_in_stack(stack,bc->channel);
                        empty_bc(bc);
                        clean_up_bc(bc);
                        break;
@@ -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);
        bc->l3_id=frm->dinfo;
-       
-       if (mypid>5000) mypid=1;
-       bc->pid=mypid++;
        return 0;
 }
 
@@ -1532,7 +1529,8 @@ int handle_cr ( struct misdn_stack *stack, iframe_t *frm)
       
                        if (bc) {
                                cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo);
-                               empty_chan_in_stack(stack,bc->channel);
+                               if (bc->channel>0)
+                                       empty_chan_in_stack(stack,bc->channel);
                                empty_bc(bc);
                                
                                clean_up_bc(bc);
@@ -1570,10 +1568,10 @@ void misdn_lib_release(struct misdn_bchannel *bc)
                return;
        }
        
-       if (bc->channel>=0) {
+       if (bc->channel>0) {
                empty_chan_in_stack(stack,bc->channel);
-               empty_bc(bc);
        }
+       empty_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->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;
                                } else {
                                        cb_log(-1,port, "Port Down L2:%d L1:%d\n",
@@ -1996,6 +1998,9 @@ handle_event_nt(void *dat, void *arg)
                                        break;
                                case EVENT_RELEASE:
                                case EVENT_RELEASE_COMPLETE:
+                                       if (bc->channel>0)
+                                               empty_chan_in_stack(stack, bc->channel);
+                                       empty_bc(bc);
                                        clean_up_bc(bc);
                                        break;
 
@@ -2526,7 +2531,8 @@ int handle_frm(msg_t *msg)
 
                                        bc->out_cause=16;
                                        misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
-                                       empty_chan_in_stack(stack, bc->channel);
+                                       if (bc->channel>0)
+                                               empty_chan_in_stack(stack, bc->channel);
                                        empty_bc(bc);
                                        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_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++) {
                                if (!stack->bc[i].in_use) {
-                                       stack->bc[i].channel = channel;
-                                       stack->bc[i].channel_preselected = channel?1:0;
-                                       stack->bc[i].in_use = 1;
+                                       prepare_bc(&stack->bc[i], channel);
                                        return &stack->bc[i];
                                }
                        }
@@ -3155,7 +3178,8 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
                                misdn_split_conf(bc->holded_bc,bc->holded_bc->conf_id);
                        }
 
-                       empty_chan_in_stack(stack,bc->channel);
+                       if (bc->channel>0)
+                               empty_chan_in_stack(stack,bc->channel);
                        empty_bc(bc);
                        clean_up_bc(bc);
                }
@@ -3168,11 +3192,29 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
                cb_event( EVENT_NEW_BC, holded_bc, glob_mgr->user_data);
        }
        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:
+               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:
-               /*we do the cleanup in EVENT_CLEANUP*/
-               /*clean_up_bc(bc);*/
+               if (!bc->need_release_complete) {
+                       cb_log(-1,bc->port," --> we have already send Release_complete\n");
+                       return -1;
+               }
+               bc->need_release_complete=0;
                break;
     
        case EVENT_CONNECT_ACKNOWLEDGE:
@@ -3948,7 +3990,8 @@ void manager_clean_bc(struct misdn_bchannel *bc )
 {
        struct misdn_stack *stack=get_stack_by_bc(bc);
        
-       empty_chan_in_stack(stack, bc->channel);
+       if (bc->channel>0)
+               empty_chan_in_stack(stack, bc->channel);
        empty_bc(bc);
   
        misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
index f544a61..5e93b3d 100644 (file)
@@ -191,7 +191,11 @@ struct misdn_bchannel {
        
        int layer;
        
-       
+       /*state stuff*/
+       int need_disconnect;
+       int need_release;
+       int need_release_complete;
+
        /** var stuff**/
        int l3_id;
        int pid;
index 02b1025..124f5c7 100644 (file)
@@ -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"
                "\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..." },
+       { "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,
                "Set this to yes, if you want to bridge a mISDN data channel to\n"
                "\tanother channel type or to an application." },
index 03df166..2c86b43 100644 (file)
@@ -201,6 +201,7 @@ te_choose_channel=no
 ; default: yes
 ;
 pmp_l1_check=yes
+pp_l2_check=no
 
 ;
 ; Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),