summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuper User2008-06-06 15:18:59 +0200
committerSuper User2008-06-06 15:18:59 +0200
commitcbc232643c7b26d64204ba7f6151007e9c0267e4 (patch)
treede9d04deac87922f6e8a6a6e0f1e4654d12a0706
parentfixed bad bug in opening bchannel (diff)
downloadlcr-cbc232643c7b26d64204ba7f6151007e9c0267e4.tar.gz
lcr-cbc232643c7b26d64204ba7f6151007e9c0267e4.tar.xz
lcr-cbc232643c7b26d64204ba7f6151007e9c0267e4.zip
work on chan_lcr: bridging works, interface selection possible
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
-rw-r--r--Makefile16
-rw-r--r--apppbx.cpp23
-rw-r--r--apppbx.h1
-rw-r--r--bchannel.c35
-rw-r--r--bchannel.h4
-rw-r--r--chan_lcr.c253
-rw-r--r--chan_lcr.h7
-rw-r--r--dss1.cpp2
-rw-r--r--genext.c2
-rw-r--r--joinremote.cpp4
-rw-r--r--joinremote.h2
-rw-r--r--mISDN.cpp87
-rw-r--r--mISDN.h2
-rw-r--r--macro.h24
-rw-r--r--main.c3
-rw-r--r--message.h3
-rw-r--r--options.c61
-rw-r--r--options.h2
-rw-r--r--socket_server.c5
19 files changed, 277 insertions, 259 deletions
diff --git a/Makefile b/Makefile
index 53f43c2..ce4b9fb 100644
--- 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
diff --git a/apppbx.cpp b/apppbx.cpp
index 981c867..6304848 100644
--- a/apppbx.cpp
+++ b/apppbx.cpp
@@ -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 */
diff --git a/apppbx.h b/apppbx.h
index 4afb1e8..d9c9638 100644
--- 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 */
diff --git a/bchannel.c b/bchannel.c
index 3db3bc5..9d7db44 100644
--- a/bchannel.c
+++ b/bchannel.c
@@ -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)
diff --git a/bchannel.h b/bchannel.h
index b3d950d..bcd5241 100644
--- a/bchannel.h
+++ b/bchannel.h
@@ -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);
diff --git a/chan_lcr.c b/chan_lcr.c
index 6081887..658b5ad 100644
--- a/chan_lcr.c
+++ b/chan_lcr.c
@@ -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"
diff --git a/chan_lcr.h b/chan_lcr.h
index 8265c26..29d9e7d 100644
--- a/chan_lcr.h
+++ b/chan_lcr.h
@@ -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);
diff --git a/dss1.cpp b/dss1.cpp
index 8e0ffc7..59309b6 100644
--- 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));
diff --git a/genext.c b/genext.c
index 0cbea25..21689e6 100644
--- 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);
}
diff --git a/joinremote.cpp b/joinremote.cpp
index 20c94dc..b30dd1c 100644
--- a/joinremote.cpp
+++ b/joinremote.cpp
@@ -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;
diff --git a/joinremote.h b/joinremote.h
index 560487a..c0be35a 100644
--- a/joinremote.h
+++ b/joinremote.h
@@ -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);
diff --git a/mISDN.cpp b/mISDN.cpp
index 874d2a6..6d9409b 100644
--- 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
--- 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
--- a/macro.h
+++ b/macro.h
@@ -11,28 +11,28 @@
\*****************************************************************************/
-/* 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
--- 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)
diff --git a/message.h b/message.h
index f07745c..c84ab19 100644
--- 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", \
diff --git a/options.c b/options.c
index 4c1fabb..6bfdb97 100644
--- 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);
diff --git a/options.h b/options.h
index a0dbad4..60748f9 100644
--- 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);
diff --git a/socket_server.c b/socket_server.c
index 77e5309..4619f60 100644
--- a/socket_server.c
+++ b/socket_server.c
@@ -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);
}