From cbc232643c7b26d64204ba7f6151007e9c0267e4 Mon Sep 17 00:00:00 2001 From: Super User Date: Fri, 6 Jun 2008 15:18:59 +0200 Subject: [PATCH] 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 --- Makefile | 16 ++-- apppbx.cpp | 23 +++++- apppbx.h | 1 + bchannel.c | 35 ++++---- bchannel.h | 4 +- chan_lcr.c | 253 ++++++++++++++++++++++++++++++-------------------------- chan_lcr.h | 7 ++ dss1.cpp | 2 +- genext.c | 2 +- joinremote.cpp | 4 +- joinremote.h | 2 +- mISDN.cpp | 87 +++++++------------ mISDN.h | 2 +- macro.h | 24 +++--- main.c | 3 + message.h | 3 +- options.c | 61 ++++++-------- options.h | 2 + socket_server.c | 5 +- 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, ¶m->setup.dialinginfo, sizeof(e_dialinginfo)); memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo)); memcpy(&e_capainfo, ¶m->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, ¶m->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: + * + * / + * //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 \"\"\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); } -- 2.13.6