added an up-queue message mechanism to avoid buffer fillups in the kernel, also chang...
authorChristian Richter <christian.richter@beronet.com>
Sat, 29 Apr 2006 22:56:00 +0000 (22:56 +0000)
committerChristian Richter <christian.richter@beronet.com>
Sat, 29 Apr 2006 22:56:00 +0000 (22:56 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@23443 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_misdn.c
channels/misdn/isdn_lib.c
channels/misdn/isdn_lib_intern.h

index ae4c5ce..1b30772 100644 (file)
@@ -183,6 +183,9 @@ struct chan_list {
 
        char context[BUFFERSIZE];
 
+       int zero_read_cnt;
+       int dropped_frame_cnt;
+
        const struct tone_zone_sound *ts;
        
        struct chan_list *peer;
@@ -749,7 +752,7 @@ static int misdn_set_tics (int fd, int argc, char *argv[])
 static int misdn_show_stacks (int fd, int argc, char *argv[])
 {
        int port;
-       
+
        ast_cli(fd, "BEGIN STACK_LIST:\n");
 
        for (port=misdn_cfg_get_next_port(0); port > 0;
@@ -927,7 +930,7 @@ static char *complete_ch_helper(const char *line, const char *word, int pos, int
                c = ast_channel_walk_locked(c);
        }
        if (c) {
-               ret = strdup(c->name);
+               ret = ast_strdupa(c->name);
                ast_mutex_unlock(&c->lock);
        } else
                ret = NULL;
@@ -946,12 +949,12 @@ static char *complete_debug_port (const char *line, const char *word, int pos, i
 
        switch (pos) {
        case 4: if (*word == 'p')
-                               return strdup("port");
+                               return ast_strdupa("port");
                        else if (*word == 'o')
-                               return strdup("only");
+                               return ast_strdupa("only");
                        break;
        case 6: if (*word == 'o')
-                               return strdup("only");
+                               return ast_strdupa("only");
                        break;
        }
        return NULL;
@@ -1504,17 +1507,13 @@ static int read_config(struct chan_list *ch, int orig) {
                if ( strcmp(bc->dad,ast->exten)) {
                        ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
                }
-               if ( ast->cid.cid_num && strcmp(ast->cid.cid_num, bc->oad)) {
-                       free(ast->cid.cid_num);
-                       ast->cid.cid_num=NULL;
-                       
-               }
+               
                if ( !ast->cid.cid_num) {
-                       ast->cid.cid_num=strdup(bc->oad);
+                       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
                }
                
                if ( !ast_strlen_zero(bc->rad) ) 
-                       ast->cid.cid_rdnis=strdup(bc->rad);
+                       ast->cid.cid_rdnis=ast_strdupa(bc->rad);
        }
        return 0;
 }
@@ -2062,10 +2061,20 @@ static struct ast_frame  *misdn_read(struct ast_channel *ast)
        len = misdn_ibuf_usedcount(tmp->bc->astbuf);
 
        if (!len) {
-               chan_misdn_log(4,tmp->bc->port,"misdn_read: ZERO READ\n");
+               struct ast_frame *frame;
+               if(!tmp->zero_read_cnt)
+                       chan_misdn_log(4,tmp->bc->port,"misdn_read: ZERO READ\n");
+               tmp->zero_read_cnt++;
+
+               if (tmp->zero_read_cnt > 5000) {
+                       chan_misdn_log(4,tmp->bc->port,"misdn_read: ZERO READ counted > 5000 times\n");
+                       tmp->zero_read_cnt=0;
+
+               }
                tmp->frame.frametype = AST_FRAME_NULL;
                tmp->frame.subclass = 0;
-               return &tmp->frame;
+               frame=ast_frisolate(&tmp->frame);
+               return frame;
        }
 
        /*shrinken len if necessary, we transmit at maximum 4k*/
@@ -2154,7 +2163,16 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
                case BCHAN_BRIDGED:
                        break;
                default:
-               chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch));
+               if (!ch->dropped_frame_cnt)
+                       chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state);
+               
+               ch->dropped_frame_cnt++;
+               if (ch->dropped_frame_cnt > 100) {
+                       ch->dropped_frame_cnt=0;
+                       chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x  dropped > 100 frames!\n",frame->samples,ch->bc->addr);
+
+               }
+
                return 0;
        }
        
@@ -2264,10 +2282,6 @@ static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
     
        }
   
-       if (bridging) {
-               misdn_lib_split_bridge(ch1->bc,ch2->bc);
-       }
-  
        return 0;
 }
 
@@ -2612,10 +2626,9 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char
                        char *cid_name, *cid_num;
       
                        ast_callerid_parse(callerid, &cid_name, &cid_num);
-                       if (cid_name)
-                               tmp->cid.cid_name=strdup(cid_name);
-                       if (cid_num)
-                               tmp->cid.cid_num=strdup(cid_num);
+                       ast_set_callerid(tmp, cid_num,cid_name,cid_num);
+               } else {
+                       ast_set_callerid(tmp, NULL,NULL,NULL);
                }
 
                {
index 627ccca..824fc59 100644 (file)
@@ -802,6 +802,8 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
                free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0);
                if (!free_chan) return -1;
                bc->channel=free_chan;
+               
+               cb_log(0,stack->port, " -->  found channel: %d\n",free_chan);
     
                for (i=0; i <= MAXPROCS; i++)
                        if (stack->procids[i]==0) break;
@@ -833,6 +835,7 @@ static int create_process (int midev, struct misdn_bchannel *bc) {
                        free_chan = find_free_chan_in_stack(stack, bc->channel_preselected?bc->channel:0);
                        if (!free_chan) return -1;
                        bc->channel=free_chan;
+                       cb_log(0,stack->port, " -->  found channel: %d\n",free_chan);
                } else {
                        /* other phones could have made a call also on this port (ptmp) */
                        bc->channel=0xff;
@@ -1107,6 +1110,7 @@ struct misdn_stack* stack_init( int midev, int port, int ptp )
        stack->pri=0;
   
        msg_queue_init(&stack->downqueue);
+       msg_queue_init(&stack->upqueue);
   
        /* query port's requirements */
        ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff));
@@ -2072,11 +2076,18 @@ int handle_bchan(msg_t *msg)
                
        case MGR_SETSTACK| INDICATION:
                cb_log(2, stack->port, "BCHAN: MGR_SETSTACK|IND \n");
-               
+
+       AGAIN:
                bc->addr = mISDN_get_layerid(stack->midev, bc->b_stid, bc->layer);
                if (!bc->addr) {
-                       cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno));
 
+                       if (errno == EAGAIN) {
+                               usleep(1000);
+                               goto AGAIN;
+                       }
+                       
+                       cb_log(0,stack->port,"$$$ Get Layer (%d) Id Error: %s\n",bc->layer,strerror(errno));
+                       
                        /* we kill the channel later, when we received some
                           data. */
                        bc->addr= frm->addr;
@@ -2587,10 +2598,12 @@ msg_t *fetch_msg(int midev)
        FD_SET(midev,&rdfs);
   
        mISDN_select(FD_SETSIZE, &rdfs, NULL, NULL, NULL);
+       //select(FD_SETSIZE, &rdfs, NULL, NULL, NULL);
   
        if (FD_ISSET(midev, &rdfs)) {
-    
-               r=mISDN_read(midev,msg->data,MAX_MSG_SIZE,0);
+
+       AGAIN:
+               r=mISDN_read(midev,msg->data,MAX_MSG_SIZE, 5000);
                msg->len=r;
     
                if (r==0) {
@@ -2599,6 +2612,17 @@ msg_t *fetch_msg(int midev)
                        return NULL;
                }
 
+               if (r<0) {
+                       if (errno == EAGAIN) {
+                               /*we wait for mISDN here*/
+                               cb_log(-1,0,"mISDN_read wants us to wait\n");
+                               usleep(5000);
+                               goto AGAIN;
+                       }
+                       
+                       cb_log(-1,0,"mISDN_read returned :%d error:%s (%d)\n",r,strerror(errno),errno); 
+               }
+
                return msg;
        } else {
                printf ("Select timeout\n");
@@ -2976,6 +3000,22 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
 int handle_err(msg_t *msg)
 {
        iframe_t *frm = (iframe_t*) msg->data;
+
+
+       if (!frm->addr) {
+               static int cnt=0;
+               if (!cnt)
+                       cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x\n",frm->prim,frm->dinfo);
+               cnt++;
+               if (cnt>100) {
+                       cb_log(0,0,"mISDN Msg without Address pr:%x dinfo:%x (already more than 100 of them)\n",frm->prim,frm->dinfo);
+                       cnt=0;
+               }
+               
+               free_msg(msg);
+               return 1;
+               
+       }
        
        switch (frm->prim) {
                case DL_DATA|INDICATION:
@@ -2983,7 +3023,13 @@ int handle_err(msg_t *msg)
                        int port=(frm->addr&MASTER_ID_MASK) >> 8;
                        int channel=(frm->addr&CHILD_ID_MASK) >> 16;
 
-                       cb_log(3,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel);
+                       /*we flush the read buffer here*/
+                       
+                       cb_log(9,0,"BCHAN DATA without BC: addr:%x port:%d channel:%d\n",frm->addr, port,channel);
+                       
+                       free_msg(msg) ; 
+                       return 1;
+                       
                        
                        struct misdn_bchannel *bc=find_bc_by_channel( port , channel);
 
@@ -3015,11 +3061,28 @@ int handle_err(msg_t *msg)
 }
 
 
+int queue_l2l3(msg_t *msg) {
+       iframe_t *frm= (iframe_t*)msg->data;
+       struct misdn_stack *stack;
+       int err=0;
+
+       stack=find_stack_by_addr( frm->addr );
+
+       
+       if (!stack) {
+               return 0;
+       }
+
+       msg_queue_tail(&stack->upqueue, msg);
+       sem_post(&glob_mgr->new_msg);
+       return 1;
+}
+
 int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
 {  
 
        if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM)) {
-               printf("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
+               cb_log(0,0,"SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
        }
 
        if ( ((frm->addr | ISDN_PID_BCHANNEL_BIT )>> 28 ) == 0x5) {
@@ -3039,21 +3102,17 @@ int manager_isdn_handler(iframe_t *frm ,msg_t *msg)
        /* Its important to handle l1 AFTER l2  */
        if (handle_l1(msg)) 
                return 0 ;
-       
-       
-       /** Handle L2/3 Signalling after bchans **/ 
-       if (handle_frm_nt(msg)) 
-               return 0 ;
-       
-       if (handle_frm(msg)) 
-               return 0 ;
+
+       /* The L2/L3 will be queued */
+       if (queue_l2l3(msg))
+               return 0;
 
        if (handle_err(msg)) 
                return 0 ;
-       
+
        cb_log(-1, 0, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on this port.\n",frm->prim, frm->len, frm->addr, frm->dinfo);           
-   
        free_msg(msg);
+       
 
        return 0;
 }
@@ -3200,6 +3259,24 @@ void manager_event_handler(void *arg)
                for (stack=glob_mgr->stack_list;
                     stack;
                     stack=stack->next ) { 
+
+                       while ( (msg=msg_dequeue(&stack->upqueue)) ) {
+                               int res=0;
+                               /** Handle L2/3 Signalling after bchans **/ 
+                               if (!handle_frm_nt(msg)) {
+                                       /* Maybe it's TE */
+                                       if (!handle_frm(msg)) {
+                                               /* wow none! */
+                                               cb_log(-1,stack->port,"Wow we've got a strange issue while dequeueing a Frame\n");
+                                       }
+                               }
+                       }
+
+                       /* Here we should check if we really want to 
+                               send all the messages we've queued, lets 
+                               assume we've queued a Disconnect, but 
+                               received it already from the other side!*/
+                    
                        while ( (msg=msg_dequeue(&stack->downqueue)) ) {
                                if (stack->nt ) {
                                        if (stack->nst.manager_l3(&stack->nst, msg))
@@ -3208,6 +3285,7 @@ void manager_event_handler(void *arg)
                                } else {
                                        iframe_t *frm = (iframe_t *)msg->data;
                                        struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo);
+                                       cb_log(0,stack->port,"Sending msg, prim:%x addr:%x dinfo:%x\n",frm->prim,frm->addr,frm->dinfo);
                                        if (bc) send_msg(glob_mgr->midev, bc, msg);
                                }
                        }
index 5e9e565..8a96431 100644 (file)
@@ -74,6 +74,7 @@ struct misdn_stack {
        int procids[0x100+1];
 
        msg_queue_t downqueue;
+       msg_queue_t upqueue;
        int busy;
   
        int port;