work on chan_lcr: bridging works, interface selection possible
authorSuper User <root@isdn.jolly.ten>
Fri, 6 Jun 2008 13:18:59 +0000 (15:18 +0200)
committerSuper User <root@isdn.jolly.ten>
Fri, 6 Jun 2008 13:18:59 +0000 (15:18 +0200)
modified:   Makefile
modified:   apppbx.cpp
modified:   apppbx.h
modified:   bchannel.c
modified:   bchannel.h
modified:   chan_lcr.c
modified:   chan_lcr.h
modified:   dss1.cpp
modified:   genext.c
modified:   joinremote.cpp
modified:   joinremote.h
modified:   mISDN.cpp
modified:   mISDN.h
modified:   macro.h
modified:   main.c
modified:   message.h
modified:   options.c
modified:   options.h
modified:   socket_server.c

19 files changed:
Makefile
apppbx.cpp
apppbx.h
bchannel.c
bchannel.h
chan_lcr.c
chan_lcr.h
dss1.cpp
genext.c
joinremote.cpp
joinremote.h
mISDN.cpp
mISDN.h
macro.h
main.c
message.h
options.c
options.h
socket_server.c

index 53f43c2..ce4b9fb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -74,7 +74,9 @@ message.o: message.c *.h Makefile
        $(PP) -c $(CFLAGS) message.c -o message.o
 
 options.o: options.c *.h Makefile
-       $(PP) -c $(CFLAGS) options.c -o options.o
+       $(CC) -c $(CFLAGS) options.c -o options.o
+options.ooo: options.c *.h Makefile
+       $(PP) -c $(CFLAGS) options.c -o options.ooo
 
 interface.o: interface.c *.h Makefile
        $(PP) -c $(CFLAGS) interface.c -o interface.o
@@ -168,7 +170,7 @@ bchannel.o: bchannel.c *.h Makefile
 #      -o $(WIZZARD) 
 
 $(LCR): main.o \
-       options.o \
+       options.ooo \
        interface.o \
        extension.o \
        cause.o \
@@ -196,7 +198,7 @@ $(LCR): main.o \
        trace.o
        $(PP) $(LIBDIR) \
                main.o \
-       options.o \
+       options.ooo \
        interface.o \
        extension.o \
        cause.o \
@@ -228,8 +230,8 @@ $(LCRADMIN): lcradmin.c cause.c *.h Makefile
        $(PP) $(LIBDIR) $(CFLAGS_LCRADMIN) $(CURSES) -lm lcradmin.c cause.c \
        -o $(LCRADMIN) 
 
-$(CHAN_LCR): chan_lcr.o bchannel.o callerid.o *.h Makefile
-       $(CC) -shared -Xlinker -x $(LDFLAGS) -o $(CHAN_LCR) chan_lcr.o bchannel.o callerid.o
+$(CHAN_LCR): chan_lcr.o bchannel.o callerid.o options.o *.h Makefile
+       $(CC) -shared -Xlinker -x $(LDFLAGS) -o $(CHAN_LCR) chan_lcr.o bchannel.o callerid.o options.o
 
 
 $(LCRWATCH): watch.c *.h Makefile
@@ -248,8 +250,8 @@ $(GENRC): genrc.c *.h Makefile
        $(PP) $(LIBDIR) $(CFLAGS) -lm genrc.c \
        -o $(GENRC) 
 
-$(GENEXT): options.o extension.o genext.o
-       $(PP) $(CFLAGS) options.o extension.o genext.o -o $(GENEXT) 
+$(GENEXT): options.ooo extension.o genext.o
+       $(PP) $(CFLAGS) options.ooo extension.o genext.o -o $(GENEXT) 
 
 #install:
 #      @echo Remember, this is a beta release. To overwrite your current installed
index 981c867..6304848 100644 (file)
@@ -73,6 +73,7 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp
         e_dtmf = 0;
         e_dtmf_time = 0;
         e_dtmf_last = 0;
+       e_enablekeypad = 0;
        e_cfnr_release = 0;
        e_cfnr_call = 0;
        e_password_timeout = 0;
@@ -238,6 +239,7 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                        e_dtmf = 0;
                        e_dtmf_time = 0;
                        e_dtmf_last = 0;
+                       e_enablekeypad = 0;
                        e_cfnr_release = 0;
                        e_cfnr_call = 0;
                        e_multipoint_cause = 0;
@@ -1476,7 +1478,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
        memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
        memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
        memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
-       e_dtmf = param->setup.dtmf;
+//     e_dtmf = param->setup.dtmf;
        /* screen incoming caller id */
        interface = interface_first;
        while(interface)
@@ -1666,7 +1668,7 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
        /* keypad when connected */
        if (e_state == EPOINT_STATE_CONNECT)
        {
-               if (e_ext.keypad)
+               if (e_ext.keypad || e_enablekeypad)
                {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
                        /* processing keypad function */
@@ -1947,6 +1949,9 @@ void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type,
 
        /* signal to call tool */
        admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
+//#warning hack!!
+//     if (e_adminid)
+//             set_tone(portlist, "hold");
 
        new_state(EPOINT_STATE_OUT_ALERTING);
        /* check if pattern is available */
@@ -2957,8 +2962,10 @@ void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type,
 
        new_state(EPOINT_STATE_CONNECT);
 //                     UCPY(e_join_tone, "");
+//                     
        if (e_ext.number[0])
                e_dtmf = 1; /* allow dtmf */
+
        e_powerdialing = 0;
        memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_callerinfo));
        if(portlist)
@@ -3503,6 +3510,15 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_notify(portlist, message_type, param);
                break;
 
+               /* JOIN wants keypad / dtml */
+               case MESSAGE_ENABLEKEYPAD:
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received keypad enable request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               e_enablekeypad = 1;
+               e_dtmf = 1;
+               trace_header("ENABLE KEYPAD", DIRECTION_NONE);
+               end_trace();
+               break;
+
                default:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
        }
@@ -3682,7 +3698,8 @@ reject:
 
        /* connnecting our endpoint */
        new_state(EPOINT_STATE_CONNECT);
-       e_dtmf = 1;
+       if (e_ext.number[0])
+               e_dtmf = 1;
        set_tone(ea_endpoint->ep_portlist, NULL);
 
        /* now we send a release to the ringing endpoint */
index 4afb1e8..d9c9638 100644 (file)
--- a/apppbx.h
+++ b/apppbx.h
@@ -127,6 +127,7 @@ class EndpointAppPBX : public EndpointApp
        /* read doc/keypad.txt for more information */
        int e_dtmf_time;                        /* time when the last key was received. */
        int e_dtmf_last;                        /* last dtmf key */
+       int e_enablekeypad;                     /* remote app requests dtmf */
 
        /* transmit and receive state */
        int e_tx_state;                         /* current endpoint's state */
index 3db3bc5..9d7db44 100644 (file)
@@ -70,7 +70,7 @@ static void ph_control(unsigned long handle, unsigned long c1, unsigned long c2,
        unsigned long *d = (unsigned long *)(buffer+MISDN_HEADER_LEN);
        int ret;
 
-       CDEBUG(NULL, NULL, "Sending PH_CONTROL %d,%d\n", c1, c2);
+       CDEBUG(NULL, NULL, "Sending PH_CONTROL %s %x,%x\n", trace_name, c1, c2);
        ctrl->prim = PH_CONTROL_REQ;
        ctrl->id = 0;
        *d++ = c1;
@@ -78,14 +78,6 @@ static void ph_control(unsigned long handle, unsigned long c1, unsigned long c2,
        ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
        if (ret < 0)
                CERROR(NULL, NULL, "Failed to send to socket %d\n", handle);
-#if 0
-       chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
-       if (c1 == CMX_CONF_JOIN)
-               add_trace(trace_name, NULL, "0x%08x", trace_value);
-       else
-               add_trace(trace_name, NULL, "%d", trace_value);
-       end_trace();
-#endif
 }
 
 static void ph_control_block(unsigned long handle, unsigned long c1, void *c2, int c2_len, char *trace_name, int trace_value)
@@ -95,7 +87,7 @@ static void ph_control_block(unsigned long handle, unsigned long c1, void *c2, i
        unsigned long *d = (unsigned long *)(buffer+MISDN_HEADER_LEN);
        int ret;
 
-       CDEBUG(NULL, NULL, "Sending PH_CONTROL (block) %d\n", c1);
+       CDEBUG(NULL, NULL, "Sending PH_CONTROL (block) %s %x\n", trace_name, c1);
        ctrl->prim = PH_CONTROL_REQ;
        ctrl->id = 0;
        *d++ = c1;
@@ -103,11 +95,6 @@ static void ph_control_block(unsigned long handle, unsigned long c1, void *c2, i
        ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
        if (ret < 0)
                CERROR(NULL, NULL, "Failed to send to socket %d\n", handle);
-#if 0
-       chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
-       add_trace(trace_name, NULL, "%d", trace_value);
-       end_trace();
-#endif
 }
 
 
@@ -280,8 +267,8 @@ static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsi
                        add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
                        end_trace();
 #endif
-                       if (bchannel->rx_dtmf)
-                               bchannel->rx_dtmf(bchannel, cont & DTMF_TONE_MASK);
+                       if (bchannel->call)
+                               lcr_in_dtmf(bchannel->call, cont & DTMF_TONE_MASK);
                        return;
                }
                switch(cont)
@@ -411,6 +398,20 @@ void bchannel_join(struct bchannel *bchannel, unsigned short id)
 
 
 /*
+ * dtmf bchannel
+ */
+void bchannel_dtmf(struct bchannel *bchannel, int on)
+{
+       int handle;
+
+       handle = bchannel->b_sock;
+       bchannel->b_dtmf = 1;
+       if (bchannel->b_state == BSTATE_ACTIVE)
+               ph_control(handle, on?DTMF_TONE_START:DTMF_TONE_STOP, 0, "DSP-DTMF", 1);
+}
+
+
+/*
  * main loop for processing messages from mISDN
  */
 int bchannel_handle(void)
index b3d950d..bcd5241 100644 (file)
@@ -30,9 +30,6 @@ struct bchannel {
        int b_crypt_len;
        int b_crypt_type;
        unsigned char b_crypt_key[128];
-
-       void (*rx_data)(struct bchannel *bchannel, unsigned char *data, int len);
-       void (*rx_dtmf)(struct bchannel *bchannel, char tone);
 };
 
 
@@ -45,6 +42,7 @@ int bchannel_create(struct bchannel *channel);
 void bchannel_activate(struct bchannel *channel, int activate);
 void bchannel_transmit(struct bchannel *channel, unsigned char *data, int len);
 void bchannel_join(struct bchannel *channel, unsigned short id);
+void bchannel_dtmf(struct bchannel *channel, int on);
 int bchannel_handle(void);
 struct bchannel *find_bchannel_handle(unsigned long handle);
 //struct bchannel *find_bchannel_ref(unsigned long ref);
index 6081887..658b5ad 100644 (file)
@@ -31,10 +31,11 @@ The state changes to CHAN_LCR_STATE_IN_SETUP.
 
 Call is initiated by Asterisk:
 
-If a call is reveiced from Asterisk, a new chan_call instance is created.
+If a call is requested from Asterisk, a new chan_call instance is created.
 The new Asterisk instance pointer (ast) is stored to chan_call structure.
-A MESSASGE_NEWREF is sent to LCR requesting a new call reference (ref).
 The current call ref is set to 0, the state is CHAN_LCR_STATE_OUT_PREPARE.
+If the call is received (lcr_call) A MESSASGE_NEWREF is sent to LCR requesting
+a new call reference (ref).
 Further dialing information is queued.
 After the new callref is received by special MESSAGE_NEWREF reply, new ref
 is stored in the chan_call structure. 
@@ -121,6 +122,7 @@ If the ref is 0 and the state is CHAN_LCR_STATE_RELEASE, see the proceedure
 #include "lcrsocket.h"
 #include "cause.h"
 #include "bchannel.h"
+#include "options.h"
 #include "chan_lcr.h"
 
 CHAN_LCR_STATE // state description structure
@@ -166,7 +168,7 @@ void chan_lcr_log(int type, const char *file, int line, const char *function, st
        buffer[sizeof(buffer)-1]=0;
        va_end(args);
 
-       if ((unsigned long)call > 1)
+       if (call)
                sprintf(call_text, "%ld", call->ref);
        if (ast)
                strncpy(ast_text, ast->name, sizeof(ast_text)-1);
@@ -344,11 +346,14 @@ 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");
+       CDEBUG(call, call->ast, "Sending setup to LCR. (interface=%s dialstring=%s)\n", call->interface, call->dialstring);
 
        /* send setup message to LCR */
        memset(&newparam, 0, sizeof(union parameter));
-       strncpy(newparam.setup.dialinginfo.id, ast->exten, sizeof(newparam.setup.dialinginfo.id)-1);
+               newparam.setup.dialinginfo.itype = INFO_ITYPE_ISDN;     
+               newparam.setup.dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
+       strncpy(newparam.setup.dialinginfo.id, call->dialstring, sizeof(newparam.setup.dialinginfo.id)-1);
+       strncpy(newparam.setup.dialinginfo.interfaces, call->interface, sizeof(newparam.setup.dialinginfo.interfaces)-1);
                newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;      
                newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
        if (ast->cid.cid_num) if (ast->cid.cid_num[0])
@@ -390,10 +395,7 @@ static void send_setup_to_lcr(struct chan_call *call)
                newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
        }
        newparam.setup.capainfo.bearer_capa = ast->transfercapability;
-#ifdef TODO
-       newparam.setup.capainfo.bearer_info1 = alaw 3, ulaw 2;
-#endif
-       newparam.setup.capainfo.bearer_info1 = 3;
+       newparam.setup.capainfo.bearer_info1 = (options.law=='a')?3:2;
        newparam.setup.capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
        newparam.setup.capainfo.hlc = INFO_HLC_NONE;
        newparam.setup.capainfo.exthlc = INFO_HLC_NONE;
@@ -445,7 +447,7 @@ static void send_release_and_import(struct chan_call *call, int cause, int locat
        union parameter newparam;
 
        /* importing channel */
-       if (call->bchannel && call->bchannel->handle) {
+       if (call->bchannel) {
                memset(&newparam, 0, sizeof(union parameter));
                newparam.bchannel.type = BCHANNEL_RELEASE;
                newparam.bchannel.handle = call->bchannel->handle;
@@ -582,10 +584,8 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
                ast->cid.cid_num = strdup(param->setup.callerinfo.id);
        if (param->setup.callerinfo.name[0])
                ast->cid.cid_name = strdup(param->setup.callerinfo.name);
-#ifdef TODO
        if (param->setup.redirinfo.id[0])
-               ast->cid.cid_name = strdup(numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter));
-#endif
+               ast->cid.cid_name = strdup(numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
        switch (param->setup.callerinfo.present)
        {
                case INFO_PRESENT_ALLOWED:
@@ -612,22 +612,12 @@ 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;
-#ifdef TODO
-       strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, configfile->prefix_nat, configfile->prefix_inter), sizeof(call->oad)-1);
-#else
-       strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, "0", "00"), sizeof(call->oad)-1);
-#endif
+       strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international), sizeof(call->oad)-1);
 
        /* configure channel */
-#ifdef TODO
-       ast->nativeformats = configfile->lawformat;
-       ast->readformat = ast->rawreadformat = configfile->lawformat;
-       ast->writeformat = ast->rawwriteformat = configfile->lawformat;
-#else
-       ast->nativeformats = AST_FORMAT_ALAW;
-       ast->readformat = ast->rawreadformat = AST_FORMAT_ALAW;
-       ast->writeformat = ast->rawwriteformat = AST_FORMAT_ALAW;
-#endif
+       ast->nativeformats = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
+       ast->readformat = ast->rawreadformat = ast->nativeformats;
+       ast->writeformat = ast->rawwriteformat =  ast->nativeformats;
        ast->priority = 1;
        ast->hangupcause = 0;
 
@@ -854,13 +844,36 @@ static void lcr_in_facility(struct chan_call *call, int message_type, union para
 }
 
 /*
+ * got dtmf from bchannel
+ */
+void lcr_in_dtmf(struct chan_call *call, int val)
+{
+       struct ast_channel *ast = call->ast;
+       struct ast_frame fr;
+
+       if (!ast)
+               return;
+       if (!call->pbx_started)
+               return;
+
+       CDEBUG(call, call->ast, "Frowarding DTMF digit '%c' to Asterisk.\n", val);
+
+       /* send digit to asterisk */
+       memset(&fr, 0, sizeof(fr));
+       fr.frametype = AST_FRAME_DTMF;
+       fr.subclass = val;
+       fr.delivery = ast_tv(0, 0);
+       ast_queue_frame(call->ast, &fr);
+}
+
+/*
  * message received from LCR
  */
 int receive_message(int message_type, unsigned long ref, union parameter *param)
 {
-       union parameter newparam;
        struct bchannel *bchannel;
        struct chan_call *call;
+       union parameter newparam;
 
        memset(&newparam, 0, sizeof(union parameter));
 
@@ -901,10 +914,13 @@ int receive_message(int message_type, unsigned long ref, union parameter *param)
                        /* in case, ref is not set, this bchannel instance must
                         * be created until it is removed again by LCR */
                        /* link to call */
-                       if ((call = find_call_ref(ref)))
+                       call = find_call_ref(ref);
+                       if (call)
                        {
                                bchannel->call = call;
                                call->bchannel = bchannel;
+                               if (call->dtmf)
+                                       bchannel_dtmf(bchannel, 1);
 #ifdef TODO
 hier muesen alle bchannel-features gesetzt werden (pipeline...) falls sie vor dem b-kanal verf├╝gbar waren
 #endif
@@ -915,11 +931,17 @@ hier muesen alle bchannel-features gesetzt werden (pipeline...) falls sie vor de
                        }
                        if (bchannel_create(bchannel))
                                bchannel_activate(bchannel, 1);
-
                        /* acknowledge */
                        newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
                        newparam.bchannel.handle = param->bchannel.handle;
                        send_message(MESSAGE_BCHANNEL, 0, &newparam);
+                       /* if call has released before bchannel is assigned */
+                       if (!call) {
+                               newparam.bchannel.type = BCHANNEL_RELEASE;
+                               newparam.bchannel.handle = param->bchannel.handle;
+                               send_message(MESSAGE_BCHANNEL, 0, &newparam);
+                       }
+
                        break;
 
                        case BCHANNEL_REMOVE:
@@ -1332,11 +1354,13 @@ static void *chan_thread(void *arg)
 static
 struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause)
 {
+       char exten[256], *dial, *interface, *opt;
        struct ast_channel *ast;
+        struct chan_call *call;
 
        ast_mutex_lock(&chan_lock);
 
-       CDEBUG(NULL, NULL, "Received request from Asterisk.\n");
+       CDEBUG(NULL, NULL, "Received request from Asterisk. data=%s\n", (char *)data);
 
        /* if socket is closed */
        if (lcr_sock < 0)
@@ -1345,34 +1369,66 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
                return NULL;
        }
 
+       /* create call instance */
+       call = alloc_call();
+       if (!call)
+       {
+               /* failed to create instance */
+               return NULL;
+       }
+
        /* create asterisk channel instrance */
        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;
        }
        ast->tech = &lcr_tech;
-       ast->tech_pvt = (void *)1L; // or asterisk will not call
+       ast->tech_pvt = (void *)1L; // set pointer or asterisk will not call
        /* configure channel */
-#ifdef TODO
-       snprintf(ast->name, sizeof(ast->name), "%s/%d", lcr_type, ++glob_channel);
-       ast->name[sizeof(ast->name)-1] = '\0';
-#endif
-#ifdef TODO
-       ast->nativeformats = configfile->lawformat;
-       ast->readformat = ast->rawreadformat = configfile->lawformat;
-       ast->writeformat = ast->rawwriteformat = configfile->lawformat;
-#else
-       ast->nativeformats = AST_FORMAT_ALAW;
-       ast->readformat = ast->rawreadformat = AST_FORMAT_ALAW;
-       ast->writeformat = ast->rawwriteformat = AST_FORMAT_ALAW;
-#endif
+       ast->nativeformats = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
+       ast->readformat = ast->rawreadformat = ast->nativeformats;
+       ast->writeformat = ast->rawwriteformat =  ast->nativeformats;
        ast->priority = 1;
        ast->hangupcause = 0;
 
+       /* link together */
+       call->ast = ast;
+       ast->tech_pvt = call;
+       ast->fds[0] = call->pipe[0];
        ast_mutex_unlock(&chan_lock);
+       call->pbx_started = 0;
+       /* set state */
+       call->state = CHAN_LCR_STATE_OUT_PREPARE;
+
+       /*
+        * Extract interface, dialstring, options from data.
+        * Formats can be:
+        *      <dialstring>
+        *      <interface>/<dialstring>
+        *      <interface>/<dialstring>/options
+        */
+       strncpy(exten, (char *)data, sizeof(exten)-1);
+       exten[sizeof(exten)-1] = '\0';
+       if ((dial = strchr(exten, '/'))) {
+               *dial++ = '\0';
+               interface = exten;
+               if ((opt = strchr(dial, '/')))
+                       *opt++ = '\0';
+               else
+                       opt = "";
+       } else {
+               dial = exten;
+               interface = "";
+               opt = "";
+       }
+       strncpy(call->interface, interface, sizeof(call->interface)-1);
+       strncpy(call->dialstring, dial, sizeof(call->dialstring)-1);
+
+#warning todo: parse options
 
        return ast;
 }
@@ -1382,38 +1438,25 @@ struct ast_channel *lcr_request(const char *type, int format, void *data, int *c
  */
 static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
 {
-        struct chan_call *call;
        union parameter newparam;
+        struct chan_call *call;
 
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
-       if ((unsigned long)call > 1) {
-               CERROR(NULL, ast, "Received call from Asterisk, but call instance already exists.\n");
+       if (!call) {
+               CERROR(NULL, ast, "Received call from Asterisk, but call instance does not exist.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
 
        CDEBUG(NULL, ast, "Received call from Asterisk.\n");
 
-       /* create call instance */
-       call = alloc_call();
-       if (!call)
-       {
-               /* failed to create instance */
-               return -1;
-       }
-       /* link together */
-       call->ast = ast;
-       ast->tech_pvt = call;
-       ast->fds[0] = call->pipe[0];
        /* pbx process is started */
        call->pbx_started = 1;
        /* send MESSAGE_NEWREF */
        memset(&newparam, 0, sizeof(union parameter));
        newparam.direction = 0; /* request from app */
        send_message(MESSAGE_NEWREF, 0, &newparam);
-       /* set state */
-       call->state = CHAN_LCR_STATE_OUT_PREPARE;
 
        ast_mutex_unlock(&chan_lock);
        return 0; 
@@ -1431,13 +1474,13 @@ static int lcr_digit(struct ast_channel *ast, char digit)
 
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       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");
+       CDEBUG(call, ast, "Received digit '%c' from Asterisk.\n", digit);
 
        /* send information or queue them */
        if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING)
@@ -1449,7 +1492,7 @@ static int lcr_digit(struct ast_channel *ast, char digit)
                send_message(MESSAGE_INFORMATION, call->ref, &newparam);
        } else
        if (!call->ref
-        && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP));
+        && (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;
@@ -1468,7 +1511,7 @@ static int lcr_answer(struct ast_channel *ast)
 
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       if (!call) {
                CERROR(NULL, ast, "Received answer from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
@@ -1492,6 +1535,10 @@ static int lcr_answer(struct ast_channel *ast)
                newparam.bchannel.type = BCHANNEL_REQUEST;
                send_message(MESSAGE_BCHANNEL, call->ref, &newparam);
        }
+       /* enable keypad */
+//     memset(&newparam, 0, sizeof(union parameter));
+//     send_message(MESSAGE_ENABLEKEYPAD, call->ref, &newparam);
+       call->dtmf = 1;
        
        ast_mutex_unlock(&chan_lock);
         return 0;
@@ -1505,7 +1552,7 @@ static int lcr_hangup(struct ast_channel *ast)
        if (!pthread_equal(tid, chan_tid))
                ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       if (!call) {
                CERROR(NULL, ast, "Received hangup from Asterisk, but no call instance exists.\n");
                if (!pthread_equal(tid, chan_tid))
                        ast_mutex_unlock(&chan_lock);
@@ -1559,16 +1606,12 @@ static int lcr_write(struct ast_channel *ast, struct ast_frame *f)
 
        if (!f->subclass)
                CDEBUG(NULL, ast, "No subclass\n");
-#ifdef TODO
-       config
-#else
-       if (!(f->subclass & AST_FORMAT_ALAW))
-#endif
+       if (!(f->subclass & ast->nativeformats))
                CDEBUG(NULL, ast, "Unexpected format.\n");
        
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       if (!call) {
                ast_mutex_unlock(&chan_lock);
                return -1;
        }
@@ -1587,7 +1630,7 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
 
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       if (!call) {
                ast_mutex_unlock(&chan_lock);
                return NULL;
        }
@@ -1607,11 +1650,7 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
        }
 
        call->read_fr.frametype = AST_FRAME_VOICE;
-#ifdef TODO
-       format aus config
-#else
-       call->read_fr.subclass = AST_FORMAT_ALAW;
-#endif
+       call->read_fr.subclass = ast->nativeformats;
        call->read_fr.datalen = len;
        call->read_fr.samples = len;
        call->read_fr.delivery = ast_tv(0,0);
@@ -1629,7 +1668,7 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
 
        ast_mutex_lock(&chan_lock);
         call = ast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       if (!call) {
                CERROR(NULL, ast, "Received indicate from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
@@ -1729,7 +1768,7 @@ static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *newast)
 
        ast_mutex_lock(&chan_lock);
        call = oldast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       if (!call) {
                CERROR(NULL, oldast, "Received fixup from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
@@ -1751,7 +1790,7 @@ static int lcr_send_text(struct ast_channel *ast, const char *text)
 
        ast_mutex_lock(&chan_lock);
        call = ast->tech_pvt;
-       if ((unsigned long)call <= 1) {
+       if (!call) {
                CERROR(NULL, ast, "Received send_text from Asterisk, but no call instance exists.\n");
                ast_mutex_unlock(&chan_lock);
                return -1;
@@ -1776,11 +1815,14 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
 {
        struct chan_call        *call1, *call2;
        struct ast_channel      *carr[2], *who;
-       int                     to = -1;
+       int                     to;
        struct ast_frame        *f;
        int                     bridge_id;
 
        CDEBUG(NULL, NULL, "Received briding request from Asterisk.\n");
+
+       carr[0] = ast1;
+       carr[1] = ast2;
        
        /* join via dsp (if the channels are currently open) */
        ast_mutex_lock(&chan_lock);
@@ -1804,6 +1846,7 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
        ast_mutex_unlock(&chan_lock);
        
        while(1) {
+               to = -1;
                who = ast_waitfor_n(carr, 2, &to);
 
                if (!who) {
@@ -1813,6 +1856,10 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
                f = ast_read(who);
     
                if (!f || f->frametype == AST_FRAME_CONTROL) {
+                       if (!f)
+                               CDEBUG(NULL, NULL, "Got hangup.\n");
+                       else
+                               CDEBUG(NULL, NULL, "Got CONTROL.\n");
                        /* got hangup .. */
                        *fo=f;
                        *rc=who;
@@ -1820,6 +1867,7 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
                }
                
                if ( f->frametype == AST_FRAME_DTMF ) {
+                       CDEBUG(NULL, NULL, "Got DTMF.\n");
                        *fo=f;
                        *rc=who;
                        break;
@@ -1867,11 +1915,6 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
 static struct ast_channel_tech lcr_tech = {
        .type="LCR",
        .description="Channel driver for connecting to Linux-Call-Router",
-#ifdef TODO
-       law from config
-#else
-       .capabilities=AST_FORMAT_ALAW,
-#endif
        .requester=lcr_request,
        .send_digit_begin=lcr_digit,
        .call=lcr_call,
@@ -1890,6 +1933,7 @@ static struct ast_channel_tech lcr_tech = {
 /*
  * cli
  */
+#if 0
 static int lcr_show_lcr (int fd, int argc, char *argv[])
 {
        return 0;
@@ -1973,6 +2017,7 @@ static struct ast_cli_entry cli_port_unload =
  "Unloads LCR port, port is closes by mISDN",
  "Usage: lcr port unload \"<port>\"\n",
 };
+#endif
 
 
 /*
@@ -1987,6 +2032,11 @@ int load_module(void)
                             | (i<<7) | ((i&2)<<5) | ((i&4)<<3) | ((i&8)<<1);
        }
 
+       if (read_options() == 0) {
+               CERROR(NULL, NULL, "%s", options_error);
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
        ast_mutex_init(&chan_lock);
        ast_mutex_init(&log_lock);
 
@@ -2001,6 +2051,7 @@ int load_module(void)
        }
        mISDN_created = 1;
 
+       lcr_tech.capabilities = (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW;
        if (ast_channel_register(&lcr_tech)) {
                CERROR(NULL, NULL, "Unable to register channel class\n");
                bchannel_deinitialize();
@@ -2082,34 +2133,6 @@ int reload_module(void)
        return 0;
 }
 
-#ifdef TODO
-wech damit
-
-int usecnt;
-ast_mutex_t usecnt_lock;
-
-int usecount(void)
-{
-       int res;
-       ast_mutex_lock(&usecnt_lock);
-       res = usecnt;
-       ast_mutex_unlock(&usecnt_lock);
-       return res;
-}
-
-
-char *desc="Channel driver for lcr";
-
-char *description(void)
-{
-       return desc;
-}
-
-char *key(void)
-{
-       return ASTERISK_GPL_KEY;
-}
-#endif
 
 #define AST_MODULE "chan_lcr"
 
index 8265c26..29d9e7d 100644 (file)
@@ -39,6 +39,12 @@ struct chan_call {
                                        /* read buffer for frame */
        struct ast_frame        read_fr;
                                        /* frame for read */
+       char                    interface[32];
+                                       /* LCR interface name for setup */
+       char                    dialstring[64];
+                                       /* cached dial string for setup */
+       int                     dtmf;
+                                       /* shall dtmf be enabled */
 };
 
 enum {
@@ -97,3 +103,4 @@ enum {
 #define CDEBUG(call, ast, arg...) chan_lcr_log(__LOG_NOTICE, __FILE__, __LINE__,  __FUNCTION__, call, ast, ##arg)
 void chan_lcr_log(int type, const char *file, int line, const char *function,  struct chan_call *call, struct ast_channel *ast, const char *fmt, ...);
 extern unsigned char flip_bits[256];
+void lcr_in_dtmf(struct chan_call *call, int val);
index 8e0ffc7..59309b6 100644 (file)
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -692,7 +692,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
        message->param.setup.isdn_port = p_m_portnum;
        message->param.setup.port_type = p_type;
-       message->param.setup.dtmf = !p_m_mISDNport->ifport->nodtmf;
+//     message->param.setup.dtmf = !p_m_mISDNport->ifport->nodtmf;
        memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
        memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
        memcpy(&message->param.setup.redirinfo, &p_redirinfo, sizeof(struct redir_info));
index 0cbea25..21689e6 100644 (file)
--- a/genext.c
+++ b/genext.c
@@ -55,7 +55,7 @@ int main(int argc, char *argv[])
 
        if (!read_options())
        {
-               PERROR("Failed to read options.conf\n");
+               PERROR("%s", options_error);
                return(-1);
        }
 
index 20c94dc..b30dd1c 100644 (file)
@@ -100,7 +100,7 @@ void JoinRemote::message_remote(int message_type, union parameter *param)
         * also ref is given, so we send message with ref */
        if (message_type == MESSAGE_BCHANNEL)
        {
-               message_bchannel_from_join(this, param->bchannel.type, param->bchannel.handle);
+               message_bchannel_from_remote(this, param->bchannel.type, param->bchannel.handle);
                return;
        }
        
@@ -116,7 +116,7 @@ void JoinRemote::message_remote(int message_type, union parameter *param)
        }
 }
 
-void message_bchannel_to_join(unsigned long remote_id, unsigned long ref, int type, unsigned long handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type)
+void message_bchannel_to_remote(unsigned long remote_id, unsigned long ref, int type, unsigned long handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type)
 {
        union parameter param;
 
index 560487a..c0be35a 100644 (file)
@@ -24,4 +24,4 @@ class JoinRemote : public Join
 }; 
 
 
-void message_bchannel_to_join(unsigned long remote_id, unsigned long ref, int type, unsigned long handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type);
+void message_bchannel_to_remote(unsigned long remote_id, unsigned long ref, int type, unsigned long handle, int tx_gain, int rx_gain, char *pipeline, unsigned char *crypt, int crypt_len, int crypt_type);
index 874d2a6..6d9409b 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -635,7 +635,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        if (p_m_remote_ref)
                        {
                                /* export bchannel */
-                               message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
+                               message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
                                chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
                                add_trace("type", NULL, "assign");
                                add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
@@ -687,7 +687,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        /* in case, the bchannel is exported right after seize_bchannel */
                        /* export bchannel */
                        /* p_m_remote_id is set, when this event happens. */
-                       message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
+                       message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
                        chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
                        add_trace("type", NULL, "assign");
                        add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
@@ -744,7 +744,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
 
                        case B_STATE_REMOTE:
                        /* bchannel is exported, so we re-import */
-                       message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
+                       message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
                        chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
                        add_trace("type", NULL, "remove");
                        add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
@@ -800,7 +800,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                                 * OR bchannel is not used anymore
                                 * OR bchannel has been exported to an obsolete ref,
                                 * so reimport, to later export to new remote */
-                               message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
+                               message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
                                chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
                                add_trace("type", NULL, "remove");
                                add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
@@ -837,7 +837,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
 
                        case B_STATE_REMOTE:
                        /* bchannel is exported, so we re-import */
-                       message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
+                       message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
                        chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
                        add_trace("type", NULL, "remove");
                        add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
@@ -871,7 +871,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                                /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
                                if (p_m_remote_ref)
                                {
-                                       message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
+                                       message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
                                        chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
                                        add_trace("type", NULL, "assign");
                                        add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
@@ -908,7 +908,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                                /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
                                if (p_m_remote_ref)
                                {
-                                       message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
+                                       message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
                                        chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
                                        add_trace("type", NULL, "assign");
                                        add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
@@ -1074,7 +1074,7 @@ void PmISDN::drop_bchannel(void)
 }
 
 /* process bchannel export/import message from join */
-void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long handle)
+void message_bchannel_from_remote(class JoinRemote *joinremote, int type, unsigned long handle)
 {
        class Endpoint *epoint;
        class Port *port;
@@ -1131,51 +1131,6 @@ void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned
                break;
 
                case BCHANNEL_RELEASE:
-               /* find the port object for the join object ref */
-               if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
-               {
-                       PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
-                       return;
-               }
-               if (!epoint->ep_portlist)
-               {
-                       PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
-                       return;
-               }
-               if (epoint->ep_portlist->next)
-               {
-                       PERROR("join %d has enpoint %d with more than one port. this shall not happen to remote joins.\n", joinremote->j_serial, epoint->ep_serial);
-               }
-               if (!(port = find_port_id(epoint->ep_portlist->port_id)))
-               {
-                       PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
-                       return;
-               }
-               if ((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN)
-               {
-                       PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
-               }
-               isdnport = (class PmISDN *)port;
-
-               /* release */
-               if (!isdnport->p_m_remote_id)
-               {
-                       PERROR("join %d recevied bchannel release from remote, but channel is already released.\n", joinremote->j_serial);
-                       break;
-               }
-               mISDNport = isdnport->p_m_mISDNport;
-               i = isdnport->p_m_b_index;
-               chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
-               add_trace("type", NULL, "export request");
-               end_trace();
-               isdnport->p_m_remote_ref = 0;
-               isdnport->p_m_remote_id = 0;
-               if (mISDNport && i>=0)
-               {
-                       bchannel_event(mISDNport, i, B_EVENT_IMPORTREQUEST);
-               }
-               break;
-
                case BCHANNEL_ASSIGN_ACK:
                case BCHANNEL_REMOVE_ACK:
                /* find mISDNport for stack ID */
@@ -1199,14 +1154,28 @@ void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned
                        PERROR("received assign/remove ack for bchannel's handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
                        break;
                }
-               /* mISDNport may now be set or NULL */
                
-               /* set */
-               chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
-               add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
-               end_trace();
-               if (mISDNport && i>=0)
+               if (type!=BCHANNEL_RELEASE)
+               {
+                       /* ack */
+                       chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
+                       add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
+                       end_trace();
                        bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
+               } else
+               {
+                       /* release */
+                       isdnport = mISDNport->b_port[i];
+                       chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
+                       add_trace("type", NULL, "export request");
+                       end_trace();
+                       if (isdnport)
+                       {
+                               isdnport->p_m_remote_ref = 0;
+                               isdnport->p_m_remote_id = 0;
+                       }
+                       bchannel_event(mISDNport, i, B_EVENT_IMPORTREQUEST);
+               }
                break;
                default:
                PERROR("received wrong bchannel message type %d from remote\n", type);
diff --git a/mISDN.h b/mISDN.h
index a61b5cd..f9bae48 100644 (file)
--- a/mISDN.h
+++ b/mISDN.h
@@ -91,7 +91,7 @@ void ph_control_block(struct mISDNport *mISDNport, unsigned long handle, unsigne
 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction);
 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction);
 void bchannel_event(struct mISDNport *mISDNport, int i, int event);
-void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long handle);
+void message_bchannel_from_remote(class JoinRemote *joinremote, int type, unsigned long handle);
 
 
 /* mISDN port classes */
diff --git a/macro.h b/macro.h
index 9bb1f29..07921e0 100644 (file)
--- a/macro.h
+++ b/macro.h
 \*****************************************************************************/ 
 
 
-/* save strcpy/strncpy */
+/* safe strcpy/strncpy */
 
 #define SCPY(dst, src) scpy(dst, src, sizeof(dst))
-extern __inline__ void scpy(char *dst, char *src, unsigned int siz)
+static inline void scpy(char *dst, char *src, unsigned int siz)
 {
        strncpy(dst, src, siz);
        dst[siz-1] = '\0';
 }
 
-/* save strcat/strncat */
+/* safe strcat/strncat */
 
 #define SCAT(dst, src) scat(dst, src, sizeof(dst))
-extern __inline__ void scat(char *dst, char *src, unsigned int siz)
+static inline void scat(char *dst, char *src, unsigned int siz)
 {
        strncat(dst, src, siz);
        dst[siz-1] = '\0';
 }
 
-/* save concat of a byte */
+/* safe concat of a byte */
 
 #define SCCAT(dst, src) sccat(dst, src, sizeof(dst))
-extern __inline__ void sccat(char *dst, char chr, unsigned int siz)
+static inline void sccat(char *dst, char chr, unsigned int siz)
 {
        if (strlen(dst) < siz-1)
        {
@@ -41,10 +41,10 @@ extern __inline__ void sccat(char *dst, char chr, unsigned int siz)
        }
 }
 
-/* save sprintf/snprintf */
+/* safe sprintf/snprintf */
 
 #define SPRINT(dst, fmt, arg...) sprint(dst, sizeof(dst), fmt, ## arg)
-extern __inline__ void sprint(char *dst, unsigned int siz, char *fmt, ...)
+static inline void sprint(char *dst, unsigned int siz, char *fmt, ...)
 {
        va_list args;
 
@@ -54,7 +54,7 @@ extern __inline__ void sprint(char *dst, unsigned int siz, char *fmt, ...)
        va_end(args);
 }
 
-/* unsave */
+/* unsafe */
 #define UCPY strcpy
 #define UNCPY strncpy
 #define UCAT strcat
@@ -65,7 +65,7 @@ extern __inline__ void sprint(char *dst, unsigned int siz, char *fmt, ...)
 
 /* fatal error with error message and exit */
 #define FATAL(fmt, arg...) fatal(__FUNCTION__, __LINE__, fmt, ##arg)
-extern __inline__ void fatal(const char *function, int line, char *fmt, ...)
+static inline void fatal(const char *function, int line, char *fmt, ...)
 {
        va_list args;
        char buffer[256];
@@ -85,7 +85,7 @@ extern __inline__ void fatal(const char *function, int line, char *fmt, ...)
 
 /* memory allocation with setting to zero */
 #define MALLOC(size) _malloc(size, __FUNCTION__, __LINE__)
-extern __inline__ void *_malloc(unsigned long size, const char *function, int line)
+static inline void *_malloc(unsigned long size, const char *function, int line)
 {
        void *addr;
        addr = malloc(size);
@@ -97,7 +97,7 @@ extern __inline__ void *_malloc(unsigned long size, const char *function, int li
 
 /* memory freeing with clearing memory to prevent using freed memory */
 #define FREE(addr, size) _free(addr, size)
-extern __inline void _free(void *addr, int size)
+static inline void _free(void *addr, int size)
 {
        if (size)
                memset(addr, 0, size);
diff --git a/main.c b/main.c
index 21b3384..b66615f 100644 (file)
--- a/main.c
+++ b/main.c
@@ -282,7 +282,10 @@ int main(int argc, char *argv[])
 
        /* read options */
        if (read_options() == 0)
+       {
+               PERROR("%s", options_error);
                goto free;
+       }
 
        /* init mISDN */
        if (mISDN_initialize() < 0)
index f07745c..c84ab19 100644 (file)
--- a/message.h
+++ b/message.h
@@ -240,7 +240,6 @@ struct useruser_info {
 struct message_setup {
        int isdn_port; /* card number 1...n (only on calls from isdn port) */
        int port_type; /* type of port (only required if message is port -> epoint) */
-       int dtmf; /* used to enabled dtmf dialing at setup state */
        int partyline; /* if set, call will be a conference room */
        int partyline_jingle; /* if set, the jingle will be played on conference join */
        struct caller_info callerinfo;          /* information about the caller */
@@ -358,6 +357,7 @@ enum { /* messages between entities */
        MESSAGE_NONE,           /* no message */
        MESSAGE_TONE,           /* set information tone (to isdn port) */
        MESSAGE_DTMF,           /* dtmf digit (from isdn port) */
+       MESSAGE_ENABLEKEYPAD,   /* remote application requests keypad/dtmf */
        MESSAGE_mISDNSIGNAL,    /* special mixer command (down to isdn port) */
        MESSAGE_SETUP,          /* setup message */
        MESSAGE_INFORMATION,    /* additional digit information */
@@ -392,6 +392,7 @@ enum { /* messages between entities */
        "MESSAGE_NONE", \
        "MESSAGE_TONE", \
        "MESSAGE_DTMF", \
+       "MESSAGE_ENABLEKEYPAD", \
        "MESSAGE_mISDNSIGNAL", \
        "MESSAGE_SETUP", \
        "MESSAGE_INFORMATION", \
index 4c1fabb..6bfdb97 100644 (file)
--- a/options.c
+++ b/options.c
@@ -9,7 +9,14 @@
 **                                                                           **
 \*****************************************************************************/ 
 
-#include "main.h"
+#include "stdio.h"
+#include "string.h"
+#include "stdarg.h"
+#include "unistd.h"
+#include "stdlib.h"
+#include "macro.h"
+#include "extension.h"
+#include "options.h"
 
 struct options options = {
        "/usr/local/lcr/log",           /* log file */
@@ -26,6 +33,8 @@ struct options options = {
        "lcr@your.machine"              /* source mail adress */
 };
 
+char options_error[256];
+
 /* read options
  *
  * read options from options.conf
@@ -44,8 +53,8 @@ int read_options(void)
 
        if (!(fp=fopen(filename,"r")))
        {
-               PERROR("Cannot open %s\n",filename);
-               return(-1);
+               SPRINT(options_error, "Cannot open %s\n",filename);
+               return(0);
        }
 
        line=0;
@@ -71,7 +80,7 @@ int read_options(void)
                {
                        if (i+1 >= sizeof(option))
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): option too long.\n",filename,line);
+                               SPRINT(options_error, "Error in %s (line %d): option too long.\n",filename,line);
                                goto error;
                        }
                        option[i+1] = '\0';
@@ -93,7 +102,7 @@ int read_options(void)
                        {
                                if (i+1 >= sizeof(param))
                                {
-                                       PERROR_RUNTIME("Error in %s (line %d): param too long.\n",filename,line);
+                                       SPRINT(options_error, "Error in %s (line %d): param too long.\n",filename,line);
                                        goto error;
                                }
                                param[i+1] = '\0';
@@ -106,99 +115,89 @@ int read_options(void)
                /* check option */
                if (!strcmp(option,"nt_if") || !strcmp(option,"te_if"))
                {
-                       PERROR_RUNTIME("Error in %s (line %d): obsolete option %s. Use multiple 'port' options to define ports to use.\n",filename,line,option);
+                       SPRINT(options_error, "Error in %s (line %d): obsolete option %s. Use multiple 'port' options to define ports to use.\n",filename,line,option);
                        goto error;
                } else
                if (!strcmp(option,"debug"))
                {
                        if (param[0]==0)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
                                goto error;
                        }
                        options.deb = strtol(param, NULL, 0);
 
-                       PDEBUG(DEBUG_CONFIG, "debugging: 0x%x\n", options.deb);
                } else
                if (!strcmp(option,"log"))
                {
                        if (param[0]==0)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line, option);
                                goto error;
                        }
                        SCPY(options.log, param);
 
-                       PDEBUG(DEBUG_CONFIG, "log file: %s\n", options.log);
                } else
                if (!strcmp(option,"alaw"))
                {
                        options.law = 'a';
 
-                       PDEBUG(DEBUG_CONFIG, "isdn audio type: alaw\n");
                } else
                if (!strcmp(option,"ulaw"))
                {
                        options.law = 'u';
 
-                       PDEBUG(DEBUG_CONFIG, "isdn audio type: ulaw\n");
                } else
                if (!strcmp(option,"tones_dir"))
                {
                        if (param[0]==0)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
                                goto error;
                        }
                        if (param[strlen(param)-1] == '/')
                                param[strlen(param)-1]=0;
                        SCPY(options.tones_dir, param);
 
-                       PDEBUG(DEBUG_CONFIG, "directory of tones: %s\n",param);
                } else
                if (!strcmp(option,"fetch_tones"))
                {
                        if (param[0]==0)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
                                goto error;
                        }
                        if (param[strlen(param)-1] == '/')
                                param[strlen(param)-1]=0;
                        SCPY(options.fetch_tones, param);
 
-                       PDEBUG(DEBUG_CONFIG, "directories of tones to fetch: %s\n",param);
                } else
                if (!strcmp(option,"extensions_dir"))
                {
                        if (param[0]==0)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
                                goto error;
                        }
                        if (param[strlen(param)-1] == '/')
                                param[strlen(param)-1]=0;
                        SCPY(options.extensions_dir, param);
 
-                       PDEBUG(DEBUG_CONFIG, "directory of extensions: %s\n",param);
                } else
                if (!strcmp(option,"national"))
                {
                        SCPY(options.national, param);
 
-                       PDEBUG(DEBUG_CONFIG, "national dial prefix: %s\n", param);
                } else
                if (!strcmp(option,"international"))
                {
                        SCPY(options.international, param);
 
-                       PDEBUG(DEBUG_CONFIG, "inernational dial prefix: %s\n", param);
                } else
                if (!strcmp(option,"dummyid"))
                {
                        SCPY(options.dummyid, param);
 
-                       PDEBUG(DEBUG_CONFIG, "dummy caller id\n", param);
                } else
                if (!strcmp(option,"dsptones"))
                {
@@ -211,44 +210,38 @@ int read_options(void)
                        else if (!strcasecmp(param, "none"))
                                options.dsptones = DSP_NONE;
                        else {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n",filename,line,option);
                                goto error;
                        }
 
-                       PDEBUG(DEBUG_CONFIG, "dsp tones = %d\n", options.dsptones);
                } else
                if (!strcmp(option,"schedule"))
                {
                        options.schedule = atoi(param);
                        if (options.schedule < 0)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be at least '0'.\n", filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s must be at least '0'.\n", filename,line,option);
                                goto error;
                        }
                        if (options.schedule > 99)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be '99' or less.\n", filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s must be '99' or less.\n", filename,line,option);
                                goto error;
                        }
 
-                       if (atoi(param))
-                               PDEBUG(DEBUG_CONFIG, "use real time scheduler priority: %d\n", atoi(param));
-                       else
-                               PDEBUG(DEBUG_CONFIG, "don't use real time scheduler\n");
                } else
                if (!strcmp(option,"email"))
                {
                        if (param[0]==0)
                        {
-                               PERROR_RUNTIME("Error in %s (line %d): parameter for option %s missing.\n", filename,line,option);
+                               SPRINT(options_error, "Error in %s (line %d): parameter for option %s missing.\n", filename,line,option);
                                goto error;
                        }
                        SCPY(options.email, param);
 
-                       PDEBUG(DEBUG_CONFIG, "source mail address of pbx: %s\n", param);
                } else
                {
-                       PERROR_RUNTIME("Error in %s (line %d): wrong option keyword %s.\n", filename,line,option);
+                       SPRINT(options_error, "Error in %s (line %d): wrong option keyword %s.\n", filename,line,option);
                        goto error;
                }
        }
@@ -256,13 +249,13 @@ int read_options(void)
 #if 0
        if (!options.dsptones)
        {
-               PERROR_RUNTIME("Error in %s (line %d): option 'dsptones' missing.\n", filename);
+               SPRINT(options_error, "Error in %s (line %d): option 'dsptones' missing.\n", filename);
                goto error;
        }
 #endif
        if (!options.tones_dir[0])
        {
-               PERROR_RUNTIME("Error in %s (line %d): option 'tones_dir' with parameter missing.\n", filename);
+               SPRINT(options_error, "Error in %s (line %d): option 'tones_dir' with parameter missing.\n", filename);
                goto error;
        }
        if (fp) fclose(fp);
index a0dbad4..60748f9 100644 (file)
--- a/options.h
+++ b/options.h
@@ -28,6 +28,8 @@ struct options {
 
 extern struct options options;
 
+extern char options_error[256];
+
 int read_options(void);
 
 
index 77e5309..4619f60 100644 (file)
@@ -654,10 +654,11 @@ int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin)
         * no ref given for *_ack */
        if (msg->type == MESSAGE_BCHANNEL)
        if (msg->param.bchannel.type == BCHANNEL_ASSIGN_ACK
-        || msg->param.bchannel.type == BCHANNEL_REMOVE_ACK)
+        || msg->param.bchannel.type == BCHANNEL_REMOVE_ACK
+        || msg->param.bchannel.type == BCHANNEL_RELEASE)
        {
                /* no ref, but address */
-               message_bchannel_from_join(NULL, msg->param.bchannel.type, msg->param.bchannel.handle);
+               message_bchannel_from_remote(NULL, msg->param.bchannel.type, msg->param.bchannel.handle);
                return(0);
        }