lcr work (soon done :)
authorSuper User <root@isdn.jolly.ten>
Sun, 18 May 2008 17:04:35 +0000 (19:04 +0200)
committerSuper User <root@isdn.jolly.ten>
Sun, 18 May 2008 17:04:35 +0000 (19:04 +0200)
modified:   Makefile
modified:   bchannel.c
modified:   chan_lcr.c
modified:   chan_lcr.h
modified:   dss1.cpp
modified:   todo.txt

Makefile
bchannel.c
chan_lcr.c
chan_lcr.h
dss1.cpp
todo.txt

index 254448c..0f8a0e9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@
 #*****************************************************************************/ 
 
 WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used
-#WITH-ASTERISK = 42 # comment this out, if you don't require built-in Asterisk channel driver.
+WITH-ASTERISK = 42 # comment this out, if you don't require built-in Asterisk channel driver.
 WITH-SOCKET = 42 # compile for socket based mISDN (this options is far unfinished !!!)
 # note: check your location and the names of libraries.
 
index 42831d8..7e2db3b 100644 (file)
@@ -42,9 +42,6 @@
 #define ISDN_PID_L4_B_USER 0x440000ff
 #endif
 
-#define PERROR(arg...) fprintf(stderr, ##arg)
-#define PDEBUG(arg...) while(0)
-
 pid_t  bchannel_pid;
 
 enum {
@@ -79,11 +76,11 @@ int bchannel_initialize(void)
                ret = mISDN_open();
                if (ret < 0)
                {
-                       PERROR("cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
+                       CERROR("cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
                        return(-1);
                }
                bchannel_device = ret;
-               PDEBUG("mISDN device opened.\n");
+               CDEBUG("mISDN device opened.\n");
 
                /* create entity for layer 3 TE-mode */
                mISDN_write_frame(bchannel_device, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
@@ -91,7 +88,7 @@ int bchannel_initialize(void)
                if (ret < (int)mISDN_HEADER_LEN)
                {
                        noentity:
-                       PERROR("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
+                       CERROR("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
                        return(-1);
                }
                bchannel_entity = frm->dinfo & 0xffff;
@@ -133,7 +130,7 @@ static void ph_control(unsigned long handle, unsigned long c1, unsigned long c2,
        *d++ = c2;
        ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
        if (!ret)
-               PERROR("Failed to send to socket %d\n", handle);
+               CERROR("Failed to send to socket %d\n", handle);
 #else
        unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
        iframe_t *ctrl = (iframe_t *)buffer; 
@@ -171,7 +168,7 @@ static void ph_control_block(unsigned long handle, unsigned long c1, void *c2, i
        memcpy(d, c2, c2_len);
        ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
        if (!ret)
-               PERROR("Failed to send to socket %d\n", handle);
+               CERROR("Failed to send to socket %d\n", handle);
 #else
        unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
        iframe_t *ctrl = (iframe_t *)buffer;
@@ -206,7 +203,7 @@ int bchannel_create(struct bchannel *bchannel)
 
        if (bchannel->b_sock)
        {
-               PERROR("Error: Socket already created for handle 0x%x\n", bchannel->handle);
+               CERROR("Error: Socket already created for handle 0x%x\n", bchannel->handle);
                return(0);
        }
 
@@ -217,7 +214,7 @@ int bchannel_create(struct bchannel *bchannel)
        channel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
        if (bchannel->b_sock < 0)
        {
-               PERROR("Error: Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
+               CERROR("Error: Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
                return(0);
        }
        
@@ -225,7 +222,7 @@ int bchannel_create(struct bchannel *bchannel)
        ret = ioctl(bchannel->b_sock, FIONBIO, &on);
        if (ret < 0)
        {
-               PERROR("Error: Failed to set bchannel-socket handle 0x%x into nonblocking IO\n", bchannel->handle);
+               CERROR("Error: Failed to set bchannel-socket handle 0x%x into nonblocking IO\n", bchannel->handle);
                close(bchannel->b_sock);
                channel->b_sock = -1;
                return(0);
@@ -238,7 +235,7 @@ int bchannel_create(struct bchannel *bchannel)
        ret = bind(bchannel->b_sock, (struct sockaddr *)&addr, sizeof(addr));
        if (ret < 0)
        {
-               PERROR("Error: Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
+               CERROR("Error: Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
                close(bchannel->b_sock);
                channel->b_sock = -1;
                return(0);
@@ -256,18 +253,18 @@ int bchannel_create(struct bchannel *bchannel)
 
        if (bchannel->b_stid)
        {
-               PERROR("Error: stack already created for address 0x%lx\n", bchannel->b_stid);
+               CERROR("Error: stack already created for address 0x%lx\n", bchannel->b_stid);
                return(0);
        }
 
        if (bchannel->b_addr)
        {
-               PERROR("Error: stack already created for address 0x%lx\n", bchannel->b_addr);
+               CERROR("Error: stack already created for address 0x%lx\n", bchannel->b_addr);
                return(0);
        }
 
        /* create new layer */
-       PDEBUG("creating new layer for stid 0x%lx.\n" , bchannel->handle);
+       CDEBUG("creating new layer for stid 0x%lx.\n" , bchannel->handle);
        memset(&li, 0, sizeof(li));
        memset(&pid, 0, sizeof(pid));
        li.object_id = -1;
@@ -280,7 +277,7 @@ int bchannel_create(struct bchannel *bchannel)
        if (ret)
        {
                failed_new_layer:
-               PERROR("mISDN_new_layer() failed to add bchannel for stid 0x%lx.\n", bchannel->handle);
+               CERROR("mISDN_new_layer() failed to add bchannel for stid 0x%lx.\n", bchannel->handle);
                goto failed;
        }
        if (!li.id)
@@ -289,7 +286,7 @@ int bchannel_create(struct bchannel *bchannel)
        }
        bchannel->b_stid = bchannel->handle;
        bchannel->b_addr = li.id;
-       PDEBUG("new layer (b_addr=0x%x)\n", bchannel->b_addr);
+       CDEBUG("new layer (b_addr=0x%x)\n", bchannel->b_addr);
 
        /* create new stack */
        pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
@@ -301,7 +298,7 @@ int bchannel_create(struct bchannel *bchannel)
        if (ret)
        {
                stack_error:
-               PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%lx\n", ret, bchannel->b_stid);
+               CERROR("mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%lx\n", ret, bchannel->b_stid);
                mISDN_write_frame(bchannel_device, buff, bchannel->b_addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
                goto failed;
        }
@@ -344,7 +341,7 @@ void bchannel_activate(struct bchannel *bchannel, int activate)
        act.id = 0;
        ret = sendto(bchannel->b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
        if (!ret)
-               PERROR("Failed to send to socket %d\n", bchannel->b_sock);
+               CERROR("Failed to send to socket %d\n", bchannel->b_sock);
 #else
        iframe_t act;
 
@@ -444,7 +441,7 @@ static void bchannel_destroy(struct bchannel *bchannel)
        /* remove our stack only if set */
        if (bchannel->b_addr)
        {
-               PDEBUG("free stack (b_addr=0x%x)\n", bchannel->b_addr);
+               CDEBUG("free stack (b_addr=0x%x)\n", bchannel->b_addr);
                mISDN_clear_stack(bchannel_device, bchannel->b_stid);
                mISDN_write_frame(bchannel_device, buff, bchannel->b_addr | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
                bchannel->b_stid = 0;
@@ -470,7 +467,7 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
        {
                if (len < 4)
                {
-                       PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
+                       CERROR("SHORT READ OF PH_CONTROL INDICATION\n");
                        return;
                }
                if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
@@ -521,7 +518,7 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
                        if (!bchannel->b_txdata)
                        {
                                /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
-                               PDEBUG("PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
+                               CDEBUG("PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
                                return;
                        }
                        break;
@@ -539,7 +536,7 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
        }
        if (prim != PH_DATA_IND && prim != DL_DATA_IND)
        {
-               PERROR("Bchannel received unknown primitve: 0x%lx\n", prim);
+               CERROR("Bchannel received unknown primitve: 0x%lx\n", prim);
                return;
        }
        /* calls will not process any audio data unless
@@ -549,19 +546,19 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
        /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
        if (bchannel->b_rxoff)
        {
-               PDEBUG("PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
+               CDEBUG("PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
                return;
        }
 
        if (!bchannel->call)
        {
-               PDEBUG("PmISDN(%s) ignoring data, because no call associated with bchannel\n", p_name);
+               CDEBUG("PmISDN(%s) ignoring data, because no call associated with bchannel\n", p_name);
                return;
        }
        len = write(bchannel->call->pipe[1], data, len);
        if (len < 0)
        {
-               PDEBUG("PmISDN(%s) broken pipe on bchannel pipe\n", p_name);
+               CDEBUG("PmISDN(%s) broken pipe on bchannel pipe\n", p_name);
                return;
        }
 }
@@ -582,7 +579,7 @@ void bchannel_transmit(struct bchannel *bchannel, unsigned char *data, int len)
        frm->id = 0;
        ret = sendto(bchannel->b_sock, data, len, 0, NULL, 0);
        if (!ret)
-               PERROR("Failed to send to socket %d\n", bchannel->b_sock);
+               CERROR("Failed to send to socket %d\n", bchannel->b_sock);
 #else
        frm->prim = DL_DATA | REQUEST; 
        frm->addr = bchannel->b_addr | FLG_MSG_DOWN;
@@ -665,7 +662,7 @@ int bchannel_handle(void)
                                        case DL_ESTABLISH_IND:
                                        case PH_ACTIVATE_CONF:
                                        case DL_ESTABLISH_CONF:
-                                       PDEBUG("DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", bchannel->b_sock);
+                                       CDEBUG("DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", bchannel->b_sock);
                                        bchannel_activated(bchannel);
                                        break;
 
@@ -673,17 +670,17 @@ int bchannel_handle(void)
                                        case DL_RELEASE_IND:
                                        case PH_DEACTIVATE_CONF:
                                        case DL_RELEASE_CONF:
-                                       PDEBUG("DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", bchannel->b_sock);
+                                       CDEBUG("DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", bchannel->b_sock);
 //                                     bchannel_deactivated(bchannel);
                                        break;
 
                                        default:
-                                       PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, bchannel->b_sock, msg->len);
+                                       CERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, bchannel->b_sock, msg->len);
                                }
                        } else
                        {
                                if (ret < 0 && errno != EWOULDBLOCK)
-                                       PERROR("Read from socket %d failed with return code %d\n", bchannel->b_sock, ret);
+                                       CERROR("Read from socket %d failed with return code %d\n", bchannel->b_sock, ret);
                        }
                }
                bchannel = bchannel->next;
@@ -710,7 +707,7 @@ int bchannel_handle(void)
        {
                if (errno == EAGAIN)
                        return(0);
-               PERROR("Failed to do mISDN_read()\n");
+               CERROR("Failed to do mISDN_read()\n");
                return(0);
        }
        if (!len)
@@ -741,7 +738,7 @@ int bchannel_handle(void)
        } 
        if (!bchannel)
        {
-               PERROR("message belongs to no bchannel: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
+               CERROR("message belongs to no bchannel: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
                goto out;
        }
 
@@ -765,7 +762,7 @@ int bchannel_handle(void)
                case DL_ESTABLISH | INDICATION:
                case PH_ACTIVATE | CONFIRM:
                case DL_ESTABLISH | CONFIRM:
-               PDEBUG( "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
+               CDEBUG( "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
                bchannel_activated(bchannel);
                break;
 
@@ -773,12 +770,12 @@ int bchannel_handle(void)
                case DL_RELEASE | INDICATION:
                case PH_DEACTIVATE | CONFIRM:
                case DL_RELEASE | CONFIRM:
-               PDEBUG("DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
+               CDEBUG("DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
 //             bchannel_deactivated(bchannel);
                break;
 
                default:
-               PERROR("message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
+               CERROR("message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
        }
 
        out:
index f33d917..18cbec7 100644 (file)
@@ -79,13 +79,6 @@ If the ref is 0 and the state is CHAN_LCR_STATE_RELEASE, see the proceedure
 
 */
 
-u_char flip_bits[256];
-
-#warning TODO: bchannel oeffnen und aktivieren (wer macht das?:)
-#warning reconnect after socket closed, release all calls.
-#warning debug of call handling
-#warning ausloesen beim socket-verlust
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -131,13 +124,16 @@ u_char flip_bits[256];
 
 CHAN_LCR_STATE // state description structure
 
+u_char flip_bits[256];
+
 int lcr_debug=1;
 int mISDN_created=1;
 
 char lcr_type[]="lcr";
 
 pthread_t chan_tid;
-ast_mutex_t chan_lock;
+ast_mutex_t chan_lock; /* global lock */
+ast_mutex_t log_lock; /* logging log */
 int quit;
 
 int glob_channel = 0;
@@ -152,6 +148,34 @@ struct admin_list {
 static struct ast_channel_tech lcr_tech;
 
 /*
+ * logging
+ */
+void chan_lcr_log(int type, struct chan_call *call, struct ast_channel *ast, const char *fmt, ...)
+{
+       char buffer[1024];
+       char call_text[128] = "NULL";
+       char ast_text[128] = "NULL";
+       va_list args;
+
+       ast_mutex_lock(&log_lock);
+
+       va_start(args,fmt);
+       vsnprintf(buffer,sizeof(buffer)-1,fmt,args);
+       buffer[sizeof(buffer)-1]=0;
+       va_end(args);
+
+       if (call)
+               sprintf(call_text, "%ld", call->ref);
+       if (ast)
+               strncpy(ast_text, ast->name, sizeof(ast_text)-1);
+       ast_text[sizeof(ast_text)-1] = '\0';
+       
+       ast_log(type, "[call=%s ast=%s] %s", call_text, ast_text, buffer);
+
+       ast_mutex_unlock(&log_lock);
+}
+
+/*
  * channel and call instances
  */
 struct chan_call *call_first;
@@ -197,24 +221,6 @@ struct chan_call *find_call_handle(unsigned long handle)
 }
 #endif
 
-struct chan_call *alloc_call(void)
-{
-       struct chan_call **callp = &call_first;
-
-       while(*callp)
-               callp = &((*callp)->next);
-
-       *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
-       if (*callp)
-               memset(*callp, 0, sizeof(struct chan_call));
-       if (pipe((*callp)->pipe) < 0) {
-               free_call(*callp);
-               return;
-       }
-       return(*callp);
-}
-
-
 void free_call(struct chan_call *call)
 {
        struct chan_call **temp = &call_first;
@@ -230,25 +236,45 @@ void free_call(struct chan_call *call)
                                close(call->pipe[1]);
                        if (call->bchannel)
                        {
-                               if (call->bchannel->call)
-                                       call->bchannel->call = NULL;
-                               else
-                                       warnung
+                               if (call->bchannel->call != call)
+                                       CERROR(call, NULL, "Linked bchannel structure has no link to us.\n");
+                               call->bchannel->call = NULL;
                        }
                        if (call->bridge_call)
                        {
-                               if (call->bridge_call->bridge_call)
-                                       call->bridge_call->bridge_call = NULL;
-                               else
-                                       warnung
+                               if (call->bridge_call->bridge_call != call)
+                                       CERROR(call, NULL, "Linked call structure has no link to us.\n");
+                               call->bridge_call->bridge_call = NULL;
                        }
+                       CDEBUG(call, NULL, "Call instance freed.\n");
                        free(call);
                        return;
                }
                temp = &((*temp)->next);
        }
+       CERROR(call, NULL, "Call instance not found in list.\n");
 }
 
+struct chan_call *alloc_call(void)
+{
+       struct chan_call **callp = &call_first;
+
+       while(*callp)
+               callp = &((*callp)->next);
+
+       *callp = (struct chan_call *)malloc(sizeof(struct chan_call));
+       if (*callp)
+               memset(*callp, 0, sizeof(struct chan_call));
+       if (pipe((*callp)->pipe) < 0) {
+               CERROR(*callp, NULL, "Failed to create pipe.\n");
+               free_call(*callp);
+               return(NULL);
+       }
+       CDEBUG(*callp, NULL, "Call instance allocated.\n");
+       return(*callp);
+}
+
+
 unsigned short new_bridge_id(void)
 {
        struct chan_call *call;
@@ -268,28 +294,24 @@ unsigned short new_bridge_id(void)
                        break;
                id++;
        }
+       CDEBUG(NULL, NULL, "New bridge ID %d.\n", id);
        return(id);
 }
 
 
 /*
- * receive bchannel data
- */
-void rx_data(struct bchannel *bchannel, unsigned char *data, int len)
-{
-}
-
-void rx_dtmf(struct bchannel *bchannel, char tone)
-{
-}
-
-/*
  * enque message to LCR
  */
 int send_message(int message_type, unsigned long ref, union parameter *param)
 {
        struct admin_list *admin, **adminp;
 
+       if (lcr_sock < 0) {
+               CDEBUG(NULL, NULL, "Ignoring message %d, because socket is closed.\n", message_type);
+               return -1;
+       }
+       CDEBUG(NULL, NULL, "Sending message %d to socket.\n", message_type);
+
        adminp = &admin_first;
        while(*adminp)
                adminp = &((*adminp)->next);
@@ -315,6 +337,8 @@ static void send_setup_to_lcr(struct chan_call *call)
        if (!call->ast || !call->ref)
                return;
 
+       CDEBUG(call, call->ast, "Sending setup to LCR.\n");
+
        /* send setup message to LCR */
        memset(&newparam, 0, sizeof(union parameter));
                newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;      
@@ -381,6 +405,8 @@ static void send_dialque_to_lcr(struct chan_call *call)
        if (!call->ast || !call->ref || !call->dialque)
                return;
        
+       CDEBUG(call, call->ast, "Sending dial queue to LCR.\n");
+
        /* send setup message to LCR */
        memset(&newparam, 0, sizeof(union parameter));
        strncpy(newparam.information.id, call->dialque, sizeof(newparam.information.id)-1);
@@ -397,6 +423,7 @@ static void bridge_message_if_bridged(struct chan_call *call, int message_type,
        /* check bridge */
        if (!call) return;
        if (!call->bridge_call) return;
+       CDEBUG(call, NULL, "Sending message due briding.\n");
        send_message(message_type, call->bridge_call->ref, param);
 }
 
@@ -405,22 +432,25 @@ static void bridge_message_if_bridged(struct chan_call *call, int message_type,
  * if it can match, proceed
  * if not, release
  */
-static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int complete)
+static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int complete)
 {
        int cause;
 
        if (complete)
        {
                /* if not match */
-               if (!ast_canmatch_extension(ast, ast->context, call->dad, 1, call->oad))
+               if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, call->oad))
                {
+                       CDEBUG(call, ast, "Got 'sending complete', but extension '%s' will not match at context '%s' - releasing.\n", ast->exten, ast->context);
                        cause = 1;
                        goto release;
-               if (!ast_exists_extension(ast, ast->context, call->dad, 1, call->oad))
+               if (!ast_exists_extension(ast, ast->context, ast->exten, 1, call->oad))
                {
+                       CDEBUG(call, ast, "Got 'sending complete', but extension '%s' would match at context '%s', if more digits would be dialed - releasing.\n", ast->exten, ast->context);
                        cause = 28;
                        goto release;
                }
+               CDEBUG(call, ast, "Got 'sending complete', extensions matches.\n");
                /* send setup acknowledge to lcr */
                memset(&newparam, 0, sizeof(union parameter));
                send_message(MESSAGE_PROCEEDING, call->ref, &newparam);
@@ -441,10 +471,13 @@ static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int c
                call->state = CHAN_LCR_STATE_IN_DIALING;
 
                /* if match, start pbx */
-               if (ast_exists_extension(ast, ast->context, dad, 1, oad))
+               if (ast_exists_extension(ast, ast->context, dad, 1, oad)) {
+                       CDEBUG(call, ast, "Extensions matches.\n");
                        goto start;
+               }
 
                /* if can match */
+               CDEBUG(call, ast, "Extensions may match, if more digits are dialed.\n");
                return;
        }
 
@@ -452,6 +485,7 @@ static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int c
        cause = 1;
        release:
        /* release lcr */
+       CDEBUG(call, ast, "Releasing due to extension missmatch.\n");
        memset(&newparam, 0, sizeof(union parameter));
        newparam.disconnectinfo.cause = cause;
        newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -459,13 +493,14 @@ static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int c
        call->ref = 0;
        /* release asterisk */
        ast->hangupcause = call->cause;
-       ast_queue_hangup(ast);
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
+       ast_hangup(ast); // call will be destroyed here
        return;
        
        start:
        /* send setup to asterisk */
+       CDEBUG(call, ast, "Starting call to Asterisk due to matching extension.\n");
        ret = ast_pbx_start(ast);
        if (ret < 0)
        {
@@ -484,11 +519,14 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
        struct ast_channel *ast;
        union parameter newparam;
 
+       CDEBUG(call, NULL, "Incomming setup from LCR. (callerid %d, dialing %d)\n", param->setup.callerinfo.id, param->setup.dialinginfo.id);
+
        /* create asterisk channel instrance */
        ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
        if (!ast)
        {
                /* release */
+               CERROR(call, NULL, "Failed to create Asterisk channel - releasing.\n");
                memset(&newparam, 0, sizeof(union parameter));
                newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
                newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
@@ -543,8 +581,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
                        ast->cid.cid_ton = 0;
        }
        ast->transfercapability = param->setup.capainfo.bearer_capa;
-       strcpy(call->dad, param->setup.dialinginfo.id);
-       strcpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter));
+       strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter), sizeof(call->oad)-1);
 
        /* configure channel */
 #warning todo
@@ -568,6 +605,8 @@ static void lcr_in_overlap(struct chan_call *call, int message_type, union param
 {
        if (!call->ast) return;
 
+       CDEBUG(call, call->ast, "Incomming setup acknowledge from LCR.\n");
+
        /* send pending digits in dialque */
        if (call->dialque)
                send_dialque_to_lcr(call);
@@ -580,10 +619,12 @@ static void lcr_in_overlap(struct chan_call *call, int message_type, union param
  */
 static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param)
 {
+       CDEBUG(call, call->ast, "Incomming proceeding from LCR.\n");
+
        /* change state */
        call->state = CHAN_LCR_STATE_OUT_PROCEEDING;
        /* send event to asterisk */
-       if (call->ast)
+       if (call->ast && call->pbx_started)
                ast_queue_control(call->ast, AST_CONTROL_PROCEEDING);
 }
 
@@ -592,10 +633,12 @@ static void lcr_in_proceeding(struct chan_call *call, int message_type, union pa
  */
 static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param)
 {
+       CDEBUG(call, call->ast, "Incomming alerting from LCR.\n");
+
        /* change state */
        call->state = CHAN_LCR_STATE_OUT_ALERTING;
        /* send event to asterisk */
-       if (call->ast)
+       if (call->ast && call->pbx_started)
                ast_queue_control(call->ast, AST_CONTROL_RINGING);
 }
 
@@ -604,12 +647,14 @@ static void lcr_in_alerting(struct chan_call *call, int message_type, union para
  */
 static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param)
 {
+       CDEBUG(call, call->ast, "Incomming connect (answer) from LCR.\n");
+
        /* change state */
        call->state = CHAN_LCR_STATE_CONNECT;
        /* copy connectinfo */
        memcpy(&call->connectinfo, &param->connectinfo, sizeof(struct connect_info));
        /* send event to asterisk */
-       if (call->ast)
+       if (call->ast && call->pbx_started)
                ast_queue_control(call->ast, AST_CONTROL_ANSWER);
 }
 
@@ -621,30 +666,38 @@ static void lcr_in_disconnect(struct chan_call *call, int message_type, union pa
        struct ast_channel *ast = call->ast;
        union parameter newparam;
 
+       CDEBUG(call, call->ast, "Incomming disconnect from LCR. (cause=%d)\n", param.disconnectinfo.cause);
+
        /* change state */
        call->state = CHAN_LCR_STATE_IN_DISCONNECT;
        /* save cause */
        call->cause = param->disconnectinfo.cause;
        call->location = param->disconnectinfo.location;
-per option
-
-wenn setup raus geht, pointer 
        /* if bridge, forward disconnect and return */
+#ifdef TODO
+       feature flag
        if (call->bridge_call)
        {
+               CDEBUG(call, call->ast, "Only signal disconnect via bridge.\n");
                bridge_message_if_bridged(call, message_type, param);
                return;
        }
-       /* release lcr */
-       newparam.disconnectinfo.cause = CAUSE_NORMAL;
-       newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-       send_message(MESSAGE_RELEASE, call->ref, &newparam);
+#endif
+       /* release lcr with same cause */
+       send_message(MESSAGE_RELEASE, call->ref, param);
        call->ref = 0;
-       /* release asterisk */
-       ast->hangupcause = call->cause;
-       ast_queue_hangup(ast);
        /* change to release state */
        call->state = CHAN_LCR_STATE_RELEASE;
+       /* release asterisk */
+       if (ast)
+       {
+               ast->hangupcause = call->cause;
+               if (call->pbx_started)
+                       ast_queue_hangup(ast);
+               else {
+                       ast_hangup(ast); // call will be destroyed here
+               }
+       }
 }
 
 /*
@@ -654,6 +707,8 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param
 {
        struct ast_channel *ast = call->ast;
 
+       CDEBUG(call, call->ast, "Incomming release from LCR. (cause=%d)\n", param.disconnectinfo.cause);
+
        /* release ref */
        call->ref = 0;
        /* change to release state */
@@ -668,7 +723,11 @@ static void lcr_in_release(struct chan_call *call, int message_type, union param
        if (ast)
        {
                ast->hangupcause = call->cause;
-               ast_queue_hangup(ast);
+               if (call->pbx_started)
+                       ast_queue_hangup(ast);
+               else {
+                       ast_hangup(ast); // call will be destroyed here
+               }
        } else
        {
                free_call(call);
@@ -684,11 +743,14 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
        struct ast_frame fr;
        char *p;
 
+       CDEBUG(call, call->ast, "Incomming information from LCR. (dialing=%d)\n", param.information.id);
+       
        if (!call->ast) return;
 
        /* pbx not started */
        if (!call->pbx_started)
        {
+               CDEBUG(call, call->ast, "Asterisk not started, adding digits to number.\n");
                strncat(ast->exten, param->information.id, AST_MAX_EXTENSION-1);
                lcr_start_pbx(call, ast, param->information.complete);
                return;
@@ -698,6 +760,7 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
        p = param->information.id;
        if (call->state == CHAN_LCR_STATE_IN_DIALING && *p)
        {
+               CDEBUG(call, call->ast, "Asterisk is started, sending DTMF frame.\n");
                while (*p)
                {
                        /* send digit to asterisk */
@@ -710,8 +773,10 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
                }
        }
        /* use bridge to forware message not supported by asterisk */
-       if (call->state == CHAN_LCR_STATE_CONNECT)
+       if (call->state == CHAN_LCR_STATE_CONNECT) {
+               CDEBUG(call, call->ast, "Call is connected, briding.\n");
                bridge_message_if_bridged(call, message_type, param);
+       }
 }
 
 /*
@@ -719,6 +784,8 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
  */
 static void lcr_in_notify(struct chan_call *call, int message_type, union parameter *param)
 {
+       CDEBUG(call, call->ast, "Incomming notify from LCR. (notify=%d)\n", param.notifyinfo.notify);
+
        if (!call->ast) return;
 
        /* use bridge to forware message not supported by asterisk */
@@ -730,6 +797,8 @@ static void lcr_in_notify(struct chan_call *call, int message_type, union parame
  */
 static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param)
 {
+       CDEBUG(call, call->ast, "Incomming facility from LCR.\n");
+
        if (!call->ast) return;
 
        /* use bridge to forware message not supported by asterisk */
@@ -753,16 +822,17 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
                switch(param->bchannel.type)
                {
                        case BCHANNEL_ASSIGN:
+                       CDEBUG(NULL, NULL "Received BCHANNEL_ASSIGN message. (handle=%08lx)\n", param->bchannel.handle);
                        if ((bchannel = find_bchannel_handle(param->bchannel.handle)))
                        {
-                               fprintf(stderr, "error: bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
+                               CERROR(NULL, NULL, "bchannel handle %x already assigned.\n", (int)param->bchannel.handle);
                                return(-1);
                        }
                        /* create bchannel */
                        bchannel = alloc_bchannel(param->bchannel.handle);
                        if (!bchannel)
                        {
-                               fprintf(stderr, "error: alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
+                               CERROR(NULL, NULL, "alloc bchannel handle %x failed.\n", (int)param->bchannel.handle);
                                return(-1);
                        }
 
@@ -788,8 +858,10 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
                                bchannel->call = call;
                                call->bchannel = bchannel;
 #warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren
-                               if (call->bridge_id)
+                               if (call->bridge_id) {
+                                       CDEBUG(call, call->ast, "Join bchannel, because call is already bridged.\n");
                                        bchannel_join(bchannel, call->bridge_id);
+                               }
                        }
                        if (bchannel_create(bchannel))
                                bchannel_activate(bchannel, 1);
@@ -801,10 +873,10 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
                        break;
 
                        case BCHANNEL_REMOVE:
+                       CDEBUG(NULL, NULL, "Received BCHANNEL_REMOVE message. (handle=%08lx)\n", param->bchannel.handle);
                        if (!(bchannel = find_bchannel_handle(param->bchannel.handle)))
                        {
-                               #warning alle fprintf nach ast_log
-                               fprintf(stderr, "error: bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
+                               CERROR(NULL, NULL, "Bchannel handle %x not assigned.\n", (int)param->bchannel.handle);
                                return(-1);
                        }
                        /* unklink from call and destroy bchannel */
@@ -818,7 +890,7 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
                        break;
 
                        default:
-                       fprintf(stderr, "received unknown bchannel message %d\n", param->bchannel.type);
+                       CDEBUG(NULL, NULL, "Received unknown bchannel message %d.\n", param->bchannel.type);
                }
                return(0);
        }
@@ -829,9 +901,10 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
                if (param->direction)
                {
                        /* new ref from lcr */
+                       CDEBUG(NULL, NULL, "Received new ref by LCR, of call from LCR. (ref=%ld)\n", ref);
                        if (!ref || find_call_ref(ref))
                        {
-                               fprintf(stderr, "illegal new ref %ld received\n", ref);
+                               CERROR(NULL, NULL, "Illegal new ref %ld received.\n", ref);
                                return(-1);
                        }
                        /* allocate new call instance */
@@ -844,10 +917,12 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
                } else
                {
                        /* new ref, as requested from this remote application */
+                       CDEBUG(NULL, NULL, "Received new ref by LCR, as requested from chan_lcr. (ref=%ld)\n", ref);
                        call = find_call_ref(0);
                        if (!call)
                        {
                                /* send release, if ref does not exist */
+                               CDEBUG(NULL, NULL, "No call found, that requests a ref.\n");
                                newparam.disconnectinfo.cause = CAUSE_NORMAL;
                                newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                                send_message(MESSAGE_RELEASE, ref, &newparam);
@@ -883,7 +958,7 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
        /* check ref */
        if (!ref)
        {
-               fprintf(stderr, "received message %d without ref\n", message_type);
+               CERROR(NULL, NULL, "Received message %d without ref.\n", message_type);
                return(-1);
        }
        call = find_call_ref(ref);
@@ -955,6 +1030,43 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
        return(0);
 }
 
+/*
+ * release all calls (due to broken socket)
+ */
+static void release_all_calls(void)
+{
+       struct chan_call *call;
+
+again:
+       call = call_first;
+       while(call)
+       {
+               /* no ast, so we may directly free call */
+               if (!call->ast) {
+                       CDEBUG(call, NULL, "Freeing call, because no Asterisk channel is linked.\n");
+                       free_call(call);
+                       goto again;
+               }
+               /* already in release process */
+               if (call->state == CHAN_LCR_STATE_RELEASE) {
+                       call = call->next;
+                       continue;
+               }
+               /* release or queue release */
+               call->ref = 0;
+               call->state = CHAN_LCR_STATE_RELEASE;
+               if (!call->pbx_started)
+               {
+                       CDEBUG(call, call->ast, "Releasing call, because no Asterisk channel is not started.\n");
+                       ast_hangup(call->ast); // call will be destroyed here
+                       goto again;
+               }
+               CDEBUG(call, call->ast, "Queue call release, because Asterisk channel is running.\n");
+               ast_queue_hangup(call->ast);
+               call = call->next;
+       }
+}
+
 
 /* asterisk handler
  * warning! not thread safe
@@ -974,29 +1086,28 @@ int handle_socket(void)
        len = read(sock, &msg, sizeof(msg));
        if (len == 0)
        {
-               printf("Socket closed\n");
+               CERROR(NULL, NULL, "Socket closed.\n");
                return(-1); // socket closed
        }
        if (len > 0)
        {
                if (len != sizeof(msg))
                {
-                       fprintf(stderr, "Socket short read (%d)\n", len);
+                       CERROR(NULL, NULL, "Socket short read. (len %d)\n", len);
                        return(-1); // socket error
                }
                if (msg.message != ADMIN_MESSAGE)
                {
-                       fprintf(stderr, "Socket received illegal message %d\n", msg.message);
+                       CERROR(NULL, NULL, "Socket received illegal message %d.\n", msg.message);
                        return(-1); // socket error
                }
                receive_message(msg.u.msg.type, msg.u.msg.ref, &msg.u.msg.param);
-               printf("message received %d\n", msg.u.msg.type);
                work = 1;
        } else
        {
                if (errno != EWOULDBLOCK)
                {
-                       fprintf(stderr, "Socket error %d\n", errno);
+                       CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
                        return(-1);
                }
        }
@@ -1008,14 +1119,14 @@ int handle_socket(void)
        len = write(sock, &admin->msg, sizeof(msg));
        if (len == 0)
        {
-               printf("Socket closed\n");
+               CERROR(NULL, NULL, "Socket closed.\n");
                return(-1); // socket closed
        }
        if (len > 0)
        {
                if (len != sizeof(msg))
                {
-                       fprintf(stderr, "Socket short write (%d)\n", len);
+                       CERROR(NULL, NULL, "Socket short write. (len %d)\n", len);
                        return(-1); // socket error
                }
                /* free head */
@@ -1027,7 +1138,7 @@ int handle_socket(void)
        {
                if (errno != EWOULDBLOCK)
                {
-                       fprintf(stderr, "Socket error %d\n", errno);
+                       CERROR(NULL, NULL, "Socket failed (errno %d).\n", errno);
                        return(-1);
                }
        }
@@ -1051,7 +1162,7 @@ int open_socket(void)
        /* open socket */
        if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        {
-               ast_log(LOG_ERROR, "Failed to create socket.\n");
+               CERROR(NULL, NULL, "Failed to create socket.\n");
                return(sock);
        }
 
@@ -1064,7 +1175,7 @@ int open_socket(void)
        if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
        {
                close(sock);
-               ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path);
+               CERROR(NULL, NULL, "Failed to connect to socket '%s'. Is LCR running?\n", sock_address.sun_path);
                return(conn);
        }
 
@@ -1072,7 +1183,7 @@ int open_socket(void)
        if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0)
        {
                close(sock);
-               ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n");
+               CERROR(NULL, NULL, "Failed to set socket into non-blocking IO.\n");
                return(ret);
        }
 
@@ -1095,32 +1206,58 @@ static void *chan_thread(void *arg)
 {
        int work;
        int ret;
+       union parameter param;
+       time_t retry = 0, now;
+
+       bchannel_pid = getpid();
+       
+       memset(&param, 0, sizeof(union parameter));
+       if (lcr_sock > 0)
+               time(&retry);
 
        ast_mutex_lock(&chan_lock);
 
-       while(!quit)
-       {
+       while(!quit) {
                work = 0;
 
-               /* handle socket */
-               ret = handle_socket();
-               if (ret < 0)
-                       break;
-               if (ret)
-                       work = 1;
+               if (lcr_sock > 0) {
+                       /* handle socket */
+                       ret = handle_socket();
+                       if (ret < 0) {
+                               CERROR(NULL, NULL, "Handling of socket failed - closing for some seconds.\n");
+                               close_socket(lcr_sock);
+                               lcr_sock = -1;
+                               release_all_calls();
+                               time(&retry);
+                       }
+                       if (ret)
+                               work = 1;
+               } else {
+                       time(&now);
+                       if (retry && now-retry > 5) {
+                               CERROR(NULL, NULL, "Retry to open socket.\n");
+                               retry = 0;
+                               if (!(lcr_sock = open_socket())) {
+                                       time(&retry);
+                               }
+                               work = 1;
+                       }
+                                       
+               }
 
                /* handle mISDN */
                ret = bchannel_handle();
                if (ret)
                        work = 1;
                
-               if (!work)
-               {
+               if (!work) {
                        ast_mutex_unlock(&chan_lock);
                        usleep(30000);
                        ast_mutex_lock(&chan_lock);
                }
        }
+
+       CERROR(NULL, NULL, "Thread exit.\n");
        
        ast_mutex_unlock(&chan_lock);
 
@@ -1138,6 +1275,15 @@ static struct ast_channel *lcr_request(const char *type, int format, void *data,
 
        ast_mutex_lock(&chan_lock);
 
+       CDEBUG(NULL, NULL, "Received request from Asterisk.\n");
+
+       /* if socket is closed */
+       if (lcr_sock < 0)
+       {
+               CERROR(NULL, NULL, "Rejecting call from Asterisk, because LCR not running.\n");
+               return NULL;
+       }
+       
        /* create call instance */
        call = alloc_call();
        if (!call)
@@ -1149,6 +1295,7 @@ static struct ast_channel *lcr_request(const char *type, int format, void *data,
        ast = ast_channel_alloc(1, AST_STATE_RESERVED, NULL, NULL, "", NULL, "", 0, "%s/%d", lcr_type, ++glob_channel);
        if (!ast)
        {
+               CERROR(NULL, NULL, "Failed to create Asterisk channel.\n");
                free_call(call);
                /* failed to create instance */
                return NULL;
@@ -1189,26 +1336,19 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
         if (!call) {
+               CERROR(NULL, ast, "Received call from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
 
+       CDEBUG(call, ast, "Received call from Asterisk.\n");
 
-#warning       hier muss noch
-#if 0
-        ast_copy_string(buf, dest, sizeof(buf)-1);
-        p=buf;
-        port_str=strsep(&p, "/");
-        dad=strsep(&p, "/");
-#endif
+       call->pbx_started = 1;
 
        /* send setup message, if we already have a callref */
        if (call->ref)
                send_setup_to_lcr(call);
 
-//        if (lcr_debug)
-  //              ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad);
-
        ast_mutex_unlock(&chan_lock);
        return 0; 
 }
@@ -1226,13 +1366,17 @@ static int lcr_digit(struct ast_channel *ast, char digit)
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
         if (!call) {
+               CERROR(NULL, ast, "Received digit from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
 
+       CDEBUG(call, ast, "Received digit Asterisk.\n");
+
        /* send information or queue them */
        if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
        {
+               CDEBUG(call, ast, "Sending digit to LCR, because we are in dialing state.\n");
                memset(&newparam, 0, sizeof(union parameter));
                newparam.information.id[0] = digit;
                newparam.information.id[1] = '\0';
@@ -1241,6 +1385,7 @@ static int lcr_digit(struct ast_channel *ast, char digit)
        if (!call->ref
         && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
        {
+               CDEBUG(call, ast, "Queue digits, because we are in setup/dialing state and have no ref yet.\n");
                *buf = digit;
                strncat(call->dialque, buf, strlen(call->dialque)-1);
        }
@@ -1258,10 +1403,13 @@ static int lcr_answer(struct ast_channel *ast)
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
         if (!call) {
+               CERROR(NULL, ast, "Received answer from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
        
+       CDEBUG(call, ast, "Received answer from Asterisk.\n");
+               
        /* copy connectinfo, if bridged */
        if (call->bridge_call)
                memcpy(&call->connectinfo, &call->bridge_call->connectinfo, sizeof(struct connect_info));
@@ -1280,27 +1428,38 @@ static int lcr_hangup(struct ast_channel *ast)
 {
        union parameter newparam;
         struct chan_call *call;
+       pthread_t tid = pthread_self();
 
-       ast_mutex_lock(&chan_lock);
+       if (!pthread_equal(tid, call_tid))
+               ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
         if (!call) {
-               ast_mutex_unlock(&chan_lock);
+               CERROR(NULL, ast, "Received hangup from Asterisk, but no call instance exists.\n");
+               if (!pthread_equal(tid, call_tid))
+                       ast_mutex_unlock(&chan_lock);
                return -1;
        }
 
+       if (!pthread_equal(tid, call_tid))
+               CDEBUG(call, ast, "Received hangup from Asterisk thread.\n");
+       else
+               CDEBUG(call, ast, "Received hangup from LCR thread.\n");
+
        /* disconnect asterisk, maybe not required */
        ast->tech_pvt = NULL;
        ast->fds[0] = -1;
        if (call->ref)
        {
                /* release */
+               CDEBUG(call, ast, "Releasing ref and freeing call instance.\n");
                memset(&newparam, 0, sizeof(union parameter));
                newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL;
                newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                send_message(MESSAGE_RELEASE, call->ref, &newparam);
                /* remove call */
                free_call(call);
-               ast_mutex_unlock(&chan_lock);
+               if (!pthread_equal(tid, call_tid))
+                       ast_mutex_unlock(&chan_lock);
                return 0;
        } else
        {
@@ -1308,14 +1467,17 @@ static int lcr_hangup(struct ast_channel *ast)
                if (call->state == CHAN_LCR_STATE_RELEASE)
                {
                        /* we get the response to our release */
+                       CDEBUG(call, ast, "Freeing call instance, because we have no ref AND we are requesting no ref.\n");
                        free_call(call);
                } else
                {
                        /* during prepare, we change to release state */
+                       CDEBUG(call, ast, "We must wait until we received our ref, until we can free call instance.\n");
                        call->state = CHAN_LCR_STATE_RELEASE;
                }
        } 
-       ast_mutex_unlock(&chan_lock);
+       if (!pthread_equal(tid, call_tid))
+               ast_mutex_unlock(&chan_lock);
        return 0;
 }
 
@@ -1367,7 +1529,9 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
        }
 
        call->read_fr.frametype = AST_FRAME_SPEECH;
-#warning todo
+#ifdef TODO
+       format aus config
+#endif
        call->read_fr.subtype = AST_FORMAT_ALAW;
        call->read_fr.datalen = len;
        call->read_fr.samples = len;
@@ -1387,12 +1551,14 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
         if (!call) {
+               CERROR(NULL, ast, "Received indicate from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
 
         switch (cond) {
                 case AST_CONTROL_BUSY:
+                       CDEBUG(call, ast, "Received indicate AST_CONTROL_BUSY from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
                        newparam.disconnectinfo.cause = 17;
@@ -1404,10 +1570,12 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                        ast_mutex_unlock(&chan_lock);
                         return 0;
                 case AST_CONTROL_CONGESTION:
+                       CDEBUG(call, ast, "Received indicate AST_CONTROL_CONGESTION from Asterisk.\n");
                        /* return */
                        ast_mutex_unlock(&chan_lock);
                         return -1;
                 case AST_CONTROL_RINGING:
+                       CDEBUG(call, ast, "Received indicate AST_CONTROL_RINGING from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
                        send_message(MESSAGE_ALERTING, call->ref, &newparam);
@@ -1425,12 +1593,14 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                         res = -1;
                         break;
                 case AST_CONTROL_HOLD:
+                       CDEBUG(call, ast, "Received indicate AST_CONTROL_HOLD from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
                        newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
                        send_message(MESSAGE_NOTIFY, call->ref, &newparam);
                         break;
                 case AST_CONTROL_UNHOLD:
+                       CDEBUG(call, ast, "Received indicate AST_CONTROL_UNHOLD from Asterisk.\n");
                        /* send message to lcr */
                        memset(&newparam, 0, sizeof(union parameter));
                        newparam.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
@@ -1438,7 +1608,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                         break;
 
                 default:
-                        ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, ast->name);
+                       CERROR(call, ast, "Received indicate from Asterisk with unknown condition %d.\n", cond);
                        /* return */
                        ast_mutex_unlock(&chan_lock);
                         return -1;
@@ -1463,7 +1633,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
        int                     to = -1;
        struct ast_frame        *f;
        int                     bridge_id;
+
+       CDEBUG(NULL, ast, "Received briding request from Asterisk.\n");
+       
        /* join via dsp (if the channels are currently open) */
        ast_mutex_lock(&chan_lock);
        bridge_id = new_bridge_id();
@@ -1489,7 +1661,7 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
                who = ast_waitfor_n(carr, 2, &to);
 
                if (!who) {
-                       ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
+                       CDEBUG(NULL, ast, "Empty read on bridge, breaking out.\n");
                        break;
                }
                f = ast_read(who);
@@ -1524,6 +1696,8 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
     
        }
        
+       CDEBUG(NULL, ast, "Releasing bride.\n");
+
        /* split channels */
        ast_mutex_lock(&chan_lock);
        call1 = ast1->tech_pvt;
@@ -1554,7 +1728,9 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
 static struct ast_channel_tech lcr_tech = {
        .type=lcr_type,
        .description="Channel driver for connecting to Linux-Call-Router",
-#warning todo
+#ifdef TODO
+       law from config
+#endif
        .capabilities=AST_FORMAT_ALAW,
        .requester=lcr_request,
        .send_digit_begin=lcr_digit,
@@ -1671,22 +1847,21 @@ int load_module(void)
                          || = (i<<7) | ((i&2)<<5) | ((i&4)<<3) | ((i&8)<<1);
 
        ast_mutex_init(&chan_lock);
+       ast_mutex_init(&log_lock);
        
        if (!(lcr_sock = open_socket())) {
-               ast_log(LOG_ERROR, "Unable to connect\n");
-               lcr_sock = -1;
                /* continue with closed socket */
        }
 
        if (!bchannel_initialize()) {
-               ast_log(LOG_ERROR, "Unable to open mISDN device\n");
+               CERROR(NULL, NULL, "Unable to open mISDN device\n");
                close_socket(lcr_sock);
                return -1;
        }
        mISDN_created = 1;
 
        if (ast_channel_register(&lcr_tech)) {
-               ast_log(LOG_ERROR, "Unable to register channel class\n");
+               CERROR(NULL, NULL, "Unable to register channel class\n");
                bchannel_deinitialize();
                close_socket(lcr_sock);
                return -1;
@@ -1721,12 +1896,11 @@ int load_module(void)
        
        lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
 
-       chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
 =======
        //lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
 #endif
 
-       quit = 1;       
+       quit = 0;       
        if ((pthread_create(&chan_tid, NULL, chan_thread, NULL)<0))
        {
                /* failed to create thread */
@@ -1741,7 +1915,7 @@ int load_module(void)
 int unload_module(void)
 {
        /* First, take us out of the channel loop */
-       ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
+       CDEBUG(NULL, NULL, "-- Unregistering mISDN Channel Driver --\n");
 
        quit = 1;
        pthread_join(chan_tid, NULL);   
@@ -1767,7 +1941,8 @@ static int reload_module(void)
        return 0;
 }
 
-
+#ifdef TODO
+mutex init fehlt noch
 ast_mutex_t usecnt_lock;
 int usecnt;
 
@@ -1779,6 +1954,7 @@ int usecount(void)
        ast_mutex_unlock(&usecnt_lock);
        return res;
 }
+#endif
 
 
 char *desc="Channel driver for lcr";
index 87a493f..2388800 100644 (file)
@@ -16,6 +16,8 @@ struct chan_call {
        int                     state;  /* current call state CHAN_LCR_STATE */
        unsigned long           ref;    /* callref for this channel */
        void                    *ast;   /* current asterisk channel */
+       int                     pbx_started;
+                                       /* indicates if pbx que is available */
        struct bchannel         *bchannel;
                                        /* reference to bchannel, if set */
        int                     cause, location;
@@ -28,6 +30,8 @@ struct chan_call {
                                        /* current ID or 0 */
        struct chan_call        *bridge_call;
                                        /* remote instance or NULL */
+       int                     pipe[2];
+                                       /* pipe for receive data */
 };
 
 enum {
@@ -82,3 +86,7 @@ enum {
 };
 
 
+#define CERROR(call, ast, arg...) chan_lcr_log(LOG_ERROR, call, ast, ##arg)
+#define CDEBUG(call, ast, arg...) chan_lcr_log(LOG_DEBUG, call, ast, ##arg)
+void chan_lcr_log(int type, struct chan_call *call, struct ast_channel *ast, const char *fmt, ...);
+
index 2df2645..d99954b 100644 (file)
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -1319,8 +1319,6 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
        dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause);
 #endif
        end_trace();
-       if (location == LOCATION_PRIVATE_LOCAL)
-               location = LOCATION_PRIVATE_REMOTE;
 
        if (cause < 0)
                cause = 16;
@@ -1343,9 +1341,9 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
 #endif
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_REQ, DIRECTION_OUT);
 #ifdef SOCKET_MISDN
-               enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); /* normal */
+               enc_ie_cause(l3m, location, cause); /* normal */
 #else
-               enc_ie_cause(&release->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); /* normal */
+               enc_ie_cause(&release->CAUSE, dmsg, location, cause); /* normal */
 #endif
                add_trace("reason", NULL, "no remote patterns");
                end_trace();
@@ -1356,6 +1354,8 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
 #endif
 
                /* sending release to endpoint */
+               if (location == LOCATION_PRIVATE_LOCAL)
+                       location = LOCATION_PRIVATE_REMOTE;
                while(p_epointlist)
                {
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -1371,6 +1371,8 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
        }
 
        /* sending disconnect to active endpoint and release to inactive endpoints */
+       if (location == LOCATION_PRIVATE_LOCAL)
+               location = LOCATION_PRIVATE_REMOTE;
        if (ACTIVE_EPOINT(p_epointlist))
        {
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
@@ -1446,50 +1448,36 @@ void Pdss1::release_ind(unsigned long prim, unsigned long dinfo, void *data)
        dec_ie_cause(release->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause);
 #endif
        end_trace();
-       if (location == LOCATION_PRIVATE_LOCAL)
-               location = LOCATION_PRIVATE_REMOTE;
 
        if (cause < 0)
                cause = 16;
 
-       /* sending release to endpoint */
-       while(p_epointlist)
-       {
-               message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = cause;
-               message->param.disconnectinfo.location = location;
-               message_put(message);
-               /* remove epoint */
-               free_epointlist(p_epointlist);
-       }
-
+#ifndef SOCKET_MISDN
        /* only in NT mode we must send release_complete, if we got a release confirm */
-#ifdef SOCKET_MISDN
-       if (cmd == MT_RELEASE)
-#else
        if (prim == (CC_RELEASE | CONFIRM))
-#endif
        {
                /* sending release complete */
-#ifdef SOCKET_MISDN
-               l3m = create_l3msg();
-#else
                RELEASE_COMPLETE_t *release_complete;
                dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, dinfo, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode);
                release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen);
-#endif
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_REQ, DIRECTION_OUT);
-#ifdef SOCKET_MISDN
-               enc_ie_cause(l3m, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16);
-#else
-               enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16);
-#endif
+               enc_ie_cause(&release_complete->CAUSE, dmsg, location, cause);
                end_trace();
-#ifdef SOCKET_MISDN
-               p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_RELEASE_COMPLETE, p_m_d_l3id, l3m);
-#else
                msg_queue_tail(&p_m_mISDNport->downqueue, dmsg);
+       }
 #endif
+
+       /* sending release to endpoint */
+       if (location == LOCATION_PRIVATE_LOCAL)
+               location = LOCATION_PRIVATE_REMOTE;
+       while(p_epointlist)
+       {
+               message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = cause;
+               message->param.disconnectinfo.location = location;
+               message_put(message);
+               /* remove epoint */
+               free_epointlist(p_epointlist);
        }
 
        new_state(PORT_STATE_RELEASE);
@@ -3577,8 +3565,7 @@ if (/*     ||*/ p_state==PORT_STATE_OUT_SETUP)
                while(p_epointlist)
                {
                        message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-                       message->param.disconnectinfo.cause = 16;
-                       message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+                       memcpy(&message->param, param, sizeof(union parameter));
                        message_put(message);
                        /* remove epoint */
                        free_epointlist(p_epointlist);
@@ -3593,9 +3580,9 @@ if (/*     ||*/ p_state==PORT_STATE_OUT_SETUP)
                l1l2l3_trace_header(p_m_mISDNport, this, L3_RELEASE_COMPLETE_REQ, DIRECTION_OUT);
                /* send cause */
 #ifdef SOCKET_MISDN
-               enc_ie_cause(l3m, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+               enc_ie_cause(l3m, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
 #else
-               enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+               enc_ie_cause(&release_complete->CAUSE, dmsg, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
 #endif
                end_trace();
 #ifdef SOCKET_MISDN
@@ -3664,9 +3651,9 @@ if (/*     ||*/ p_state==PORT_STATE_OUT_SETUP)
 #endif
        /* send cause */
 #ifdef SOCKET_MISDN
-       enc_ie_cause(l3m, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+       enc_ie_cause(l3m, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
 #else
-       enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
+       enc_ie_cause(&disconnect->CAUSE, dmsg, (!p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_REMOTE:param->disconnectinfo.location, param->disconnectinfo.cause);
 #endif
        /* send display */
        if (param->disconnectinfo.display[0])
index 2ebe280..b3e5041 100644 (file)
--- a/todo.txt
+++ b/todo.txt
@@ -1,19 +1,8 @@
-socket-test:
-
-- testswitches und karte einbauen
-- call-aufbau ohne bchannel
-- call-aufbau mit bchannel
-- dsp
-- hfc-multi
-- call nach extern
-- l1oip
-
 
 chan_lcr:
 
 - das cli
-- bchannel handling
-- config gile
+- config file
 - einbau von b-channel-features