From ef3fc1931a2fa82f482d21fb1296735206463d3a Mon Sep 17 00:00:00 2001 From: Super User Date: Sun, 15 Jul 2007 12:01:27 +0200 Subject: [PATCH] backup --- Makefile | 26 ++-- README | 25 +++- action.cpp | 44 ++++--- admin.h | 14 +- admin_client.c | 22 ++-- admin_server.c | 224 +++++++++++++++++++++++--------- admin_server.h | 3 + apppbx.cpp | 399 +++++++++++++++++++++++++++------------------------------ apppbx.h | 2 +- call.cpp | 16 +-- call.h | 3 +- callpbx.cpp | 190 ++++++++++++--------------- callpbx.h | 3 +- cause.c | 38 ++++++ cause.h | 2 + crypt.cpp | 18 +-- dss1.cpp | 247 ++++++++++------------------------- endpoint.cpp | 37 ++---- endpoint.h | 2 +- extension.h | 4 + genrc.c | 4 +- ie.cpp | 2 +- interface.c | 146 +++++++-------------- mISDN.cpp | 318 +++++++++++++++++++++++---------------------- mISDN.h | 14 +- mail.c | 10 +- main.c | 4 +- main.h | 26 ++-- message.c | 43 ++++--- message.h | 6 +- port.cpp | 45 ++----- port.h | 3 - route.c | 112 ++++++---------- route.h | 2 + todo.txt | 7 +- tones.c | 27 +--- trace.c | 6 +- vbox.cpp | 11 +- 38 files changed, 983 insertions(+), 1122 deletions(-) diff --git a/Makefile b/Makefile index 420653d..c06b281 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ #*****************************************************************************/ WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used +WITH-ASTERISK = 42 # comment this out, if you don't require built-in Asterisk channel driver. # note: check your location and the names of libraries. # select location to install @@ -32,6 +33,9 @@ LD = $(CC) WIZZARD = ./wizzard LCR = ./lcr LCRADMIN = ./lcradmin +ifdef WITH-ASTERISK +CHAN_LCR = ./chan_lcr +endif LCRWATCH = ./lcrwatch GEN = ./gentones GENW = ./genwave @@ -55,7 +59,7 @@ endif # @echo Please report any bug. To compile use \"make beta\". # @exit -all: $(LCR) $(LCRADMIN) $(GEN) $(GENW) $(GENRC) $(GENEXT) +all: $(LCR) $(LCRADMIN) $(CHAN_LCR) $(GEN) $(GENW) $(GENRC) $(GENEXT) @sh -c 'grep -n strcpy *.c* ; if test $$''? = 0 ; then echo "dont use strcpy, use makro instead." ; exit -1 ; fi' @sh -c 'grep -n strncpy *.c* ; if test $$''? = 0 ; then echo "dont use strncpy, use makro instead." ; exit -1 ; fi' @sh -c 'grep -n strcat *.c* ; if test $$''? = 0 ; then echo "dont use strcat, use makro instead." ; exit -1 ; fi' @@ -126,8 +130,8 @@ call.o: call.cpp *.h Makefile callpbx.o: callpbx.cpp *.h Makefile $(CC) -c $(CFLAGS) callpbx.cpp -o callpbx.o -callchan.o: callchan.cpp *.h Makefile - $(CC) -c $(CFLAGS) callchan.cpp -o callchan.o +callasterisk.o: callasterisk.cpp *.h Makefile + $(CC) -c $(CFLAGS) callasterisk.cpp -o callasterisk.o cause.o: cause.c *.h Makefile $(CC) -c $(CFLAGS) cause.c -o cause.o @@ -144,9 +148,6 @@ crypt.o: crypt.cpp *.h Makefile genext.o: genext.c *.h Makefile $(CC) -c $(CFLAGS) genext.c -o genext.o -#admin_client.o: admin_client.c *.h Makefile -# $(CC) -c $(CFLAGS) admin_client.c -o admin_client.o - admin_server.o: admin_server.c *.h Makefile $(CC) -c $(CFLAGS) admin_server.c -o admin_server.o @@ -181,7 +182,7 @@ $(LCR): main.o \ mail.o \ call.o \ callpbx.o \ - callchan.o \ + callasterisk.o \ admin_server.o \ trace.o $(LD) $(LIBDIR) \ @@ -208,7 +209,7 @@ $(LCR): main.o \ mail.o \ call.o \ callpbx.o \ - callchan.o \ + callasterisk.o \ admin_server.o \ trace.o \ $(LIBS) -o $(LCR) @@ -217,6 +218,10 @@ $(LCRADMIN): admin_client.c cause.c *.h Makefile $(CC) $(LIBDIR) $(CFLAGS) $(CURSES) -lm admin_client.c cause.c \ -o $(LCRADMIN) +$(CHAN_LCR): asterisk_client.c *.h Makefile + $(CC) $(LIBDIR) $(CFLAGS) $(CURSES) -lm asterisk_client.c \ + -o $(CHAN_LCR) + $(LCRWATCH): watch.c *.h Makefile $(CC) $(LIBDIR) $(CFLAGS) -lm watch.c \ -o $(LCRWATCH) @@ -245,6 +250,9 @@ install: -killall -9 -w -q lcr # the following error must be ignored cp $(LCR) $(INSTALL_BIN) cp $(LCRADMIN) $(INSTALL_BIN) +ifdef WITH_ASTERISK + cp $(CHAN_LCR) $(INSTALL_BIN) +endif # cp $(LCRWATCH) $(INSTALL_BIN) cp $(GEN) $(INSTALL_BIN) cp $(GENW) $(INSTALL_BIN) @@ -276,7 +284,7 @@ install: clean: touch * - rm -f $(LCR) $(LCRADMIN) $(LCRWATCH) $(GEN) $(GENW) $(GENRC) $(GENEXT) + rm -f $(LCR) $(LCRADMIN) $(CHAN_LCR) $(LCRWATCH) $(GEN) $(GENW) $(GENRC) $(GENEXT) rm -f *.o rm -f .*.c.sw* .*.cpp.sw* .*.h.sw* rm -f bla nohup.out diff --git a/README b/README index ca36835..9fea24b 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ -Read the documentation at ./doc/ and visit http://www.linux-call-router.de +Read the documentation at http://www.linux-call-router.de Changes in Version 20021228 @@ -334,4 +334,27 @@ Changes in Version 3.4 - Timeout condition seems to work now. - Timeout action seems to work now. +New Verion for new name: LCR + +Changes in Version 1.0 +- Statefull b-channel open and closing +- Rebuild audio flow + Made much simpler + Preloading and keeping transmit buffer for seamless tones and patterns. + Recording of what is actually transmitted and received by party. +- Logging is replaced by trace +- New isdn interface and port structure with many features + Interfaces can be changed at runtime. + Interfaces can be loaded and unloaded at runtime. +- mISDN stack fixes +- DDI in and out on all stacks +- Layer 1 over IP supports interconnection via IP +- Rebuild line and b-channel hunting with individual lists +- Screen lists for changing caller IDs +- Asterisk channel driver integrated +- Multiplexing calls to multiple extensions +- Removed all VoIP stuff to make core fast and stable (Use Asterisk for VoIP.) +- Many bug fixes +- Many minor improvements +- New bugs of course... diff --git a/action.cpp b/action.cpp index b77d937..3e8ba8b 100644 --- a/action.cpp +++ b/action.cpp @@ -67,12 +67,13 @@ char *numberrize_callerinfo(char *string, int ntype) /* - * process init 'internal' / 'external' / 'chan' / 'vbox-record' / 'partyline'... + * process init 'internal' / 'external' / 'asterisk' / 'vbox-record' / 'partyline'... */ -void EndpointAppPBX::_action_init_call(int chan) +void EndpointAppPBX::_action_init_call(int asterisk) { class Call *call; struct port_list *portlist = ea_endpoint->ep_portlist; + struct admin_list *admin; /* a created call, this should never happen */ if (ea_endpoint->ep_call_id) @@ -84,18 +85,29 @@ void EndpointAppPBX::_action_init_call(int chan) /* create call */ PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial); - if (chan) - call = new CallChan(ea_endpoint); + if (asterisk) + { + admin = admin_list; + while(admin) + { + if (admin->asterisk) + break; + admin = admin->next; + } + if (!admin) + { + /* resource not available */ + message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); + new_state(EPOINT_STATE_OUT_DISCONNECT); + set_tone(portlist,"cause_22"); + return; + } + call = new CallAsterisk(ea_endpoint->ep_serial); + } else call = new CallPBX(ea_endpoint); if (!call) - { - /* resource not available */ - message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_22"); - return; - } + FATAL("No memoy for Call instance.\n"); ea_endpoint->ep_call_id = call->c_serial; } void EndpointAppPBX::action_init_call(void) @@ -527,19 +539,13 @@ void EndpointAppPBX::action_init_partyline(void) /* create call */ PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial); if (!(call = new CallPBX(ea_endpoint))) - { - PERROR("no memory for call, exitting"); - exit(-1); - } + FATAL("No memory for Call object\n"); } else { //NOTE: callpbx must be set here /* add relation to existing call */ if (!(relation=callpbx->add_relation())) - { - PERROR("no memory for call relation, exitting"); - exit(-1); - } + FATAL("No memory for Call relation\n"); relation->type = RELATION_TYPE_SETUP; relation->channel_state = CHANNEL_STATE_CONNECT; relation->rx_state = NOTIFY_STATE_ACTIVE; diff --git a/admin.h b/admin.h index f5ca7d4..d3596ea 100644 --- a/admin.h +++ b/admin.h @@ -72,7 +72,7 @@ struct admin_response_interface { int l1link; /* down(0) or up(1) */ int l2link; /* down(0) or up(1) */ int channels; - int busy[256]; /* if port is idle(0) busy(1) */ + char busy[256]; /* if port is idle(0) busy(1) */ unsigned long port[256]; /* current port */ }; @@ -138,11 +138,11 @@ struct admin_trace_rsp { char text[1024]; }; -//struct admin_msg { -// int type; /* type of message */ -// unsigned long ref; /* reference to individual endpoints */ -// union parameter param; /* parameter union */ -//}; +struct admin_msg { + int type; /* type of message */ + unsigned long ref; /* reference to individual endpoints */ + union parameter param; /* parameter union */ +}; struct admin_message { int message; /* type of admin message */ @@ -154,7 +154,7 @@ struct admin_message { struct admin_response_epoint e; struct admin_response_call c; struct admin_call call; -// struct admin_msg msg; + struct admin_msg msg; struct admin_trace_req trace_req; struct admin_trace_rsp trace_rsp; } u; diff --git a/admin_client.c b/admin_client.c index 2bffa73..5ab45f6 100644 --- a/admin_client.c +++ b/admin_client.c @@ -20,9 +20,11 @@ #include #include #include -#include "save.h" +#include "macro.h" #include "call.h" #include "callpbx.h" +#include "extension.h" +#include "message.h" #include "admin.h" #include "cause.h" @@ -482,11 +484,7 @@ char *admin_state(int sock) return("Response not valid. Expecting state response."); } num = msg.u.s.interfaces + msg.u.s.calls + msg.u.s.epoints + msg.u.s.ports; - if (!(m = (struct admin_message *)malloc(num*sizeof(struct admin_message)))) - { - cleanup_curses(); - return("Not enough memory for messages."); - } + m = (struct admin_message *)MALLOC(num*sizeof(struct admin_message)); off=0; if (num) { @@ -494,7 +492,7 @@ char *admin_state(int sock) if ((len = read(sock, ((unsigned char *)(m))+off, num*sizeof(struct admin_message)-off)) != num*(int)sizeof(struct admin_message)-off) { if (len <= 0) { - free(m); + FREE(m, 0); // fprintf(stderr, "got=%d expected=%d\n", i, num*sizeof(struct admin_message)); cleanup_curses(); return("Broken pipe while receiving state infos."); @@ -514,7 +512,7 @@ char *admin_state(int sock) // fprintf(stderr, "j=%d message=%d\n", j, m[j].message); if (m[j].message != ADMIN_RESPONSE_S_INTERFACE) { - free(m); + FREE(m, 0); cleanup_curses(); return("Response not valid. Expecting interface information."); } @@ -526,7 +524,7 @@ char *admin_state(int sock) { if (m[j].message != ADMIN_RESPONSE_S_CALL) { - free(m); + FREE(m, 0); cleanup_curses(); return("Response not valid. Expecting call information."); } @@ -538,7 +536,7 @@ char *admin_state(int sock) { if (m[j].message != ADMIN_RESPONSE_S_EPOINT) { - free(m); + FREE(m, 0); cleanup_curses(); return("Response not valid. Expecting endpoint information."); } @@ -550,7 +548,7 @@ char *admin_state(int sock) { if (m[j].message != ADMIN_RESPONSE_S_PORT) { - free(m); + FREE(m, 0); cleanup_curses(); return("Response not valid. Expecting port information."); } @@ -946,7 +944,7 @@ char *admin_state(int sock) end: /* free memory */ - free(m); + FREE(m, 0); /* display name/time */ // move(0, 0); // hline(' ', COLS); diff --git a/admin_server.c b/admin_server.c index 1bb07af..c972ea5 100644 --- a/admin_server.c +++ b/admin_server.c @@ -86,11 +86,33 @@ int admin_init(void) /* * free connection + * also releases all asterisk joins */ void free_connection(struct admin_list *admin) { struct admin_queue *response; void *temp; + union parameter param; + class Call *call, *callnext; + + /* free asterisk joins */ + if (admin->asterisk) + { + call = call_first; + while(call) + { + callnext = call->next; + if (call->c_type == CALL_TYPE_ASTERISK) + { + memset(¶m, 0, sizeof(param)); + param.disconnectinfo.cause = CAUSE_OUTOFORDER; + param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + ((class CallAsterisk *)call)->message_asterisk(0, MESSAGE_RELEASE, ¶m); + /* call is now destroyed, so we go to next call */ + } + call = callnext; + } + } if (admin->sock >= 0) { @@ -104,12 +126,12 @@ void free_connection(struct admin_list *admin) //#warning // printf("%x\n", response); temp = response->next; - free(response); + FREE(response, 0); memuse--; response = (struct admin_queue *)temp; } // printf("new2\n", response); - free(admin); + FREE(admin, 0); // printf("new3\n", response); memuse--; } @@ -160,11 +182,8 @@ int admin_interface(struct admin_queue **responsep) err = -1; } /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_INTERFACE; @@ -274,11 +293,8 @@ int admin_route(struct admin_queue **responsep) response: /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_ROUTE; @@ -304,11 +320,8 @@ int admin_dial(struct admin_queue **responsep, char *message) char *p; /* pointer to dialing digits */ /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_DIAL; @@ -369,11 +382,8 @@ int admin_block(struct admin_queue **responsep, int portnum, int block) struct interface_port *ifport; /* create block response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_BLOCK; @@ -461,11 +471,8 @@ int admin_release(struct admin_queue **responsep, char *message) class EndpointAppPBX *apppbx; /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_CMD_RELEASE; @@ -504,14 +511,10 @@ int admin_call(struct admin_list *admin, struct admin_message *msg) class Endpoint *epoint; class EndpointAppPBX *apppbx; - if (!(epoint = new Endpoint(0,0))) - return(-1); - - if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint))) - { - PERROR("no memory for application\n"); - exit(-1); - } + if (!(epoint = new Endpoint(0, 0, 0))) + FATAL("No memory for Endpoint instance\n"); + if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint))) + FATAL("No memory for Endpoint Application instance\n"); apppbx->e_adminid = admin->sockserial; admin->epointid = epoint->ep_serial; SCPY(apppbx->e_callerinfo.id, nationalize_callerinfo(msg->u.call.callerid, &apppbx->e_callerinfo.ntype)); @@ -569,11 +572,8 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i } /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return; + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = message; @@ -591,6 +591,116 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i /* + * send data to the asterisk join instance + */ +int admin_message_to_join(struct admin_msg *msg) +{ + class Call *call; + struct admin_list *admin; + + /* dummy callref means: asterisk is here */ + if (msg->type == MESSAGE_HELLO) + { + /* look for second asterisk */ + admin = admin_list; + while(admin) + { + if (admin->asterisk) + break; + admin = admin->next; + } + if (admin) + { + PERROR("Asterisk connects twice??? (ignoring)\n"); + return(-1); + } + /* set asterisk socket instance */ + admin->asterisk = 1; + } + + /* find call instance */ + call = call_first; + while(call) + { + if (call->c_serial == msg->ref) + break; + call = call->next; + } + + /* create call instance if not existing */ + if (!call) + { + if (msg->ref < 2000000000) + { + PERROR("Asterisk sends us unknown ref %d below 2000000000.\n", msg->ref); + return(-1); + } + + /* create new call instance */ + call = new CallAsterisk(0); // must have no serial, because no endpoint is connected + if (!call) + FATAL("No memory for Asterisk Call instance\n"); + } + + /* send message */ + if (call->c_type != CALL_TYPE_ASTERISK) + FATAL("Call instance %d must be of type Call Asterisk\n", call->c_serial); + ((class CallAsterisk *)call)->message_asterisk(msg->ref, msg->type, &msg->param); + + return(0); +} + + +/* + * this function is called for every message to asterisk + */ +int admin_message_from_join(unsigned long ref, int message_type, union parameter *param) +{ + struct admin_list *admin; + struct admin_queue *response, **responsep; /* response pointer */ + + /* searching for admin id + * maybe there is no asterisk instance + */ + admin = admin_list; + while(admin) + { + if (admin->asterisk) + break; + admin = admin->next; + } + /* no asterisk connected */ + if (!admin) + return(-1); + + /* seek to end of response list */ + response = admin->response; + responsep = &admin->response; + while(response) + { + responsep = &response->next; + response = response->next; + } + + /* create state response */ + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); + memuse++; + response->num = 1; + + /* message */ + response->am[0].u.msg.type = message_type; + response->am[0].u.msg.ref = ref; + memcpy(&response->am[0].u.msg.param, param, sizeof(union parameter)); + + /* attach to response chain */ + *responsep = response; + responsep = &response->next; + + return(0); +} + + +/* * do state debugging */ int admin_state(struct admin_queue **responsep) @@ -609,11 +719,8 @@ int admin_state(struct admin_queue **responsep) struct admin_queue *response; /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_RESPONSE_STATE; @@ -672,11 +779,8 @@ int admin_state(struct admin_queue **responsep) num = (response->am[0].u.s.interfaces)+(response->am[0].u.s.calls)+(response->am[0].u.s.epoints)+(response->am[0].u.s.ports); if (num == 0) return(0); - response = (struct admin_queue *)malloc(sizeof(admin_queue)+(num*sizeof(admin_message))); - if (!response) - return(-1); + response = (struct admin_queue *)MALLOC(sizeof(admin_queue)+(num*sizeof(admin_message))); memuse++; - memset(response, 0, sizeof(admin_queue)+(num*sizeof(admin_message))); response->num = num; *responsep = response; responsep = &response->next; @@ -917,26 +1021,21 @@ int admin_handle(void) { work = 1; /* insert new socket */ - admin = (struct admin_list *)malloc(sizeof(struct admin_list)); - if (admin) + admin = (struct admin_list *)MALLOC(sizeof(struct admin_list)); + if (ioctl(new_sock, FIONBIO, (unsigned char *)(&on)) >= 0) { - if (ioctl(new_sock, FIONBIO, (unsigned char *)(&on)) >= 0) - { //#warning // PERROR("DEBUG incomming socket %d, serial=%d\n", new_sock, sockserial); - memuse++; - fhuse++; - memset(admin, 0, sizeof(struct admin_list)); - admin->sockserial = sockserial++; - admin->next = admin_list; - admin_list = admin; - admin->sock = new_sock; - } else { - close(new_sock); - free(admin); - } - } else + memuse++; + fhuse++; + admin->sockserial = sockserial++; + admin->next = admin_list; + admin_list = admin; + admin->sock = new_sock; + } else { close(new_sock); + FREE(admin, sizeof(struct admin_list)); + } } else { if (errno != EWOULDBLOCK) @@ -1070,15 +1169,12 @@ int admin_handle(void) } break; -#warning interface tbd -#if 0 case ADMIN_MESSAGE: - if (admin_message(&admin->response) < 0) + if (admin_message_to_join(&msg.u.msg) < 0) { - PERROR("Failed to create message response for socket %d.\n", admin->sock); + PERROR("Failed to deliver message for socket %d.\n", admin->sock); goto response_error; } -#endif #if 0 #warning DEBUGGING { @@ -1141,7 +1237,7 @@ int admin_handle(void) { temp = admin->response; admin->response = admin->response->next; - free(temp); + FREE(temp, 0); memuse--; } } diff --git a/admin_server.h b/admin_server.h index 1b472bb..d83c451 100644 --- a/admin_server.h +++ b/admin_server.h @@ -22,6 +22,7 @@ struct admin_list { struct admin_list *next; int sock; int sockserial; + int asterisk; /* socket is connected to asterisk */ struct admin_trace_req trace; /* stores trace, if detail != 0 */ unsigned long epointid; struct admin_queue *response; @@ -32,6 +33,8 @@ int admin_init(void); void admin_cleanup(void); int admin_handle(void); void admin_call_response(int adminid, int message, char *connected, int cause, int location, int notify); +int admin_message_to_join(struct admin_message *msg); +int admin_message_from_join(unsigned long ref, int message_type, union parameter *param); diff --git a/apppbx.cpp b/apppbx.cpp index 06ff785..23e20ac 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -1,6 +1,6 @@ /*****************************************************************************\ ** ** -** PBX4Linux ** +** LCR ** ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** @@ -126,10 +126,7 @@ EndpointAppPBX::~EndpointAppPBX(void) temp = temp->next; } if (temp == 0) - { - PERROR("error: endpoint not in endpoint's list, exitting.\n"); - exit(-1); - } + FATAL("Endpoint not in endpoint's list.\n"); *tempp = next; } @@ -180,165 +177,152 @@ void EndpointAppPBX::new_state(int state) /* screen caller id * out==0: incomming caller id, out==1: outgoing caller id */ -void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present) +void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface) { - struct interface *interface; char *msn1; struct interface_msn *ifmsn; struct interface_screen *ifscreen; char suffix[64]; - interface = interface_first; - while(interface) + /* screen incoming caller id */ + if (!out) { - if (!strcmp(e_callerinfo.interface, interface->name)) + /* check for MSN numbers, use first MSN if no match */ + msn1 = NULL; + ifmsn = interface->ifmsn; + while(ifmsn) { - break; + if (!msn1) + msn1 = ifmsn->msn; + if (!strcmp(ifmsn->msn, id)) + { + break; + } + ifmsn = ifmsn->next; + } + if (ifmsn) + { + trace_header("SCREEN (found in list)", DIRECTION_IN); + add_trace("msn", NULL, "%s", id); + end_trace(); + } + if (!ifmsn && msn1) // not in list, first msn given + { + trace_header("SCREEN (not found in list)", DIRECTION_IN); + add_trace("msn", "given", "%s", id); + add_trace("msn", "used", "%s", msn1); + end_trace(); + UNCPY(id, msn1, idsize); + id[idsize-1] = '\0'; } - interface = interface->next; } - if (interface) + + /* check screen list */ + if (out) + ifscreen = interface->ifscreen_out; + else + ifscreen = interface->ifscreen_in; + while (ifscreen) { - /* screen incoming caller id */ - if (!out) + if (ifscreen->match_type==-1 || ifscreen->match_type==*type) + if (ifscreen->match_present==-1 || ifscreen->match_present==*present) { - /* check for MSN numbers, use first MSN if no match */ - msn1 = NULL; - ifmsn = interface->ifmsn; - while(ifmsn) + if (strchr(ifscreen->match,'%')) { - if (!msn1) - msn1 = ifmsn->msn; - if (!strcmp(ifmsn->msn, id)) - { + if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match)) break; - } - ifmsn = ifmsn->next; - } - if (ifmsn) - { - trace_header("SCREEN (found in list)", DIRECTION_IN); - add_trace("msn", NULL, "%s", id); - end_trace(); - } - if (!ifmsn && msn1) // not in list, first msn given + } else { - trace_header("SCREEN (not found in list)", DIRECTION_IN); - add_trace("msn", "given", "%s", id); - add_trace("msn", "used", "%s", msn1); - end_trace(); - UNCPY(id, msn1, idsize); - id[idsize-1] = '\0'; + if (!strcmp(ifscreen->match, id)) + break; } } - - /* check screen list */ - if (out) - ifscreen = interface->ifscreen_out; - else - ifscreen = interface->ifscreen_in; - while (ifscreen) + ifscreen = ifscreen->next; + } + if (ifscreen) // match + { + trace_header("SCREEN (found in list)", out?DIRECTION_OUT:DIRECTION_IN); + switch(*type) { - if (ifscreen->match_type==-1 || ifscreen->match_type==*type) - if (ifscreen->match_present==-1 || ifscreen->match_present==*present) - { - if (strchr(ifscreen->match,'%')) - { - if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match)) - break; - } else - { - if (!strcmp(ifscreen->match, id)) - break; - } - } - ifscreen = ifscreen->next; + case INFO_NTYPE_UNKNOWN: + add_trace("given", "type", "unknown"); + break; + case INFO_NTYPE_SUBSCRIBER: + add_trace("given", "type", "subscriber"); + break; + case INFO_NTYPE_NATIONAL: + add_trace("given", "type", "national"); + break; + case INFO_NTYPE_INTERNATIONAL: + add_trace("given", "type", "international"); + break; + } + switch(*present) + { + case INFO_PRESENT_ALLOWED: + add_trace("given", "present", "allowed"); + break; + case INFO_PRESENT_RESTRICTED: + add_trace("given", "present", "restricted"); + break; + case INFO_PRESENT_NOTAVAIL: + add_trace("given", "present", "not available"); + break; } - if (ifscreen) // match + add_trace("given", "id", "%s", id[0]?id:""); + if (ifscreen->result_type != -1) { - trace_header("SCREEN (found in list)", out?DIRECTION_OUT:DIRECTION_IN); + *type = ifscreen->result_type; switch(*type) { case INFO_NTYPE_UNKNOWN: - add_trace("given", "type", "unknown"); + add_trace("used", "type", "unknown"); break; case INFO_NTYPE_SUBSCRIBER: - add_trace("given", "type", "subscriber"); + add_trace("used", "type", "subscriber"); break; case INFO_NTYPE_NATIONAL: - add_trace("given", "type", "national"); + add_trace("used", "type", "national"); break; case INFO_NTYPE_INTERNATIONAL: - add_trace("given", "type", "international"); + add_trace("used", "type", "international"); break; } + } + if (ifscreen->result_present != -1) + { + *present = ifscreen->result_present; switch(*present) { case INFO_PRESENT_ALLOWED: - add_trace("given", "present", "allowed"); + add_trace("used", "present", "allowed"); break; case INFO_PRESENT_RESTRICTED: - add_trace("given", "present", "restricted"); + add_trace("used", "present", "restricted"); break; case INFO_PRESENT_NOTAVAIL: - add_trace("given", "present", "not available"); + add_trace("used", "present", "not available"); break; } - add_trace("given", "id", "%s", id[0]?id:""); - if (ifscreen->result_type != -1) - { - *type = ifscreen->result_type; - switch(*type) - { - case INFO_NTYPE_UNKNOWN: - add_trace("used", "type", "unknown"); - break; - case INFO_NTYPE_SUBSCRIBER: - add_trace("used", "type", "subscriber"); - break; - case INFO_NTYPE_NATIONAL: - add_trace("used", "type", "national"); - break; - case INFO_NTYPE_INTERNATIONAL: - add_trace("used", "type", "international"); - break; - } - } - if (ifscreen->result_present != -1) - { - *present = ifscreen->result_present; - switch(*present) - { - case INFO_PRESENT_ALLOWED: - add_trace("used", "present", "allowed"); - break; - case INFO_PRESENT_RESTRICTED: - add_trace("used", "present", "restricted"); - break; - case INFO_PRESENT_NOTAVAIL: - add_trace("used", "present", "not available"); - break; - } - } - if (strchr(ifscreen->match,'%')) - { - SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id); - UNCPY(id, ifscreen->result, idsize); - id[idsize-1] = '\0'; - if (strchr(ifscreen->result,'%')) - { - *strchr(ifscreen->result,'%') = '\0'; - UNCAT(id, suffix, idsize); - id[idsize-1] = '\0'; - } - } else + } + if (strchr(ifscreen->match,'%')) + { + SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id); + UNCPY(id, ifscreen->result, idsize); + id[idsize-1] = '\0'; + if (strchr(ifscreen->result,'%')) { - UNCPY(id, ifscreen->result, idsize); + *strchr(ifscreen->result,'%') = '\0'; + UNCAT(id, suffix, idsize); id[idsize-1] = '\0'; } - add_trace("used", "id", "%s", id[0]?id:""); - end_trace(); + } else + { + UNCPY(id, ifscreen->result, idsize); + id[idsize-1] = '\0'; } + add_trace("used", "id", "%s", id[0]?id:""); + end_trace(); } } @@ -349,7 +333,6 @@ void EndpointAppPBX::release(int release, int calllocation, int callcause, int p struct port_list *portlist; struct message *message; char cause[16]; - class Call *call; /* message to test call */ admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0); @@ -360,11 +343,12 @@ void EndpointAppPBX::release(int release, int calllocation, int callcause, int p PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation); if (ea_endpoint->ep_call_id) { - call = find_call_id(ea_endpoint->ep_call_id); - if (call) - call->release(ea_endpoint->ep_serial, 0, calllocation, callcause); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = callcause; + message->param.disconnectinfo.location = calllocation; + message_put(message); + ea_endpoint->ep_call_id = 0; } - ea_endpoint->ep_call_id = 0; e_call_pattern = 0; #if 0 if (release != RELEASE_PORT_CALLONLY) @@ -848,7 +832,7 @@ foundif: goto portbusy; } - /* see if link is up */ + /* see if link is up on PTP*/ if (mISDNport->ptp && !mISDNport->l2link) { trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE); @@ -1137,10 +1121,7 @@ void EndpointAppPBX::out_setup(void) SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum); port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force); if (!port) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port '%s' failed to create\n", ea_endpoint->ep_serial, mISDNport->ifport->interface->name); - goto check_anycall_intern; - } + FATAL("No memory for DSS1 Port instance\n"); PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name); memset(&dialinginfo, 0, sizeof(dialinginfo)); SCPY(dialinginfo.id, e_dialinginfo.id); @@ -1228,10 +1209,7 @@ void EndpointAppPBX::out_setup(void) PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial); /* alloc port */ if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings))) - { - PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial); - break; - } + FATAL("No memory for VBOX Port instance\n"); PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name); UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */ } else @@ -1249,7 +1227,8 @@ void EndpointAppPBX::out_setup(void) { /* creating EXTERNAL port*/ SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum); - port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force); + if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force))) + FATAL("No memory for DSS1 Port instance\n"); earlyb = mISDNport->earlyb; } else { @@ -1333,24 +1312,18 @@ void EndpointAppPBX::out_setup(void) /* hunt for mISDNport and create Port */ /* hunt for mISDNport and create Port */ mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel); - if (mISDNport) - { - /* creating EXTERNAL port*/ - SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum); - port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force); - earlyb = mISDNport->earlyb; - } else + if (!mISDNport) { trace_header("INTERFACE (too busy)", DIRECTION_NONE); add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface"); end_trace(); goto check_anycall_extern; } - if (!port) - { - PERROR("EPOINT(%d) no memory for external port, exitting\n", ea_endpoint->ep_serial); - exit(-1); - } + /* creating EXTERNAL port*/ + SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum); + if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force))) + FATAL("No memory for DSS1 Port instance\n"); + earlyb = mISDNport->earlyb; PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name); memset(&dialinginfo, 0, sizeof(dialinginfo)); SCPY(dialinginfo.id, number); @@ -1632,6 +1605,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un char buffer[256]; int writeext; /* flags need to write extension after modification */ class Port *port; + struct interface *interface; portlist->port_type = param->setup.port_type; memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo)); @@ -1641,7 +1615,17 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un e_dtmf = param->setup.dtmf; /* screen incoming caller id */ - screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present); + interface = interface_first; + while(interface) + { + if (!strcmp(e_callerinfo.interface, interface->name)) + { + break; + } + interface = interface->next; + } + if (interface) + screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface); /* process extension */ if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) @@ -2143,6 +2127,7 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, unsigned long port_id = portlist->port_id; struct port_list *tportlist; class Port *port; + struct interface *interface; /* signal to call tool */ admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0); @@ -2162,12 +2147,9 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */ tportlist = tportlist->next; if (tportlist->port_id == port_id) - { - PERROR("EPOINT(%d) software error: this should not happen since the portlist list must not have two links to the same port - exitting.\n"); - exit(-1); - } + FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n"); message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE); - message->param.disconnectinfo.cause = 26; /* non selected user clearing */ + message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */ message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); logmessage(message); @@ -2178,7 +2160,17 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, e_start = now; /* screen incoming connected id */ - screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present); + interface = interface_first; + while(interface) + { + if (!strcmp(e_connectinfo.interface, interface->name)) + { + break; + } + interface = interface->next; + } + if (interface) + screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface); /* screen connected name */ if (e_ext.name[0]) @@ -2188,7 +2180,7 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, SCPY(e_connectinfo.extension, e_ext.number); /* we store the connected port number */ - SCPY(e_extension_interface, e_connectinfo.interfaces); + SCPY(e_extension_interface, e_connectinfo.interface); /* for internal and am calls, we get the extension's id */ if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) @@ -2367,31 +2359,7 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes /* collect cause */ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current multipoint cause %d location %d, received cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location); - if (param->disconnectinfo.cause == CAUSE_REJECTED) /* call rejected */ - { - e_multipoint_cause = CAUSE_REJECTED; - e_multipoint_location = param->disconnectinfo.location; - } else - if (param->disconnectinfo.cause==CAUSE_NORMAL && e_multipoint_cause!=CAUSE_REJECTED) /* reject via hangup */ - { - e_multipoint_cause = CAUSE_NORMAL; - e_multipoint_location = param->disconnectinfo.location; - } else - if (param->disconnectinfo.cause==CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* busy */ - { - e_multipoint_cause = CAUSE_BUSY; - e_multipoint_location = param->disconnectinfo.location; - } else - if (param->disconnectinfo.cause==CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* no L1 */ - { - e_multipoint_cause = CAUSE_OUTOFORDER; - e_multipoint_location = param->disconnectinfo.location; - } else - if (param->disconnectinfo.cause!=CAUSE_NOUSER && e_multipoint_cause!=CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* anything but not 18 */ - { - e_multipoint_cause = param->disconnectinfo.cause; - e_multipoint_location = param->disconnectinfo.location; - } + collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location); PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location); /* check if we have more than one portlist relation and we just ignore the disconnect */ @@ -2406,10 +2374,7 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes portlist = portlist->next; } if (!portlist) - { - PERROR("EPOINT(%d) software error: no portlist related to the calling port.\n", ea_endpoint->ep_serial); - exit(-1); - } + FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial); if (message_type != MESSAGE_RELEASE) { message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE); @@ -2421,14 +2386,16 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes ea_endpoint->free_portlist(portlist); return; /* one relation removed */ } - if (e_multipoint_cause) - { - cause = e_multipoint_cause; - location = e_multipoint_location; - } else + if (e_state == EPOINT_STATE_CONNECT) { + /* use cause from port after connect */ cause = param->disconnectinfo.cause; location = param->disconnectinfo.location; + } else + { + /* use multipoint cause if no connect yet */ + cause = e_multipoint_cause; + location = e_multipoint_location; } e_cfnr_call = e_cfnr_release = 0; @@ -2781,23 +2748,14 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un switch(message_type) { case MESSAGE_DATA: /* data from port */ - /* send back to source for recording */ - if (port_id) - { - message = message_create(ea_endpoint->ep_serial, port_id, EPOINT_TO_PORT, message_type); - memcpy(&message->param, param, sizeof(union parameter)); - message_put(message); - } - /* check if there is a call */ if (!ea_endpoint->ep_call_id) break; /* continue if only one portlist */ if (ea_endpoint->ep_portlist->next != NULL) break; - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type); - memcpy(&message->param, param, sizeof(union parameter)); - message_put(message); + /* forward message */ + message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, param); break; case MESSAGE_TONE_EOF: /* tone is end of file */ @@ -3117,6 +3075,7 @@ void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param) { struct message *message; + struct interface *interface; new_state(EPOINT_STATE_CONNECT); // UCPY(e_call_tone, ""); @@ -3129,7 +3088,17 @@ void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); memcpy(&message->param, param, sizeof(union parameter)); /* screen incoming caller id */ - screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present); + interface = interface_first; + while(interface) + { + if (!strcmp(e_connectinfo.interface, interface->name)) + { + break; + } + interface = interface->next; + } + if (interface) + screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface); memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo)); /* screen clip if prefix is required */ @@ -3284,6 +3253,7 @@ void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int mes void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param) { struct message *message; + struct interface *interface; /* if we already in setup state, we just update the dialing with new digits */ if (e_state == EPOINT_STATE_OUT_SETUP @@ -3381,7 +3351,17 @@ void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, un memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo)); /* screen incoming caller id */ - screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present); + interface = interface_first; + while(interface) + { + if (!strcmp(e_callerinfo.interface, interface->name)) + { + break; + } + interface = interface->next; + } + if (interface) + screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface); /* process (voice over) data calls */ if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) @@ -3487,9 +3467,9 @@ void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, un portlist = ea_endpoint->ep_portlist; /* send MESSAGE_DATA to port */ - if (call_id == ea_endpoint->ep_call_id) + if (message_type == MESSAGE_DATA) { - if (message_type == MESSAGE_DATA) + if (call_id == ea_endpoint->ep_call_id) // still linked with call { /* skip if no port relation */ if (!portlist) @@ -3497,10 +3477,8 @@ void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, un /* skip if more than one port relation */ if (portlist->next) return; - /* send audio data to port */ - message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DATA); - memcpy(&message->param, param, sizeof(union parameter)); - message_put(message); + /* forward audio data to port */ + message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param); return; } } @@ -3833,7 +3811,7 @@ reject: /* now we send a release to the ringing endpoint */ message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE); - message->param.disconnectinfo.cause = 26; /* non selected user clearing */ + message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */ message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); @@ -4023,8 +4001,7 @@ void EndpointAppPBX::join_call(void) { /* detach other endpoint on hold */ *other_relation_pointer = other_relation->next; - memset(other_relation, 0, sizeof(struct call_relation)); - free(other_relation); + FREE(other_relation, sizeof(struct call_relation)); cmemuse--; other_relation = *other_relation_pointer; other_eapp->ea_endpoint->ep_call_id = NULL; diff --git a/apppbx.h b/apppbx.h index a3fa660..a4baef1 100644 --- a/apppbx.h +++ b/apppbx.h @@ -347,7 +347,7 @@ class EndpointAppPBX : public EndpointApp void message_disconnect_port(struct port_list *portlist, int cause, int location, char *display); void logmessage(struct message *messsage); void trace_header(char *name, int direction); - void screen(int out, char *id, int idsize, int *type, int *present); + void screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface); }; diff --git a/call.cpp b/call.cpp index a566080..38f6b19 100644 --- a/call.cpp +++ b/call.cpp @@ -51,15 +51,10 @@ class Call *find_call_id(unsigned long call_id) /* * constructor for a new call */ -Call::Call(class Endpoint *epoint) +Call::Call(void) { class Call **callp; - if (!epoint) - { - PERROR("software error, epoint is NULL.\n"); - exit(-1); - } c_serial = call_serial++; c_type = CALL_TYPE_NONE; @@ -93,10 +88,7 @@ Call::~Call() cl = cl->next; } if (!cl) - { - PERROR("software error, call not in chain! exitting\n"); - exit(-1); - } + FATAL("software error, call not in chain!\n"); *clp = cl->next; /* detach from chain */ } @@ -119,10 +111,6 @@ int Call::handler(void) return(0); } -void Call::release(unsigned long epoint_id, int hold, int location, int cause) -{ -} - /* free all call structures */ void call_free(void) { diff --git a/call.h b/call.h index 2315b56..80e6887 100644 --- a/call.h +++ b/call.h @@ -20,12 +20,11 @@ enum { CALL_TYPE_NONE, CALL_TYPE_PBX, CALL_TYPE_ASTERISK}; class Call { public: - Call(class Endpoint *epoint); + Call(); virtual ~Call(); class Call *next; /* next node in list of calls */ virtual void message_epoint(unsigned long epoint_id, int message, union parameter *param); virtual int handler(void); - virtual void release(unsigned long epoint_id, int hold, int location, int cause); unsigned long c_type; /* call type (pbx or asterisk) */ unsigned long c_serial; /* serial/unique number of call */ diff --git a/callpbx.cpp b/callpbx.cpp index 418654d..7fede81 100644 --- a/callpbx.cpp +++ b/callpbx.cpp @@ -237,16 +237,13 @@ void callpbx_debug(class CallPBX *callpbx, char *function) * constructor for a new call * the call will have a relation to the calling endpoint */ -CallPBX::CallPBX(class Endpoint *epoint) : Call(epoint) +CallPBX::CallPBX(class Endpoint *epoint) : Call() { struct call_relation *relation; // char filename[256]; if (!epoint) - { - PERROR("software error, epoint is NULL.\n"); - exit(-1); - } + FATAL("epoint is NULL.\n"); PDEBUG(DEBUG_CALL, "creating new call and connecting it to the endpoint.\n"); @@ -258,16 +255,12 @@ CallPBX::CallPBX(class Endpoint *epoint) : Call(epoint) c_pid = getpid(); c_updatebridge = 0; c_partyline = 0; + c_multicause = CAUSE_NOUSER; + c_multilocation = LOCATION_PRIVATE_LOCAL; /* initialize a relation only to the calling interface */ - relation = c_relation = (struct call_relation *)calloc(1, sizeof(struct call_relation)); - if (!relation) - { - PERROR("no memory, exitting..\n"); - exit(-1); - } + relation = c_relation = (struct call_relation *)MALLOC(sizeof(struct call_relation)); cmemuse++; - memset(relation, 0, sizeof(struct call_relation)); relation->type = RELATION_TYPE_CALLING; relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */ relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */ @@ -291,8 +284,7 @@ CallPBX::~CallPBX() while(relation) { rtemp = relation->next; - memset(relation, 0, sizeof(struct call_relation)); - free(relation); + FREE(relation, sizeof(struct call_relation)); cmemuse--; relation = rtemp; } @@ -310,8 +302,11 @@ void CallPBX::bridge(void) class Endpoint *epoint; struct port_list *portlist; class Port *port; - int allmISDN = 0; // set until a non-mISDN relation is found -fix: +#ifdef DEBUG_COREBRIDGE + int allmISDN = 0; // never set for debug purpose +#else + int allmISDN = 1; // set until a non-mISDN relation is found +#endif relation = c_relation; while(relation) @@ -456,7 +451,6 @@ fix: void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param) { struct call_relation *relation_to; - struct message *message; /* if we are alone */ if (!c_relation->next) @@ -485,79 +479,55 @@ void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relat /* now we may send our data to the endpoint where it * will be delivered to the port */ -//PDEBUG(DEBUG_CALL, "mixing from %d to %d\n", epoint_from, relation_to->epoint_id); -printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id); - message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA); - memcpy(&message->param, param, sizeof(union parameter)); - message_put(message); +//printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id); + message_forward(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, param); } - /* release call from endpoint * if the call has two relations, all relations are freed and the call will be - * destroyed + * destroyed + * on outgoing relations, the cause is collected, if not connected + * returns if call has been destroyed */ -void CallPBX::release(unsigned long epoint_id, int hold, int location, int cause) +int CallPBX::release(struct call_relation *relation, int location, int cause) { - struct call_relation *relation, **relationpointer; + struct call_relation *reltemp, **relationpointer; struct message *message; - class Call *call; - - if (!epoint_id) - { - PERROR("software error, epoint is NULL.\n"); - return; - } - - if (options.deb & DEBUG_CALL) - callpbx_debug(this, "call_release{before}"); - - /* find relation */ - relation = c_relation; - while(relation) - { - if (relation->epoint_id == epoint_id) - break; - relation = relation->next; - } - if (!relation) - { - PERROR("software error, epoint has a call with no relation to the epoint.\n"); - return; - } + int destroy = 0; /* remove from bridge */ if (relation->channel_state != CHANNEL_STATE_HOLD) { relation->channel_state = CHANNEL_STATE_HOLD; c_updatebridge = 1; /* update bridge flag */ + // note: if call is not released, bridge must be updated } /* detach given interface */ - relation = c_relation; + reltemp = c_relation; relationpointer = &c_relation; - while(relation) + while(reltemp) { /* endpoint of function call */ - if (relation->epoint_id == epoint_id) - { - *relationpointer = relation->next; - memset(relation, 0, sizeof(struct call_relation)); - free(relation); - cmemuse--; - relation = *relationpointer; - continue; - } - relationpointer = &relation->next; - relation = relation->next; + if (relation == reltemp) + break; + relationpointer = &reltemp->next; + reltemp = reltemp->next; } + if (!reltemp) + FATAL("relation not in list of our relations. this must not happen.\n"); + *relationpointer = reltemp->next; + FREE(reltemp, sizeof(struct call_relation)); + cmemuse--; + relation = reltemp = NULL; // just in case of reuse fault; /* if no more relation */ if (!c_relation) { PDEBUG(DEBUG_CALL, "call is completely removed.\n"); /* there is no more endpoint related to the call */ + destroy = 1; delete this; // end of call object! PDEBUG(DEBUG_CALL, "call completely removed!\n"); @@ -575,6 +545,7 @@ void CallPBX::release(unsigned long epoint_id, int hold, int location, int cause message->param.disconnectinfo.cause = cause; message->param.disconnectinfo.location = location; message_put(message); + destroy = 1; delete this; // end of call object! PDEBUG(DEBUG_CALL, "call completely removed!\n"); @@ -588,6 +559,7 @@ void CallPBX::release(unsigned long epoint_id, int hold, int location, int cause call = call->next; } PDEBUG(DEBUG_CALL, "call_release(): ended.\n"); + return(destroy); } /* count number of relations in a call @@ -646,8 +618,7 @@ void CallPBX::remove_relation(struct call_relation *relation) PDEBUG(DEBUG_CALL, "removing relation.\n"); *tempp = relation->next; - memset(temp, 0, sizeof(struct call_relation)); - free(temp); + FREE(temp, sizeof(struct call_relation)); cmemuse--; } @@ -665,14 +636,8 @@ struct call_relation *CallPBX::add_relation(void) while(relation->next) relation = relation->next; - relation->next = (struct call_relation *)calloc(1, sizeof(struct call_relation)); - if (!relation->next) - { - PERROR("no memory\n"); - return(NULL); - } + relation->next = (struct call_relation *)MALLOC(sizeof(struct call_relation)); cmemuse++; - memset(relation->next, 0, sizeof(struct call_relation)); /* the record pointer is set at the first time the data is received for the relation */ // if (options.deb & DEBUG_CALL) @@ -686,7 +651,7 @@ struct call_relation *CallPBX::add_relation(void) void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param) { class Call *cl; - struct call_relation *relation, *rel; + struct call_relation *relation, *reltemp; int num; int new_state; struct message *message; @@ -728,7 +693,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa } if (!relation) { -// PERROR("no relation back to the endpoint found, ignoring (call=%d, endpoint=%d\n", c_serial, epoint_id); + PDEBUG(DEBUG_CALL, "no relation back to the endpoint found, ignoring (call=%d, endpoint=%d)\n", c_serial, epoint_id); return; } @@ -768,16 +733,16 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa default: /* send notification to all other endpoints */ - rel = c_relation; - while(rel) + reltemp = c_relation; + while(reltemp) { - if (rel->epoint_id!=epoint_id && rel->epoint_id) + if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id) { - message = message_create(c_serial, rel->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY); + message = message_create(c_serial, reltemp->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY); memcpy(&message->param, param, sizeof(union parameter)); message_put(message); } - rel = rel->next; + reltemp = reltemp->next; } } return; @@ -787,6 +752,40 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa /* now send audio data to the other endpoint */ bridge_data(epoint_id, relation, param); return; + + /* relations sends a connect */ + case MESSAGE_CONNECT: + /* outgoing setup type becomes connected */ + if (relation->type == RELATION_TYPE_SETUP) + relation->type = RELATION_TYPE_CONNECT; + /* release other relations in setup state */ + release_again: + relation = c_relation; + while(relation) + { + if (relation->type == RELATION_TYPE_SETUP) + { + if (release(relation, LOCATION_PRIVATE_LOCAL, CAUSE_NONSELECTED)) + return; // must return, because call IS destroyed + goto release_again; + } + relation = relation->next; + } + break; // continue with our message + + /* release is sent by endpoint */ + case MESSAGE_RELEASE: + if (relation->type == RELATION_TYPE_SETUP) + { + /* collect cause and send collected cause */ + collect_cause(&c_multicause, &c_multilocation, param->disconnectinfo.cause, param->disconnectinfo.location); + release(relation, c_multilocation, c_multicause); + } else + { + /* send current cause */ + release(relation, param->disconnectinfo.location, param->disconnectinfo.cause); + } + return; // must return, because call may be destroyed } /* process party line */ @@ -804,12 +803,10 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa if (message_type == MESSAGE_DISCONNECT) { PDEBUG(DEBUG_CALL, "releasing after receiving disconnect, because call in partyline mode.\n"); -// remove_relation(relation); message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE); message->param.disconnectinfo.cause = CAUSE_NORMAL; message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); -// c_updatebridge = 1; /* update bridge flag */ return; } } @@ -942,39 +939,17 @@ int CallPBX::out_setup(unsigned long epoint_id, int message_type, union paramete PDEBUG(DEBUG_CALL, "no endpoint found, so we will create an endpoint and send the setup message we have.\n"); /* create a new relation */ if (!(relation=add_relation())) - { - /* release due to error */ - ressource_error: - relation = c_relation; - while(relation) - { - message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE); - message->param.disconnectinfo.cause = (relation->epoint_id==epoint_id)?CAUSE_RESSOURCEUNAVAIL:CAUSE_NORMAL; - message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; - message_put(message); - relation = relation->next; - } - delete this; - return(-ENOMEM); - } + FATAL("No memory for relation.\n"); relation->type = RELATION_TYPE_SETUP; relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */ relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */ relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */ /* create a new endpoint */ - epoint = new Endpoint(0, c_serial); + epoint = new Endpoint(0, c_serial, 0); if (!epoint) - { - remove_relation(relation); - goto ressource_error; - } + FATAL("No memory for Endpoint instance\n"); if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint))) - { - PERROR("ERROR:No endpoint's app.\n"); - delete epoint; - remove_relation(relation); - goto ressource_error; - } + FATAL("No memory for Endpoint Application instance\n"); relation->epoint_id = epoint->ep_serial; /* send setup message to new endpoint */ //printf("JOLLY DEBUG: %d\n",call_countrelations(c_serial)); @@ -989,3 +964,4 @@ int CallPBX::out_setup(unsigned long epoint_id, int message_type, union paramete return(0); } + diff --git a/callpbx.h b/callpbx.h index c84d89a..755bdc5 100644 --- a/callpbx.h +++ b/callpbx.h @@ -56,12 +56,13 @@ class CallPBX : public Call ~CallPBX(); void message_epoint(unsigned long epoint_id, int message, union parameter *param); int handler(void); - void release(unsigned long epoint_id, int hold, int location, int cause); + int release(struct call_relation *relation, int location, int cause); char c_caller[32]; /* caller number */ char c_caller_id[32]; /* caller id to signal */ char c_dialed[1024]; /* dial string of (all) number(s) */ char c_todial[32]; /* overlap dialing (part not signalled yet) */ + int c_multicause, c_multilocation; int c_pid; /* pid of call to generate bridge id */ int c_updatebridge; /* bridge must be updated */ diff --git a/cause.c b/cause.c index c6ca903..42fdb29 100644 --- a/cause.c +++ b/cause.c @@ -373,3 +373,41 @@ char *get_isdn_cause(int cause, int location, int type) return(result); } + +/* + * collect cause for multipoint + * used by Process, Endpoint and Join instance when multiplexing + */ +void collect_cause(int *multicause, int *multilocation, int newcause, int newlocation) +{ + if (newcause == CAUSE_REJECTED) /* call rejected */ + { + *multicause = newcause; + *multilocation = newlocation; + } else + if (newcause==CAUSE_NORMAL && *multicause!=CAUSE_REJECTED) /* reject via hangup */ + { + *multicause = newcause; + *multilocation = newlocation; + } else + if (newcause==CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) /* busy */ + { + *multicause = newcause; + *multilocation = newlocation; + } else + if (newcause==CAUSE_OUTOFORDER && *multicause!=CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) /* no L1 */ + { + *multicause = newcause; + *multilocation = newlocation; + } else + if (newcause!=CAUSE_NOUSER && *multicause!=CAUSE_OUTOFORDER && *multicause!=CAUSE_BUSY && *multicause!=CAUSE_REJECTED && *multicause!=CAUSE_NORMAL) /* anything but not 18 */ + { + *multicause = newcause; + *multilocation = newlocation; + } else + if (newcause==CAUSE_NOUSER && *multicause==CAUSE_NOUSER) /* cause 18, but no cause yet, use the location */ + { + *multilocation = newlocation; + } +} + diff --git a/cause.h b/cause.h index 21d53f1..809142e 100644 --- a/cause.h +++ b/cause.h @@ -26,6 +26,7 @@ #define CAUSE_NOUSER 18 #define CAUSE_NOANSWER 19 #define CAUSE_REJECTED 21 +#define CAUSE_NONSELECTED 26 #define CAUSE_OUTOFORDER 27 #define CAUSE_INVALID 28 #define CAUSE_FACILITYREJECTED 29 @@ -49,3 +50,4 @@ struct isdn_location { extern struct isdn_cause isdn_cause[128]; extern struct isdn_location isdn_location[16]; char *get_isdn_cause(int cause, int location, int type); +void collect_cause(int *multicause, int *multilocation, int newcause, int newlocation); diff --git a/crypt.cpp b/crypt.cpp index 2b75792..7868ceb 100644 --- a/crypt.cpp +++ b/crypt.cpp @@ -293,10 +293,7 @@ unsigned long crc32(unsigned char *data, int len) unsigned long crc = 0xffffffff; if (!crc_initialized) - { - PERROR("crc not initialized, exitting..."); - exit(-1); - } + FATAL("crc not initialized, exitting..."); while (len--) crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ *data++]; @@ -577,8 +574,7 @@ static void *keyengine_child(void *arg) /* exit process */ apppbx->ea_endpoint->ep_use--; - memset(args, 0, sizeof(struct auth_args)); - free(args); + FREE(args, sizeof(struct auth_args)); amemuse--; return(NULL); } @@ -595,14 +591,7 @@ void EndpointAppPBX::cryptman_keyengine(int job) return; } - arg = (struct auth_args *)calloc(1, sizeof(struct auth_args)); - if (!arg) - { - PERROR("failed to alloc memory.\n"); - e_crypt_keyengine_return = -1; - return; - } - + arg = (struct auth_args *)MALLOC(sizeof(struct auth_args)); arg->apppbx = this; arg->job = job; e_crypt_keyengine_return = 0; @@ -2044,3 +2033,4 @@ void EndpointAppPBX::encrypt_result(int msg, char *text) } } + diff --git a/dss1.cpp b/dss1.cpp index 61c8921..e561c07 100644 --- a/dss1.cpp +++ b/dss1.cpp @@ -75,7 +75,6 @@ Pdss1::~Pdss1() */ static msg_t *create_l3msg(int prim, int mt, int dinfo, int size, int ntmode) { - int i = 0; msg_t *dmsg; Q931_info_t *qi; iframe_t *frm; @@ -83,57 +82,42 @@ static msg_t *create_l3msg(int prim, int mt, int dinfo, int size, int ntmode) if (!ntmode) size = sizeof(Q931_info_t)+2; - while(i < 10) + if (ntmode) { - if (ntmode) + dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL); + if (dmsg) { - dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL); - if (dmsg) - { - return(dmsg); - } - } else + return(dmsg); + } + } else + { + dmsg = alloc_msg(size+256+mISDN_HEADER_LEN+DEFAULT_HEADROOM); + if (dmsg) { - dmsg = alloc_msg(size+256+mISDN_HEADER_LEN+DEFAULT_HEADROOM); - if (dmsg) - { - memset(msg_put(dmsg,size+mISDN_HEADER_LEN), 0, size+mISDN_HEADER_LEN); - frm = (iframe_t *)dmsg->data; - frm->prim = prim; - frm->dinfo = dinfo; - qi = (Q931_info_t *)(dmsg->data + mISDN_HEADER_LEN); - qi->type = mt; - return(dmsg); - } + memset(msg_put(dmsg,size+mISDN_HEADER_LEN), 0, size+mISDN_HEADER_LEN); + frm = (iframe_t *)dmsg->data; + frm->prim = prim; + frm->dinfo = dinfo; + qi = (Q931_info_t *)(dmsg->data + mISDN_HEADER_LEN); + qi->type = mt; + return(dmsg); } - - if (!i) - PERROR("cannot allocate memory, trying again...\n"); - i++; - usleep(50000); } - PERROR("cannot allocate memory, system overloaded.\n"); - exit(-1); + + FATAL("Cannot allocate memory, system overloaded.\n"); + exit(0); // make gcc happy } msg_t *create_l2msg(int prim, int dinfo, int size) /* NT only */ { - int i = 0; msg_t *dmsg; - while(i < 10) - { - dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL); - if (dmsg) - return(dmsg); + dmsg = prep_l3data_msg(prim, dinfo, size, 256, NULL); + if (dmsg) + return(dmsg); - if (!i) - PERROR("cannot allocate memory, trying again...\n"); - i++; - usleep(50000); - } - PERROR("cannot allocate memory, system overloaded.\n"); - exit(-1); + FATAL("Cannot allocate memory, system overloaded.\n"); + exit(0); // make gcc happy } /* @@ -336,7 +320,7 @@ int Pdss1::received_first_reply_to_setup(unsigned long prim, int channel, int ex dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, p_m_d_l3id, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode); release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); - enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); + enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); new_state(PORT_STATE_RELEASE); @@ -501,10 +485,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) { /* nt-library now gives us the id via CC_SETUP */ if (dinfo&(~0xff) == 0xff00) - { - PERROR("fatal software error: l3-stack gives us a process id 0xff00-0xffff\n"); - exit(-1); - } + FATAL("l3-stack gives us a process id 0xff00-0xffff\n"); l1l2l3_trace_header(p_m_mISDNport, this, CC_NEW_CR | INDICATION, DIRECTION_IN); if (p_m_d_l3id) add_trace("callref", "old", "0x%x", p_m_d_l3id); @@ -541,7 +522,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, dinfo, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode); release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); - enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 27); /* temporary unavailable */ + enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 27); /* temporary unavailable */ add_trace("reason", NULL, "port blocked"); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -743,7 +724,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, dinfo, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode); release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); - enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); + enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); new_state(PORT_STATE_RELEASE); @@ -754,34 +735,13 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) /* create endpoint */ if (p_epointlist) - { - PERROR("SOFTWARE ERROR: incoming call but already got an endpoint, exitting...\n"); - exit(-1); - } - if (!(epoint = new Endpoint(p_serial, 0))) - { - RELEASE_COMPLETE_t *release_complete; - - dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, dinfo, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode); - release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); - l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); - enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 41); /* temporary failure */ - end_trace(); - msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); - new_state(PORT_STATE_RELEASE); - p_m_delete = 1; - return; - } + FATAL("Incoming call but already got an endpoint.\n"); + if (!(epoint = new Endpoint(p_serial, 0, 0))) + FATAL("No memory for Endpoint instance\n"); if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint))) - { - PERROR("no memory for application\n"); - exit(-1); - } - if (!(epointlist_new(epoint->ep_serial))) - { - PERROR("no memory for epointlist\n"); - exit(-1); - } + FATAL("No memory for Endpoint Application instance\n"); + epointlist_new(epoint->ep_serial); + /* send setup message to endpoit */ message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP); message->param.setup.isdn_port = p_m_portnum; @@ -1118,7 +1078,7 @@ void Pdss1::connect_ind(unsigned long prim, unsigned long dinfo, void *data) break; } p_connectinfo.isdn_port = p_m_portnum; - SCPY(p_connectinfo.interfaces, p_m_mISDNport->ifport->interface->name); + SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name); /* only in nt-mode we send connect ack. in te-mode it is done by stack itself or optional */ if (p_m_d_ntmode) @@ -1154,6 +1114,8 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data) dec_ie_progress(disconnect->PROGRESS, (Q931_info_t *)((unsigned long)data+headerlen), &coding, &proglocation, &progress); dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause); end_trace(); + if (location == LOCATION_PRIVATE_LOCAL) + location = LOCATION_PRIVATE_REMOTE; if (cause < 0) cause = 16; @@ -1167,7 +1129,7 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, dinfo, sizeof(RELEASE_t), p_m_d_ntmode); release = (RELEASE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE | REQUEST, DIRECTION_OUT); - enc_ie_cause(&release->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); /* normal */ + enc_ie_cause(&release->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); /* normal */ add_trace("reason", NULL, "no remote patterns"); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -1223,33 +1185,11 @@ void Pdss1::disconnect_ind_i(unsigned long prim, unsigned long dinfo, void *data } dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause); end_trace(); + if (location == LOCATION_PRIVATE_LOCAL) + location = LOCATION_PRIVATE_REMOTE; /* collect cause */ - if (cause == CAUSE_REJECTED) /* call rejected */ - { - p_m_d_collect_cause = CAUSE_REJECTED; - p_m_d_collect_location = location; - } else - if (cause==CAUSE_NORMAL && p_m_d_collect_cause!=CAUSE_REJECTED) /* reject via hangup */ - { - p_m_d_collect_cause = CAUSE_NORMAL; - p_m_d_collect_location = location; - } else - if (cause==CAUSE_BUSY && p_m_d_collect_cause!=CAUSE_REJECTED && p_m_d_collect_cause!=CAUSE_NORMAL) /* busy */ - { - p_m_d_collect_cause = CAUSE_BUSY; - p_m_d_collect_location = location; - } else - if (cause==CAUSE_OUTOFORDER && p_m_d_collect_cause!=CAUSE_BUSY && p_m_d_collect_cause!=CAUSE_REJECTED && p_m_d_collect_cause!=CAUSE_NORMAL) /* no L1 */ - { - p_m_d_collect_cause = CAUSE_OUTOFORDER; - p_m_d_collect_location = location; - } else - if (cause!=0 && cause!=CAUSE_NOUSER && p_m_d_collect_cause!=CAUSE_OUTOFORDER && p_m_d_collect_cause!=CAUSE_BUSY && p_m_d_collect_cause!=CAUSE_REJECTED && p_m_d_collect_cause!=CAUSE_NORMAL) /* anything if cause exists and not 18 */ - { - p_m_d_collect_cause = cause; - p_m_d_collect_location = location; - } + collect_cause(&p_m_d_collect_cause, &p_m_d_collect_location, cause, location); add_trace("new-cause", "location", "%d", p_m_d_collect_location); add_trace("new-cause", "value", "%d", p_m_d_collect_cause); @@ -1267,6 +1207,8 @@ void Pdss1::release_ind(unsigned long prim, unsigned long dinfo, void *data) l1l2l3_trace_header(p_m_mISDNport, this, prim, DIRECTION_IN); dec_ie_cause(release->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause); end_trace(); + if (location == LOCATION_PRIVATE_LOCAL) + location = LOCATION_PRIVATE_REMOTE; if (cause < 0) cause = 16; @@ -1291,7 +1233,7 @@ void Pdss1::release_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, dinfo, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode); release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); - enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); + enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 16); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); } @@ -1311,6 +1253,8 @@ void Pdss1::release_complete_ind(unsigned long prim, unsigned long dinfo, void * l1l2l3_trace_header(p_m_mISDNport, this, prim, DIRECTION_IN); dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)((unsigned long)data+headerlen), &location, &cause); end_trace(); + if (location == LOCATION_PRIVATE_LOCAL) + location = LOCATION_PRIVATE_REMOTE; if (cause < 0) cause = 16; @@ -1429,7 +1373,7 @@ void Pdss1::hold_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT, dinfo, sizeof(HOLD_REJECT_t), p_m_d_ntmode); hold_reject = (HOLD_REJECT_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_HOLD_REJECT | REQUEST, DIRECTION_OUT); - enc_ie_cause(&hold_reject->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, p_m_hold?101:31); /* normal unspecified / incompatible state */ + enc_ie_cause(&hold_reject->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, p_m_hold?101:31); /* normal unspecified / incompatible state */ add_trace("reason", NULL, "no endpoint"); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -1493,7 +1437,7 @@ void Pdss1::retrieve_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT, dinfo, sizeof(RETRIEVE_REJECT_t), p_m_d_ntmode); retrieve_reject = (RETRIEVE_REJECT_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RETRIEVE_REJECT | REQUEST, DIRECTION_OUT); - enc_ie_cause(&retrieve_reject->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, cause); + enc_ie_cause(&retrieve_reject->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, cause); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -1558,7 +1502,7 @@ void Pdss1::suspend_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, dinfo, sizeof(SUSPEND_REJECT_t), p_m_d_ntmode); suspend_reject = (SUSPEND_REJECT_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_SUSPEND_REJECT | REQUEST, DIRECTION_OUT); - enc_ie_cause(&suspend_reject->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); + enc_ie_cause(&suspend_reject->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); @@ -1638,10 +1582,7 @@ void Pdss1::resume_ind(unsigned long prim, unsigned long dinfo, void *data) { /* nt-library now gives us the id via CC_RESUME */ if (dinfo&(~0xff) == 0xff00) - { - PERROR("fatal software error: l3-stack gives us a process id 0xff00-0xffff\n"); - exit(-1); - } + FATAL("l3-stack gives us a process id 0xff00-0xffff\n"); l1l2l3_trace_header(p_m_mISDNport, this, CC_NEW_CR | INDICATION, DIRECTION_IN); if (p_m_d_l3id) add_trace("callref", "old", "0x%x", p_m_d_l3id); @@ -1685,7 +1626,7 @@ void Pdss1::resume_ind(unsigned long prim, unsigned long dinfo, void *data) dmsg = create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT, dinfo, sizeof(RESUME_REJECT_t), p_m_d_ntmode); resume_reject = (RESUME_REJECT_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RESUME_REJECT | REQUEST, DIRECTION_OUT); - enc_ie_cause(&resume_reject->CAUSE, dmsg, (p_m_d_ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); + enc_ie_cause(&resume_reject->CAUSE, dmsg, (p_m_mISDNport->locally)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, -ret); if (ret == -27) add_trace("reason", NULL, "port blocked"); end_trace(); @@ -1698,10 +1639,7 @@ void Pdss1::resume_ind(unsigned long prim, unsigned long dinfo, void *data) /* create endpoint */ if (p_epointlist) - { - PERROR("SOFTWARE ERROR: incoming resume but already got an endpoint, exitting...\n"); - exit(-1); - } + FATAL("Incoming resume but already got an endpoint.\n"); ret = -85; /* no call suspended */ epoint = epoint_first; while(epoint) @@ -1718,16 +1656,9 @@ void Pdss1::resume_ind(unsigned long prim, unsigned long dinfo, void *data) if (!epoint) goto reject; - if (!(epointlist_new(epoint->ep_serial))) - { - PERROR("no memory for epointlist\n"); - exit(-1); - } + epointlist_new(epoint->ep_serial); if (!(epoint->portlist_new(p_serial, p_type, p_m_mISDNport->earlyb))) - { - PERROR("no memory for portlist\n"); - exit(-1); - } + FATAL("No memory for portlist\n"); message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RESUME); message_put(message); @@ -2139,13 +2070,7 @@ void Pdss1::message_setup(unsigned long epoint_id, int message_id, union paramet epointlist = epointlist->next; } if (!epointlist) - { - if (!(epointlist_new(epoint_id))) - { - PERROR("no memory for epointlist\n"); - exit(-1); - } - } + epointlist_new(epoint_id); /* get channel */ exclusive = 0; @@ -2758,7 +2683,7 @@ void Pdss1::message_disconnect(unsigned long epoint_id, int message_id, union pa release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); /* send cause */ - enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); + enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); new_state(PORT_STATE_RELEASE); @@ -2798,7 +2723,7 @@ void Pdss1::message_disconnect(unsigned long epoint_id, int message_id, union pa if (p_m_mISDNport->tones) enc_ie_progress(&disconnect->PROGRESS, dmsg, 0, p_m_d_ntmode?1:5, 8); /* send cause */ - enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_d_ntmode && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); + enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); /* send display */ if (param->disconnectinfo.display[0]) p = param->disconnectinfo.display; @@ -2829,7 +2754,7 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param release = (RELEASE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE | REQUEST, DIRECTION_OUT); /* send cause */ - enc_ie_cause(&release->CAUSE, dmsg, (p_m_d_ntmode && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); + enc_ie_cause(&release->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); new_state(PORT_STATE_RELEASE); @@ -2847,7 +2772,7 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen); l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE | REQUEST, DIRECTION_OUT); /* send cause */ - enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_d_ntmode && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); + enc_ie_cause(&release_complete->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); end_trace(); msg_queue_tail(&p_m_mISDNport->downqueue, dmsg); new_state(PORT_STATE_RELEASE); @@ -2898,7 +2823,7 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param if (p_m_mISDNport->tones) enc_ie_progress(&disconnect->PROGRESS, dmsg, 0, p_m_d_ntmode?1:5, 8); /* send cause */ - enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_d_ntmode && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); + enc_ie_cause(&disconnect->CAUSE, dmsg, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause); /* send display */ epoint = find_epoint_id(epoint_id); if (param->disconnectinfo.display[0]) @@ -2966,10 +2891,7 @@ int Pdss1::message_epoint(unsigned long epoint_id, int message_id, union paramet break; } if (p_epointlist && p_state==PORT_STATE_IDLE) - { - PERROR("Pdss1(%s): software error: epoint pointer is set in idle state, how bad!! exitting.\n", p_name); - exit(-1); - } + FATAL("Pdss1(%s): epoint pointer is set in idle state, how bad!!\n", p_name); /* note: pri is a special case, because links must be up for pri */ if (p_m_mISDNport->l1link || p_m_mISDNport->pri || !p_m_mISDNport->ntmode || p_state!=PORT_STATE_IDLE) { @@ -2982,10 +2904,7 @@ int Pdss1::message_epoint(unsigned long epoint_id, int message_id, union paramet memcpy(&p_m_d_queue->param, param, sizeof(union parameter)); /* attach us */ if (!(epointlist_new(epoint_id))) - { - PERROR("no memory for epointlist\n"); - exit(-1); - } + FATAL("No memory for epointlist\n"); /* activate link */ PDEBUG(DEBUG_ISDN, "the L1 is down, we try to establish the link NT portnum=%d (%s).\n", p_m_mISDNport->portnum, p_name); act.prim = PH_ACTIVATE | REQUEST; @@ -3192,19 +3111,8 @@ int stack2manager_nt(void *dat, void *arg) /* creating port object */ SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum); if (!(pdss1 = new Pdss1(PORT_TYPE_DSS1_NT_IN, mISDNport, name, NULL, 0, 0))) - { - RELEASE_COMPLETE_t *release_complete; - msg_t *dmsg; - PERROR("FATAL ERROR: cannot create port object.\n"); - dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, hh->dinfo, sizeof(RELEASE_COMPLETE_t), mISDNport->ntmode); - release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + mISDN_HEADER_LEN); - l1l2l3_trace_header(mISDNport, NULL, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); - enc_ie_cause_standalone(mISDNport->ntmode?&release_complete->CAUSE:NULL, dmsg, (mISDNport->ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 47); - end_trace(); - msg_queue_tail(&mISDNport->downqueue, dmsg); - break; - } + FATAL("Cannot create Port instance.\n"); pdss1->message_isdn(hh->prim, hh->dinfo, msg->data); break; @@ -3212,19 +3120,7 @@ int stack2manager_nt(void *dat, void *arg) /* creating port object */ SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum); if (!(pdss1 = new Pdss1(PORT_TYPE_DSS1_NT_IN, mISDNport, name, NULL, 0, 0))) - { - SUSPEND_REJECT_t *suspend_reject; - msg_t *dmsg; - - PERROR("FATAL ERROR: cannot create port object.\n"); - dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT, hh->dinfo, sizeof(SUSPEND_REJECT_t), mISDNport->ntmode); - suspend_reject = (SUSPEND_REJECT_t *)(dmsg->data + mISDN_HEADER_LEN); - l1l2l3_trace_header(mISDNport, NULL, CC_SUSPEND_REJECT | REQUEST, DIRECTION_OUT); - enc_ie_cause_standalone(mISDNport->ntmode?&suspend_reject->CAUSE:NULL, dmsg, (mISDNport->ntmode)?1:0, 47); - end_trace(); - msg_queue_tail(&mISDNport->downqueue, dmsg); - break; - } + FATAL("Cannot create Port instance.\n"); pdss1->message_isdn(hh->prim, hh->dinfo, msg->data); break; @@ -3289,20 +3185,7 @@ int stack2manager_te(struct mISDNport *mISDNport, msg_t *msg) /* creating port object */ SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum); if (!(pdss1 = new Pdss1(PORT_TYPE_DSS1_TE_IN, mISDNport, name, NULL, 0, 0))) - { - RELEASE_COMPLETE_t *release_complete; - msg_t *dmsg; - - PERROR("FATAL ERROR: cannot create port object.\n"); - dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, frm->dinfo, sizeof(RELEASE_COMPLETE_t), mISDNport->ntmode); - release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + mISDN_HEADER_LEN); - l1l2l3_trace_header(mISDNport, NULL, CC_RELEASE_COMPLETE | REQUEST, DIRECTION_OUT); - enc_ie_cause_standalone(mISDNport->ntmode?&release_complete->CAUSE:NULL, dmsg, (mISDNport->ntmode)?LOCATION_PRIVATE_LOCAL:LOCATION_PRIVATE_REMOTE, 47); - end_trace(); - msg_queue_tail(&mISDNport->downqueue, dmsg); - free_msg(msg); - return(0); - } + FATAL("Cannot create Port instance.\n"); /* l3id will be set from dinfo at message_isdn */ pdss1->message_isdn(frm->prim, frm->dinfo, msg->data); free_msg(msg); diff --git a/endpoint.cpp b/endpoint.cpp index 53d2149..819f779 100644 --- a/endpoint.cpp +++ b/endpoint.cpp @@ -39,7 +39,7 @@ class Endpoint *find_epoint_id(unsigned long epoint_id) /* * endpoint constructor (link with either port or call id) */ -Endpoint::Endpoint(int port_id, int call_id) +Endpoint::Endpoint(unsigned long port_id, unsigned long call_id, unsigned long use_epoint_id) { class Port *port; class Endpoint **epointpointer; @@ -60,7 +60,10 @@ Endpoint::Endpoint(int port_id, int call_id) *epointpointer = this; /* serial */ - ep_serial = epoint_serial++; + if (use_epoint_id) + ep_serial = use_epoint_id; + else + ep_serial = epoint_serial++; /* link to call or port */ if (port_id) @@ -71,10 +74,7 @@ Endpoint::Endpoint(int port_id, int call_id) if ((port->p_type&PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_DSS1) earlyb = ((class PmISDN *)port)->p_m_mISDNport->earlyb; if (!portlist_new(port_id, port->p_type, earlyb)) - { - PERROR("no mem for portlist, exitting...\n"); - exit(-1); - } + FATAL("No memory for portlist.\n"); } } ep_call_id = call_id; @@ -117,7 +117,7 @@ Endpoint::~Endpoint(void) mtemp = portlist; portlist = portlist->next; memset(mtemp, 0, sizeof(struct port_list)); - free(mtemp); + FREE(mtemp, sizeof(struct port_list)); ememuse--; } @@ -133,10 +133,7 @@ Endpoint::~Endpoint(void) temp = temp->next; } if (temp == 0) - { - PERROR("error: endpoint not in endpoint's list, exitting.\n"); - exit(-1); - } + FATAL("Endpoint not in Endpoint's list.\n"); *tempp = next; /* free */ @@ -150,15 +147,9 @@ struct port_list *Endpoint::portlist_new(unsigned long port_id, int port_type, i struct port_list *portlist, **portlistpointer; /* portlist structure */ - portlist = (struct port_list *)calloc(1, sizeof(struct port_list)); - if (!portlist) - { - PERROR("no mem for allocating port_list\n"); - return(0); - } + portlist = (struct port_list *)MALLOC(sizeof(struct port_list)); ememuse++; PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocating port_list.\n", ep_serial); - memset(portlist, 0, sizeof(struct port_list)); /* add port_list to chain */ portlist->next = NULL; @@ -192,18 +183,14 @@ void Endpoint::free_portlist(struct port_list *portlist) tempp = &temp->next; temp = temp->next; } - if (temp == 0) - { - PERROR("port_list not in endpoint's list, exitting.\n"); - exit(-1); - } + if (!temp) + FATAL("port_list not in Endpoint's list.\n"); /* detach */ *tempp=portlist->next; /* free */ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removed port_list from endpoint\n", ep_serial); - memset(portlist, 0, sizeof(struct port_list)); - free(portlist); + FREE(portlist, sizeof(struct port_list)); ememuse--; } diff --git a/endpoint.h b/endpoint.h index 744f3ea..fb8e8d2 100644 --- a/endpoint.h +++ b/endpoint.h @@ -22,7 +22,7 @@ struct port_list { class Endpoint { public: - Endpoint(int port_id, int call_id); + Endpoint(unsigned long port_id, unsigned long call_id, unsigned long use_epoint_id); ~Endpoint(); class Endpoint *next; /* next in list */ unsigned long ep_serial; /* a unique serial to identify */ diff --git a/extension.h b/extension.h index f62eb96..692906e 100644 --- a/extension.h +++ b/extension.h @@ -9,6 +9,10 @@ ** ** \*****************************************************************************/ +/* maximum number of redial/powerdial and reply numbers to remember + */ +#define MAX_REMEMBER 99 + /* display of callerid on internal numbers */ enum { diff --git a/genrc.c b/genrc.c index 8cb5b00..7c5089f 100644 --- a/genrc.c +++ b/genrc.c @@ -13,7 +13,7 @@ #include #include #include -#include "save.h" +#include "macro.h" char mode[256]; int type[256]; @@ -166,7 +166,7 @@ int main(void) if (!(fp=fopen(name, "w"))) { fprintf(stderr, "\nError: Failed to open '%s', try again.\n", name); - exit(-1); + exit(EXIT_FAILURE); } fprintf(fp, "# rc script for mISDN driver\n\n"); fprintf(fp, "case \"$1\" in\n"); diff --git a/ie.cpp b/ie.cpp index b27920f..75b86f4 100644 --- a/ie.cpp +++ b/ie.cpp @@ -1521,7 +1521,7 @@ void Pdss1::dec_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned cha UPRINT(debug+(j*3), " %02x", centrex[i+1+j]); i++; } - add_trace("facility", "CENTREX", "unknown=0x%2x len=%d%s\n", centrex[i], centrex[i+1], debug); + add_trace("facility", "CENTREX", "unknown=0x%02x len=%d%s\n", centrex[i], centrex[i+1], debug); } i += 1+centrex[i+1]; } diff --git a/interface.c b/interface.c index 7b90d15..1a17842 100644 --- a/interface.c +++ b/interface.c @@ -23,14 +23,8 @@ void default_out_channel(struct interface_port *ifport) { struct select_channel *selchannel, **selchannelp; - selchannel = (struct select_channel *)malloc(sizeof(struct select_channel)); - if (!selchannel) - { - PERROR("No memory!"); - return; - } + selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel)); memuse++; - memset(selchannel, 0, sizeof(struct select_channel)); if (ifport->mISDNport->ntmode) selchannel->channel = CHANNEL_FREE; @@ -43,14 +37,8 @@ void default_out_channel(struct interface_port *ifport) if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode) { selchannelp = &(selchannel->next); - selchannel = (struct select_channel *)malloc(sizeof(struct select_channel)); - if (!selchannel) - { - PERROR("No memory!"); - return; - } + selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel)); memuse++; - memset(selchannel, 0, sizeof(struct select_channel)); selchannel->channel = CHANNEL_NO; // call waiting *selchannelp = selchannel; } @@ -62,14 +50,8 @@ void default_in_channel(struct interface_port *ifport) { struct select_channel *selchannel; - selchannel = (struct select_channel *)malloc(sizeof(struct select_channel)); - if (!selchannel) - { - PERROR("No memory!"); - return; - } + selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel)); memuse++; - memset(selchannel, 0, sizeof(struct select_channel)); selchannel->channel = CHANNEL_FREE; @@ -281,14 +263,8 @@ static int inter_port(struct interface *interface, char *filename, int line, cha searchif = searchif->next; } /* alloc port substructure */ - ifport = (struct interface_port *)malloc(sizeof(struct interface_port)); - if (!ifport) - { - SPRINT(interface_error, "No memory!"); - return(-1); - } + ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port)); memuse++; - memset(ifport, 0, sizeof(struct interface_port)); ifport->interface = interface; /* set value */ ifport->portnum = val; @@ -360,14 +336,8 @@ static int inter_channel_out(struct interface *interface, char *filename, int li } selchannel: /* add to select-channel list */ - selchannel = (struct select_channel *)malloc(sizeof(struct select_channel)); - if (!selchannel) - { - SPRINT(interface_error, "No memory!"); - return(-1); - } + selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel)); memuse++; - memset(selchannel, 0, sizeof(struct select_channel)); /* set value */ selchannel->channel = val; /* tail port */ @@ -426,14 +396,8 @@ static int inter_channel_in(struct interface *interface, char *filename, int lin } selchannel: /* add to select-channel list */ - selchannel = (struct select_channel *)malloc(sizeof(struct select_channel)); - if (!selchannel) - { - SPRINT(interface_error, "No memory!"); - return(-1); - } + selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel)); memuse++; - memset(selchannel, 0, sizeof(struct select_channel)); /* set value */ selchannel->channel = val; /* tail port */ @@ -468,14 +432,8 @@ static int inter_msn(struct interface *interface, char *filename, int line, char el = p; p = get_seperated(p); /* add MSN to list */ - ifmsn = (struct interface_msn *)malloc(sizeof(struct interface_msn)); - if (!ifmsn) - { - SPRINT(interface_error, "No memory!"); - return(-1); - } + ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn)); memuse++; - memset(ifmsn, 0, sizeof(struct interface_msn)); /* set value */ SCPY(ifmsn->msn, el); /* tail port */ @@ -500,14 +458,8 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i el = p; p = get_seperated(p); /* add screen entry to list*/ - ifscreen = (struct interface_screen *)malloc(sizeof(struct interface_screen)); - if (!ifscreen) - { - SPRINT(interface_error, "No memory!"); - return(-1); - } + ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen)); memuse++; - memset(ifscreen, 0, sizeof(struct interface_screen)); ifscreen->match_type = -1; /* unchecked */ ifscreen->match_present = -1; /* unchecked */ ifscreen->result_type = -1; /* unchanged */ @@ -788,10 +740,7 @@ struct interface *read_interfaces(void) struct interface_param *ifparam; if (interface_newlist != NULL) - { - PERROR("software error, list is not empty.\n"); - exit(-1); - } + FATAL("list is not empty.\n"); interface_error[0] = '\0'; SPRINT(filename, "%s/interface.conf", INSTALL_DATA); @@ -894,14 +843,8 @@ struct interface *read_interfaces(void) } /* append interface to new list */ - interface = (struct interface *)malloc(sizeof(struct interface)); - if (!interface) - { - SPRINT(interface_error, "No memory!"); - goto error; - } + interface = (struct interface *)MALLOC(sizeof(struct interface)); memuse++; - memset(interface, 0, sizeof(struct interface)); /* name interface */ SCPY(interface->name, parameter+1); @@ -964,8 +907,7 @@ void free_interfaces(struct interface *interface) { temp = selchannel; selchannel = selchannel->next; - memset(temp, 0, sizeof(struct select_channel)); - free(temp); + FREE(temp, sizeof(struct select_channel)); memuse--; } selchannel = ifport->out_channel; @@ -973,14 +915,12 @@ void free_interfaces(struct interface *interface) { temp = selchannel; selchannel = selchannel->next; - memset(temp, 0, sizeof(struct select_channel)); - free(temp); + FREE(temp, sizeof(struct select_channel)); memuse--; } temp = ifport; ifport = ifport->next; - memset(temp, 0, sizeof(struct interface_port)); - free(temp); + FREE(temp, sizeof(struct interface_port)); memuse--; } ifmsn = interface->ifmsn; @@ -988,8 +928,7 @@ void free_interfaces(struct interface *interface) { temp = ifmsn; ifmsn = ifmsn->next; - memset(temp, 0, sizeof(struct interface_msn)); - free(temp); + FREE(temp, sizeof(struct interface_msn)); memuse--; } ifscreen = interface->ifscreen_in; @@ -997,8 +936,7 @@ void free_interfaces(struct interface *interface) { temp = ifscreen; ifscreen = ifscreen->next; - memset(temp, 0, sizeof(struct interface_screen)); - free(temp); + FREE(temp, sizeof(struct interface_screen)); memuse--; } ifscreen = interface->ifscreen_out; @@ -1006,8 +944,7 @@ void free_interfaces(struct interface *interface) { temp = ifscreen; ifscreen = ifscreen->next; - memset(temp, 0, sizeof(struct interface_screen)); - free(temp); + FREE(temp, sizeof(struct interface_screen)); memuse--; } iffilter = interface->iffilter; @@ -1015,18 +952,43 @@ void free_interfaces(struct interface *interface) { temp = iffilter; iffilter = iffilter->next; - memset(temp, 0, sizeof(struct interface_filter)); - free(temp); + FREE(temp, sizeof(struct interface_filter)); memuse--; } temp = interface; interface = interface->next; - memset(temp, 0, sizeof(struct interface)); - free(temp); + FREE(temp, sizeof(struct interface)); memuse--; } } +/* + * defaults of ports if not specified by config + */ +static void set_defaults(struct interface_port *ifport) +{ + /* default channel selection list */ + if (!ifport->out_channel) + default_out_channel(ifport); + if (!ifport->in_channel) + default_in_channel(ifport); + /* default is_tones */ + if (ifport->interface->is_tones) + ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES); + else + ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0; + /* default is_earlyb */ + if (ifport->interface->is_earlyb) + ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES); + else + ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1; + /* set locally flag */ + if (ifport->interface->extension) + ifport->mISDNport->locally = 1; + else + ifport->mISDNport->locally = 0; +} + /* * all links between mISDNport and interface are made @@ -1061,6 +1023,7 @@ void relink_interfaces(void) { ifport->mISDNport = mISDNport; mISDNport->ifport = ifport; + set_defaults(ifport); } mISDNport = mISDNport->next; } @@ -1117,22 +1080,7 @@ void load_port(struct interface_port *ifport) /* link port */ ifport->mISDNport = mISDNport; mISDNport->ifport = ifport; - - /* default channel selection list */ - if (!ifport->out_channel) - default_out_channel(ifport); - if (!ifport->in_channel) - default_in_channel(ifport); - /* default is_tones */ - if (ifport->interface->is_tones) - ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES); - else - ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0; - /* default is_earlyb */ - if (ifport->interface->is_earlyb) - ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES); - else - ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1; + set_defaults(ifport); } else { ifport->block = 2; /* not available */ diff --git a/mISDN.cpp b/mISDN.cpp index c53b758..9a492de 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -53,7 +53,6 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti p_m_b_channel = 0; p_m_b_exclusive = 0; p_m_b_reserve = 0; - p_m_jittercheck = 0; p_m_delete = 0; p_m_hold = 0; p_m_txvol = p_m_rxvol = 0; @@ -68,9 +67,9 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti p_m_timeout = 0; p_m_timer = 0; - /* audio from up */ - p_m_fromup_buffer_readp = 0; - p_m_fromup_buffer_writep = 0; + /* audio */ + p_m_load = 0; + p_m_last_tv_sec = 0; /* crypt */ p_m_crypt = 0; @@ -270,7 +269,10 @@ void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned lo *d++ = c2; mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC); chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT); - add_trace(trace_name, NULL, "%d", trace_value); + 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(); } @@ -363,8 +365,8 @@ static int _bchannel_create(struct mISDNport *mISDNport, int i) goto stack_error; chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT); add_trace("channel", NULL, "%d", i+1+(i>=15)); - add_trace("stack", "id", "0x%8x", mISDNport->b_stid[i]); - add_trace("stack", "address", "0x%8x", mISDNport->b_addr[i]); + add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]); + add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]); end_trace(); return(1); @@ -465,8 +467,8 @@ static void _bchannel_destroy(struct mISDNport *mISDNport, int i) chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT); add_trace("channel", NULL, "%d", i+1+(i>=15)); - add_trace("stack", "id", "0x%8x", mISDNport->b_stid[i]); - add_trace("stack", "address", "0x%8x", mISDNport->b_addr[i]); + add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]); + add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]); end_trace(); /* remove our stack only if set */ PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]); @@ -538,10 +540,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) case B_EVENT_ACTIVATE: /* port must be linked in order to allow activation */ if (!mISDNport->b_port[i]) - { - PERROR("SOFTWARE ERROR: bchannel must be linked to a Port class\n"); - exit(-1); - } + FATAL("bchannel must be linked to a Port class\n"); switch(state) { case B_STATE_IDLE: @@ -590,10 +589,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event) case B_EVENT_DEACTIVATE: if (!mISDNport->b_port[i]) - { - PERROR("SOFTWARE ERROR: bchannel must be linked to a Port class\n"); - exit(-1); - } + FATAL("bchannel must be linked to a Port class\n"); switch(state) { case B_STATE_IDLE: @@ -722,7 +718,6 @@ seize: p_m_b_index = i; p_m_b_channel = channel; p_m_b_exclusive = exclusive; - p_m_jittercheck = 0; /* reserve channel */ if (!p_m_b_reserve) @@ -765,130 +760,141 @@ void PmISDN::drop_bchannel(void) /* * handler + +audio transmission procedure: +----------------------------- + +* priority +three sources of audio transmission: +- crypto-data high priority +- tones high priority (also high) +- remote-data low priority + +* elapsed +a variable that temporarily shows the number of samples elapsed since last transmission process. +p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed. + +* load +a variable that is increased whenever data is transmitted. +it is decreased while time elapses. it stores the number of samples that +are currently loaded to dsp module. +since clock in dsp module is the same clock for user space process, these +times have no skew. + +* levels +there are two levels: +ISDN_LOAD will give the load that have to be kept in dsp. +ISDN_MAXLOAD will give the maximum load before dropping. + +* procedure for low priority data +see txfromup() for procedure +in short: remote data is ignored during high priority tones + +* procedure for high priority data +whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD +if no more data is available, load becomes empty again. + +'load' variable: +0 ISDN_LOAD ISDN_MAXLOAD ++--------------------+----------------------+ +| | | ++--------------------+----------------------+ + +on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD: +0 ISDN_LOAD ISDN_MAXLOAD ++--------------------+----------------------+ +|TTTTTTTTTTTTTTTTTTTT| | ++--------------------+----------------------+ + +on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD. +0 ISDN_LOAD ISDN_MAXLOAD ++--------------------+----------------------+ +|TTTTTTTTTTTTTTTTTTTTRRRRR | ++--------------------+----------------------+ + */ int PmISDN::handler(void) { struct message *message; - int elapsed, length; + int elapsed = 0; int ret; - int inbuffer; if ((ret = Port::handler())) return(ret); - inbuffer = (p_m_fromup_buffer_writep - p_m_fromup_buffer_readp) & FROMUP_BUFFER_MASK; - /* send tone data to isdn device only if we have data */ - if (p_tone_name[0] || p_m_crypt_msg_loops || inbuffer) + /* get elapsed */ + if (p_m_last_tv_sec) { - /* calculate how much to transmit */ - if (!p_last_tv_sec) - { - elapsed = ISDN_PRELOAD; /* preload for the first time */ - } else - { - elapsed = 8000 * (now_tv.tv_sec - p_last_tv_sec) - + 8 * (now_tv.tv_usec/1000 - p_last_tv_msec); - /* gap was greater preload, so only fill up to preload level */ - if (elapsed > ISDN_PRELOAD) - { - elapsed = ISDN_PRELOAD; - } - } -printf("p%d elapsed=%d\n", p_serial, elapsed); - if (elapsed >= ISDN_TRANSMIT) + elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec) + + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec); + } else + { + /* set clock of first process ever in this instance */ + p_m_last_tv_sec = now_tv.tv_sec; + p_m_last_tv_msec = now_tv.tv_usec/1000; + } + /* process only if we have a minimum of samples, to make packets not too small */ + if (elapsed >= ISDN_TRANSMIT) + { + /* set clock of last process! */ + p_m_last_tv_sec = now_tv.tv_sec; + p_m_last_tv_msec = now_tv.tv_usec/1000; + + /* update load */ + if (elapsed < p_m_load) + p_m_load -= elapsed; + else + p_m_load = 0; + + /* to send data, tone must be active OR crypt messages must be on */ + if ((p_tone_name[0] || p_m_crypt_msg_loops) && p_m_load < ISDN_LOAD) { - unsigned char buf[mISDN_HEADER_LEN+ISDN_PRELOAD]; + int tosend = ISDN_LOAD - p_m_load, length; + unsigned char buf[mISDN_HEADER_LEN+tosend]; iframe_t *frm = (iframe_t *)buf; unsigned char *p = buf+mISDN_HEADER_LEN; - p_last_tv_sec = now_tv.tv_sec; - p_last_tv_msec = now_tv.tv_usec/1000; - - /* read tones or fill with silence */ - length = read_audio(p, elapsed); - - /* - * get data from up - * the fromup_buffer data is written to the beginning of the buffer - * the part that is filles with tones (length) is skipped, so tones have priority - * the length value is increased by the number of data copied from fromup_buffer - */ -printf("p%d inbuffer=%d\n", p_serial, inbuffer); - if (inbuffer) - { - /* inbuffer might be less than we skip due to audio */ - if (inbuffer <= length) - { - /* clear buffer */ - p_m_fromup_buffer_readp = p_m_fromup_buffer_writep; - inbuffer = 0; - } else - { - /* skip what we already have with tones */ - p_m_fromup_buffer_readp = (p_m_fromup_buffer_readp + length) & FROMUP_BUFFER_MASK; - inbuffer -= length; - p += length; - } - /* if we have more in buffer, than we send this time */ - if (inbuffer > (elapsed-length)) - inbuffer = elapsed - length; - /* set length to what we actually have */ - length = length + inbuffer; -printf("p%d inbuffer=%d\n", p_serial, inbuffer); - /* now fill up with fromup_buffer */ - while (inbuffer) - { - *p++ = p_m_fromup_buffer[p_m_fromup_buffer_readp]; - p_m_fromup_buffer_readp = (p_m_fromup_buffer_readp + 1) & FROMUP_BUFFER_MASK; - inbuffer--; - } - } -printf("p%d length=%d\n", p_serial, length); - - /* overwrite buffer with crypto stuff */ - if (p_m_crypt_msg_loops) + /* copy crypto loops */ + while (p_m_crypt_msg_loops && tosend) { - /* send pending message */ - int tosend; - /* how much do we have to send */ - tosend = p_m_crypt_msg_len - p_m_crypt_msg_current; - if (tosend > elapsed) - tosend = elapsed; + length = p_m_crypt_msg_len - p_m_crypt_msg_current; - /* our length increases, if less */ - if (length < tosend) + /* clip tosend */ + if (length > tosend) length = tosend; /* copy message (part) to buffer */ - memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, tosend); - p_m_crypt_msg_current += tosend; + memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length); + + /* new position */ + p_m_crypt_msg_current += length; if (p_m_crypt_msg_current == p_m_crypt_msg_len) { + /* next loop */ p_m_crypt_msg_current = 0; p_m_crypt_msg_loops--; } + + /* new length */ + tosend -= length; + } + + /* copy tones */ + if (p_tone_name[0] && tosend) + { + tosend -= read_audio(p, tosend); } + + /* send data */ frm->prim = DL_DATA | REQUEST; frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN; frm->dinfo = 0; - frm->len = length; - mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC); - - if (p_debug_nothingtosend) - { - p_debug_nothingtosend = 0; - PDEBUG((DEBUG_PORT | DEBUG_BCHANNEL), "PmISDN(%s) start sending, because we have tones and/or remote audio.\n", p_name); - } - return(1); + frm->len = ISDN_LOAD - p_m_load - tosend; + if (frm->len) + mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC); + p_m_load += frm->len; } - } else - { - if (!p_debug_nothingtosend) - { - p_debug_nothingtosend = 1; - PDEBUG((DEBUG_PORT | DEBUG_BCHANNEL), "PmISDN(%s) stop sending, because we have only silence.\n", p_name); - } } // NOTE: deletion is done by the child class @@ -968,8 +974,8 @@ void PmISDN::bchannel_receive(iframe_t *frm) case CMX_TX_DATA: if (!p_m_txdata) { - /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */ - PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring rx data, because 'txdata' is turned off\n", p_name); + /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */ + PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name); return; } if (p_record) @@ -993,8 +999,7 @@ void PmISDN::bchannel_receive(iframe_t *frm) * the call is connected OR interface features audio during call setup. */ //printf("%d -> %d prim=%x calldata=%d tones=%d\n", p_serial, ACTIVE_EPOINT(p_epointlist), frm->prim, p_m_calldata, p_m_mISDNport->earlyb); -#warning "disabled for debug" -#if 0 +#ifndef DEBUG_COREBRIDGE if (p_state!=PORT_STATE_CONNECT && !p_m_mISDNport->earlyb) return; @@ -1489,8 +1494,7 @@ int mISDN_handler(void) free_msg(msg); if (errno == EAGAIN) return(0); - PERROR("FATAL ERROR: failed to do mISDN_read()\n"); - exit(-1); + FATAL("Failed to do mISDN_read()\n"); } if (!ret) { @@ -1804,8 +1808,7 @@ struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, struct interface * if (ret < (int)mISDN_HEADER_LEN) { noentity: - fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug."); - exit(-1); + FATAL("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug."); } entity = frm->dinfo & 0xffff; if (!entity) @@ -1907,14 +1910,8 @@ struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, struct interface * mISDNportp = &mISDNport_first; while(*mISDNportp) mISDNportp = &((*mISDNportp)->next); - mISDNport = (struct mISDNport *)calloc(1, sizeof(struct mISDNport)); - if (!mISDNport) - { - PERROR("Cannot alloc mISDNport structure\n"); - return(NULL); - } + mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport)); pmemuse++; - memset(mISDNport, 0, sizeof(mISDNport)); *mISDNportp = mISDNport; /* allocate ressources of port */ @@ -2163,7 +2160,7 @@ void mISDNport_close(struct mISDNport *mISDNport) /* phd */ msg_queue_purge(&nst->down_queue); if (nst->phd_down_msg) - free(nst->phd_down_msg); + FREE(nst->phd_down_msg, 0); } } @@ -2188,13 +2185,9 @@ void mISDNport_close(struct mISDNport *mISDNport) } if (mISDNportp) - { - PERROR("software error, mISDNport not in list\n"); - exit(-1); - } + FATAL("mISDNport not in list\n"); - memset(mISDNport, 0, sizeof(struct mISDNport)); - free(mISDNport); + FREE(mISDNport, sizeof(struct mISDNport)); pmemuse--; /* close mISDNdevice, if no port */ @@ -2227,7 +2220,7 @@ void mISDN_port_info(void) if ((device = mISDN_open()) < 0) { fprintf(stderr, "cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", device, errno, strerror(errno)); - exit(-1); + exit(EXIT_FAILURE); } /* get number of stacks */ @@ -2376,10 +2369,7 @@ void mISDN_port_info(void) /* close mISDN */ if ((err = mISDN_close(device))) - { - fprintf(stderr, "mISDN_close() failed: err=%d '%s'\n", err, strerror(err)); - exit(-1); - } + FATAL("mISDN_close() failed: err=%d '%s'\n", err, strerror(err)); } @@ -2388,26 +2378,44 @@ void mISDN_port_info(void) */ void PmISDN::txfromup(unsigned char *data, int length) { - int avail; - /* no data */ - if (!length) - return; + unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)]; + iframe_t *frm = (iframe_t *)buf; - /* get free samples in buffer */ - avail = ((p_m_fromup_buffer_readp - p_m_fromup_buffer_writep - 1) & FROMUP_BUFFER_MASK); - if (avail < length) - { - PDEBUG(DEBUG_PORT, "Port(%d): fromup_buffer overflows, this shall not happen under normal conditions\n", p_serial); + /* configure frame */ + frm->prim = DL_DATA | REQUEST; + frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN; + frm->dinfo = 0; + + /* check if high priority tones exist + * ignore data in this case + */ + if (p_tone_name[0] || p_m_crypt_msg_loops) return; - } - /* write data to buffer and return */ - while(length) + /* preload procedure + * if transmit buffer in DSP module is empty, + * preload it to DSP_LOAD to prevent jitter gaps. + */ + if (p_m_load==0 && ISDN_LOAD>0) { - p_m_fromup_buffer[p_m_fromup_buffer_writep] = *data++; - p_m_fromup_buffer_writep = (p_m_fromup_buffer_writep + 1) & FROMUP_BUFFER_MASK; - length--; + + memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD); + frm->len = ISDN_LOAD; + mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC); + p_m_load += frm->len; } - return; // must return, because length is 0 + + /* drop if load would exceed ISDN_MAXLOAD + * this keeps the delay not too high + */ + if (p_m_load+length > ISDN_MAXLOAD) + return; + + /* load data to buffer + */ + memcpy(buf+mISDN_HEADER_LEN, data, length); + frm->len = length; + mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC); + p_m_load += frm->len; } diff --git a/mISDN.h b/mISDN.h index e8df862..030c5fc 100644 --- a/mISDN.h +++ b/mISDN.h @@ -58,6 +58,7 @@ struct mISDNport { int b_addr[128]; int b_state[128]; /* state 0 = IDLE */ int procids[128]; /* keep track of free ids */ + int locally; /* local causes are sent as local causes not remote */ msg_queue_t downqueue; /* l4->l3 */ }; extern mISDNport *mISDNport_first; @@ -119,9 +120,12 @@ class PmISDN : public Port int p_m_dtmf; /* dtmf decoding is enabled */ int p_m_calldata; /* the call requires data due to no briging capability */ - int p_m_fromup_buffer_readp; /* buffer for audio from remote endpoint */ - int p_m_fromup_buffer_writep; - unsigned char p_m_fromup_buffer[FROMUP_BUFFER_SIZE]; + int p_m_load; /* current data in dsp tx buffer */ + unsigned long p_m_last_tv_sec; /* time stamp of last handler call, (to sync audio data */ + unsigned long p_m_last_tv_msec; +// int p_m_fromup_buffer_readp; /* buffer for audio from remote endpoint */ +// int p_m_fromup_buffer_writep; +// unsigned char p_m_fromup_buffer[FROMUP_BUFFER_SIZE]; void txfromup(unsigned char *data, int length); int p_m_crypt; /* encryption is enabled */ @@ -146,8 +150,8 @@ class PmISDN : public Port int p_m_b_channel; /* number 1,2 1..15,17... */ int p_m_b_exclusive; /* if bchannel is exclusive */ int p_m_b_reserve; /* set if channel is reserved */ - long long p_m_jittercheck; /* time of audio data */ - long long p_m_jitterdropped; /* number of bytes dropped */ +// long long p_m_jittercheck; /* time of audio data */ +// long long p_m_jitterdropped; /* number of bytes dropped */ int p_m_delete; /* true if obj. must del. */ int p_m_hold; /* if port is on hold */ unsigned long p_m_timeout; /* timeout of timers */ diff --git a/mail.c b/mail.c index d4c6441..b55fc56 100644 --- a/mail.c +++ b/mail.c @@ -179,8 +179,7 @@ static void *mail_child(void *arg) PDEBUG(DEBUG_EPOINT, "child process done for sending a mail\n"); /* exit process */ - memset(args, 0, sizeof(struct mail_args)); - free(args); + FREE(args, sizeof(struct mail_args)); amemuse--; return(NULL); } @@ -190,12 +189,7 @@ void send_mail(char *filename, char *callerid, char *callerintern, char *callern struct mail_args *arg; pthread_t tid; - arg = (struct mail_args *)calloc(1, sizeof(struct mail_args)); - if (!arg) - { - PERROR("failed to alloc memory.\n"); - return; - } + arg = (struct mail_args *)MALLOC(sizeof(struct mail_args)); amemuse++; SCPY(arg->email, vbox_email); diff --git a/main.c b/main.c index 3d905d0..d0c39e1 100644 --- a/main.c +++ b/main.c @@ -222,7 +222,7 @@ int main(int argc, char *argv[]) printf("rules [action] = Get individual help for given action.\n"); // printf("route = Show current routing as it is parsed.\n"); printf("\n"); - ret = 0; + ret = 999; goto free; } @@ -807,6 +807,8 @@ free: MEMCHECK("file handler(s) left",fhuse) /* take me out */ + if (ret == 999) + exit(0); SPRINT(tracetext, "%s exit", NAME); printf("%s\n", tracetext); start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext); diff --git a/main.h b/main.h index 723d51c..6d0e32c 100644 --- a/main.h +++ b/main.h @@ -32,6 +32,7 @@ extern int fhuse; #define PERROR_RUNTIME(fmt, arg...) _printerror(NULL, 0, fmt, ## arg) void _printdebug(const char *function, int line, unsigned long mask, const char *fmt, ...); void _printerror(const char *function, int line, const char *fmt, ...); +#define DEBUG_FUNC void debug(const char *function, int line, char *prefix, char *buffer); #define DEBUG_CONFIG 0x0001 @@ -59,24 +60,18 @@ void debug(const char *function, int line, char *prefix, char *buffer); #define DEBUG_LOG 0x7fff /* - * preload transmit buffer to avoid gaps at the beginning due to jitter - * this is also the maximum load that will be kept in tx-buffer - */ -#define ISDN_PRELOAD 1024 // samples - -/* - * interval for refreshing transmit buffer + * load transmit buffer to avoid gaps at the beginning due to jitter + * also the maximum load that will be kept in tx-buffer + * also the (minimum) number of data to transmit in a frame */ +#define ISDN_LOAD 1024 // samples +#define ISDN_MAXLOAD 2048 // samples #define ISDN_TRANSMIT 256 // samples /* give sendmail program. if not inside $PATH, give absolute path here (e.g. "/usr/sbin/sendmail") */ #define SENDMAIL "sendmail" -/* maximum number of redial/powerdial and reply numbers to remember - */ -#define MAX_REMEMBER 50 - /* leave it above 1024, because lower values can be unsafe, higher valuse cause * data larger than 512 bytes of hex strings. */ @@ -88,6 +83,11 @@ void debug(const char *function, int line, char *prefix, char *buffer); */ #define RULE_NESTING 10 +/* to debug core bridging, rather than mISDN dsp bridging, enable. + * this is for debugging only, bridging conferences will not work + */ +//#define DEBUG_COREBRIDGE + /* special debugging for buffer overflow bugs * note: whenever a buffer gets strange values, the budetect function must * be modified to detect the change of these values. whenever it is detected, @@ -117,7 +117,7 @@ extern "C" { #ifdef __cplusplus } #endif -#include "save.h" +#include "macro.h" #include "options.h" #include "interface.h" #include "extension.h" @@ -132,7 +132,7 @@ extern "C" { #include "vbox.h" #include "call.h" #include "callpbx.h" -#include "callchan.h" +#include "callasterisk.h" #include "cause.h" #include "alawulaw.h" #include "tones.h" diff --git a/message.c b/message.c index 0e4fd67..daa0992 100644 --- a/message.c +++ b/message.c @@ -23,28 +23,12 @@ struct message **messagepointer_end = &message_first; struct message *message_create(int id_from, int id_to, int flow, int type) { struct message *message; - int i = 0; - while(i < 10) - { - message = (struct message *)calloc(1, sizeof(struct message)); - if (message) - break; - - if (!i) - PERROR("no mem for message, retrying...\n"); - i++; - usleep(300000); - } + message = (struct message *)MALLOC(sizeof(struct message)); if (!message) - { - PERROR("***Fatal error: no mem for message!!! exitting.\n"); - exit(-1); - } + FATAL("No memory for message.\n"); mmemuse++; - memset(message, 0, sizeof(struct message)); - message->id_from = id_from; message->id_to = id_to; message->flow = flow; @@ -70,6 +54,21 @@ void message_put(struct message *message) messagepointer_end = &(message->next); } +void message_forward(int id_from, int id_to, int flow, union parameter *param) +{ + struct message *message; + + /* get point to message */ + message = (struct message *)((unsigned long)param - ((unsigned long)(&message->param) - (unsigned long)message)); + + /* protect, so forwarded messages are not freed after handling */ + message->keep = 1; + + message->id_from = id_from; + message->id_to = id_to; + message->flow = flow; + message_put(message); +} /* detaches the first messages from the message chain */ struct message *message_get(void) @@ -86,7 +85,10 @@ struct message *message_get(void) if (!message_first) messagepointer_end = &message_first; + message->keep = 0; + if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA) + PDEBUG(DEBUG_MSG, "message %s reading from %ld to %ld (memory %x)\n", messages_txt[message->type], message->id_from, message->id_to, message); return(message); @@ -95,8 +97,9 @@ struct message *message_get(void) /* free a message */ void message_free(struct message *message) { - memset(message, 0, sizeof(struct message)); - free(message); + if (message->keep) + return; + FREE(message, sizeof(struct message)); mmemuse--; } diff --git a/message.h b/message.h index fc00c02..c45867d 100644 --- a/message.h +++ b/message.h @@ -154,7 +154,7 @@ struct connect_info { char extension[32]; /* internal id */ char name[16]; int isdn_port; /* internal/external port (if call is isdn) */ - char interfaces[128]; /* interfaces for extenal calls */ + char interface[128]; /* interface for extenal calls */ int itype; /* type of interface */ int ntype; /* type of number */ int present; /* presentation */ @@ -311,6 +311,7 @@ struct message { int flow; /* from where to where */ unsigned long id_from; /* in case of flow==PORT_TO_EPOINT: id_from is the port's serial, id_to is the epoint's serial */ unsigned long id_to; + int keep; union parameter param; }; @@ -348,6 +349,7 @@ enum { /* messages between entities */ MESSAGE_VBOX_TONE, /* set answering VBOX tone */ MESSAGE_TONE_COUNTER, /* tone counter (for VBOX tone use) */ MESSAGE_TONE_EOF, /* tone is end of file */ + MESSAGE_HELLO, /* hello message for asterisk */ }; #define MESSAGES static const char *messages_txt[] = { \ @@ -379,11 +381,13 @@ enum { /* messages between entities */ "MESSAGE_VBOX_TONE", \ "MESSAGE_TONE_COUNTER", \ "MESSAGE_TONE_EOF", \ + "MESSAGE_HELLO", \ }; struct message *message_create(int id_from, int id_to, int flow, int type); void message_put(struct message *message); +void message_forward(int id_from, int id_to, int flow, union parameter *param); struct message *message_get(void); void message_free(struct message *message); diff --git a/port.cpp b/port.cpp index abd480d..0fdfd39 100644 --- a/port.cpp +++ b/port.cpp @@ -88,8 +88,7 @@ void Port::free_epointlist(struct epoint_list *epointlist) /* free */ PDEBUG(DEBUG_EPOINT, "PORT(%d) removed epoint from port\n", p_serial); - memset(temp, 0, sizeof(struct epoint_list)); - free(temp); + FREE(temp, sizeof(struct epoint_list)); ememuse--; } @@ -110,7 +109,7 @@ void Port::free_epointid(unsigned long epoint_id) } if (temp == 0) { - PERROR("epoint_id not in port's list, exitting.\n"); + PERROR("epoint_id not in port's list.\n"); return; } /* detach */ @@ -118,8 +117,7 @@ void Port::free_epointid(unsigned long epoint_id) /* free */ PDEBUG(DEBUG_EPOINT, "PORT(%d) removed epoint from port\n", p_serial); - memset(temp, 0, sizeof(struct epoint_list)); - free(temp); + FREE(temp, sizeof(struct epoint_list)); ememuse--; } @@ -131,15 +129,11 @@ struct epoint_list *Port::epointlist_new(unsigned long epoint_id) struct epoint_list *epointlist, **epointlistpointer; /* epointlist structure */ - epointlist = (struct epoint_list *)calloc(1, sizeof(struct epoint_list)); + epointlist = (struct epoint_list *)MALLOC(sizeof(struct epoint_list)); if (!epointlist) - { - PERROR("no mem for allocating epoint_list\n"); - return(0); - } + FATAL("No memory for epointlist\n"); ememuse++; PDEBUG(DEBUG_EPOINT, "PORT(%d) allocating epoint_list.\n", p_serial); - memset(epointlist, 0, sizeof(struct epoint_list)); /* add epoint_list to chain */ epointlist->next = NULL; @@ -175,11 +169,8 @@ Port::Port(int type, char *portname, struct port_settings *settings) } SCPY(p_name, portname); SCPY(p_tone_dir, p_settings.tones_dir); // just to be sure - p_last_tv_sec = 0; - p_last_tv_msec = 0; p_type = type; p_serial = port_serial++; - p_debug_nothingtosend = 0; p_tone_fh = -1; p_tone_fetched = NULL; p_tone_name[0] = '\0'; @@ -255,10 +246,7 @@ Port::~Port(void) temp = temp->next; } if (temp == NULL) - { - PERROR("PORT(%s) port not in port's list.\n", p_name); - exit(-1); - } + FATAL("PORT(%s) port not in port's list.\n", p_name); /* detach */ *tempp=this->next; @@ -495,7 +483,7 @@ void Port::set_vbox_speed(int speed) /* * read from the given file as specified in port_set_tone and return sample data - * silence is appended if sample ends, but only the number of samples with tones are returned + * if the tone ends, the result may be less samples than requested */ int Port::read_audio(unsigned char *buffer, int length) { @@ -511,12 +499,8 @@ int Port::read_audio(unsigned char *buffer, int length) len = length; /* if there is no tone set, use silence */ - if (p_tone_name[0] == 0) - { -rest_is_silence: - memset(buffer, (options.law=='a')?0x2a:0xff, len); /* silence */ - goto done; - } + if (!p_tone_name[0]) + return(0); /* if the file pointer is not open, we open it */ if (p_tone_fh<0 && p_tone_fetched==NULL) @@ -586,7 +570,7 @@ read_more: } if (len==0) - goto done; + return(length-len); if (p_tone_fh >= 0) { @@ -605,7 +589,7 @@ read_more: PDEBUG(DEBUG_PORT, "PORT(%s) 0-length loop: %s\n", p_name, filename); p_tone_name[0]=0; p_tone_dir[0]=0; - goto rest_is_silence; + return(length-len); } /* if eof is reached, or if the normal file cannot be opened, continue with the loop file if possible */ @@ -630,7 +614,7 @@ try_loop: PDEBUG(DEBUG_PORT, "PORT(%s) no tone loop: %s\n",p_name, filename); p_tone_dir[0] = '\0'; p_tone_name[0] = '\0'; - goto rest_is_silence; + return(length-len); } fhuse++; } @@ -643,7 +627,7 @@ try_loop: PDEBUG(DEBUG_PORT, "PORT(%s) no tone loop: %s\n",p_name, filename); p_tone_dir[0] = '\0'; p_tone_name[0] = '\0'; - goto rest_is_silence; + return(length-len); } fhuse++; } @@ -652,9 +636,6 @@ try_loop: /* now we have opened the loop */ goto read_more; - -done: - return(length-len); } diff --git a/port.h b/port.h index 3a7bdb1..23b9986 100644 --- a/port.h +++ b/port.h @@ -144,9 +144,6 @@ class Port struct port_settings p_settings; /* tone */ - unsigned long p_last_tv_sec; /* time stamp of last handler call, (to sync audio data */ - unsigned long p_last_tv_msec; - int p_debug_nothingtosend; /* used for debugging the, if we have currently nothing to send (used for ISDN) */ char p_tone_dir[256]; /* name of current directory */ char p_tone_name[256]; /* name of current tone */ char p_tone_fh; /* file descriptor of current tone or -1 if not open */ diff --git a/route.c b/route.c index 97c61a6..f0c7c8a 100644 --- a/route.c +++ b/route.c @@ -91,7 +91,11 @@ struct cond_defs cond_defs[] = { { "busy", MATCH_BUSY, COND_TYPE_STRING, "busy=[,...]","Matches if any of the given extension is busy."}, { "notbusy", MATCH_IDLE, COND_TYPE_STRING, - "notbusy[,...]","Matches if any of the given extension is not busy."}, + "notbusy=[,...]","Matches if any of the given extension is not busy."}, + { "asterisk", MATCH_ASTERISK, COND_TYPE_NULL, + "asterisk","Matches if asterisk is not running with LCR channel driver."}, + { "notasterisk",MATCH_NOTASTERISK,COND_TYPE_NULL, + "notasterisk","Matches if asterisk is not running with LCR channel driver."}, { NULL, 0, 0, NULL} }; @@ -477,16 +481,16 @@ void ruleset_free(struct route_ruleset *ruleset_start) cond = rule->cond_first; if (cond->string_value) { - free(cond->string_value); + FREE(cond->string_value, 0); rmemuse--; } if (cond->string_value_to) { - free(cond->string_value_to); + FREE(cond->string_value_to, 0); rmemuse--; } rule->cond_first = cond->next; - free(cond); + FREE(cond, sizeof(struct route_cond)); rmemuse--; } while(rule->action_first) @@ -499,19 +503,19 @@ void ruleset_free(struct route_ruleset *ruleset_start) action->param_first = param->next; if (param->string_value) { - free(param->string_value); + FREE(param->string_value, 0); rmemuse--; } - free(param); + FREE(param, sizeof(struct route_param)); rmemuse--; } - free(action); + FREE(action, sizeof(struct route_action)); rmemuse--; } - free(rule); + FREE(rule, sizeof(struct route_rule)); rmemuse--; } - free(ruleset); + FREE(ruleset, sizeof(struct route_ruleset)); rmemuse--; } } @@ -1002,14 +1006,8 @@ struct route_ruleset *ruleset_parse(void) } /* create ruleset */ - ruleset = (struct route_ruleset *)malloc(sizeof(struct route_ruleset)); - if (ruleset == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + ruleset = (struct route_ruleset *)MALLOC(sizeof(struct route_ruleset)); rmemuse++; - memset(ruleset, 0, sizeof(struct route_ruleset)); *ruleset_pointer = ruleset; ruleset_pointer = &(ruleset->next); SCPY(ruleset->name, key); @@ -1026,15 +1024,9 @@ struct route_ruleset *ruleset_parse(void) goto new_ruleset; } - /* alloc memory for rule */ - rule = (struct route_rule *)malloc(sizeof(struct route_rule)); - if (rule == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + /* Alloc memory for rule */ + rule = (struct route_rule *)MALLOC(sizeof(struct route_rule)); rmemuse++; - memset(rule, 0, sizeof(struct route_rule)); *rule_pointer = rule; rule_pointer = &(rule->next); cond_pointer = &(rule->cond_first); @@ -1121,15 +1113,9 @@ struct route_ruleset *ruleset_parse(void) } nextcondvalue: - /* alloc memory for item */ - cond = (struct route_cond *)malloc(sizeof(struct route_cond)); - if (cond == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + /* Alloc memory for item */ + cond = (struct route_cond *)MALLOC(sizeof(struct route_cond)); rmemuse++; - memset(cond, 0, sizeof(struct route_cond)); *cond_pointer = cond; cond_pointer = &(cond->next); cond->index = index; @@ -1314,22 +1300,12 @@ struct route_ruleset *ruleset_parse(void) } } alloc_string: - cond->string_value = (char *)malloc(strlen(key)+1); - if (cond->string_value == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + cond->string_value = (char *)MALLOC(strlen(key)+1); rmemuse++; UCPY(cond->string_value, key); if (value_type == VALUE_TYPE_STRING_RANGE) { - cond->string_value_to = (char *)malloc(strlen(key_to)+1); - if (cond->string_value_to == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + cond->string_value_to = (char *)MALLOC(strlen(key_to)+1); rmemuse++; UCPY(cond->string_value_to, key_to); cond->comp_string = strcmp(key, key_to); @@ -1484,14 +1460,8 @@ struct route_ruleset *ruleset_parse(void) } /* alloc memory for action */ - action = (struct route_action *)malloc(sizeof(struct route_action)); - if (action == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + action = (struct route_action *)MALLOC(sizeof(struct route_action)); rmemuse++; - memset(action, 0, sizeof(struct route_action)); *action_pointer = action; action_pointer = &(action->next); param_pointer = &(action->param_first); @@ -1619,15 +1589,9 @@ struct route_ruleset *ruleset_parse(void) } nextparamvalue: - /* alloc memory for param */ - param = (struct route_param *)malloc(sizeof(struct route_param)); - if (param == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + /* Alloc memory for param */ + param = (struct route_param *)MALLOC(sizeof(struct route_param)); rmemuse++; - memset(param, 0, sizeof(struct route_param)); *param_pointer = param; param_pointer = &(param->next); param->index = index; @@ -1864,12 +1828,7 @@ struct route_ruleset *ruleset_parse(void) SPRINT(failure, "Value '%s' unknown. ('yes' or 'no')", key); goto parse_error; } - param->string_value = (char *)malloc(strlen(key)+1); - if (param->string_value == NULL) - { - SPRINT(failure, "Out of memory."); - goto parse_error; - } + param->string_value = (char *)MALLOC(strlen(key)+1); rmemuse++; UCPY(param->string_value, key); param->value_type = VALUE_TYPE_STRING; @@ -1991,6 +1950,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) FILE *tfp; double timeout; struct mISDNport *mISDNport; + struct admin_list *admin; /* reset timeout action */ e_match_timeout = 0; /* no timeout */ @@ -2231,6 +2191,7 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; case MATCH_BUSY: + case MATCH_IDLE: any = 0; mISDNport = mISDNport_first; while(mISDNport) @@ -2241,21 +2202,24 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) break; mISDNport = mISDNport->next; } - if (mISDNport) + if (mISDNport && cond->match==MATCH_BUSY) + istrue = 1; + if (!mISDNport && cond->match==MATCH_IDLE) istrue = 1; break; - case MATCH_IDLE: - mISDNport = mISDNport_first; - while(mISDNport) + case MATCH_ASTERISK: + case MATCH_NOTASTERISK: + admin = admin_list; + while(admin) { - if (mISDNport->ifport) - if (!strcasecmp(mISDNport->ifport->interface->name, cond->string_value)) - if (mISDNport->use) /* break if in use */ + if (admin->asterisk) break; - mISDNport = mISDNport->next; + admin = admin->next; } - if (!mISDNport) + if (admin && cond->match==MATCH_ASTERISK) + istrue = 1; + if (!admin && cond->match==MATCH_NOTASTERISK) istrue = 1; break; diff --git a/route.h b/route.h index 97a2429..c83ffcc 100644 --- a/route.h +++ b/route.h @@ -72,6 +72,8 @@ enum { /* what to check during runtime */ MATCH_UP, MATCH_BUSY, MATCH_IDLE, + MATCH_ASTERISK, + MATCH_NOTASTERISK, }; enum { /* how to parse text file during startup */ diff --git a/todo.txt b/todo.txt index 079294f..60ef972 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,3 @@ -BUG: no channels after reload interfaces -BUG: audio is corrupted, shall we use fh or name for state of tones? BUG: release to NT not always work make asterisk call implementation @@ -8,7 +6,7 @@ avoid disconnect-collision (release if disconnect from both sides) display message during nothing/play -Port -> Channel +Port -> Proc Call -> Link maybe: @@ -31,3 +29,6 @@ sonderwahlton facility: diversion, 3pty, ... +VLAN-Kamera + + diff --git a/tones.c b/tones.c index 0cd4684..4a386ff 100644 --- a/tones.c +++ b/tones.c @@ -377,8 +377,7 @@ int read_tone(int fh, unsigned char *buffer, int codec, int len, signed long siz break; default: - PERROR("codec %d is not supported, exitting...\n", codec); - exit(-1); + FATAL("codec %d is not supported.\n", codec); } if (l>0 && left) @@ -406,12 +405,12 @@ void free_tones(void) { temp = tonesettone_temp; tonesettone_temp = tonesettone_temp->next; - free(temp); + FREE(temp, sizeof(struct tonesettone)); memuse--; } temp = toneset_temp; toneset_temp = toneset_temp->next; - free(temp); + FREE(temp, sizeof(struct toneset)); memuse--; } toneset_first = NULL; @@ -465,15 +464,9 @@ int fetch_tones(void) printf("PBX: Fetching tones '%s'\n", p); PDEBUG(DEBUG_PORT, "fetching tones directory '%s'\n", p); - *toneset_nextpointer = (struct toneset *)calloc(1, sizeof(struct toneset)); - if (*toneset_nextpointer == NULL) - { - PERROR("No memory for tone set: '%s'\n",p); - return(0); - } + *toneset_nextpointer = (struct toneset *)MALLOC(sizeof(struct toneset)); memuse++; memory += sizeof(struct toneset); - memset(*toneset_nextpointer, 0 , sizeof(struct toneset)); SCPY((*toneset_nextpointer)->directory, p); tonesettone_nextpointer = &(*toneset_nextpointer)->first; @@ -526,18 +519,10 @@ int fetch_tones(void) continue; } - /* allocate tone */ - *tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+tone_size); - if (*toneset_nextpointer == NULL) - { - PERROR("No memory for tone set: '%s'\n",p); - close(fh); - fduse--; - return(0); - } + /* Allocate tone */ + *tonesettone_nextpointer = (struct tonesettone *)MALLOC(sizeof(struct tonesettone)+tone_size); memuse++; //printf("tone:%s, %ld bytes\n", name, tone_size); - memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+tone_size); memory += sizeof(struct tonesettone)+tone_size; samples ++; diff --git a/trace.c b/trace.c index 9453bd7..6223684 100644 --- a/trace.c +++ b/trace.c @@ -325,11 +325,8 @@ void end_trace(void) } /* create state response */ - response = (struct admin_queue *)malloc(sizeof(struct admin_queue)+sizeof(admin_message)); - if (!response) - return; + response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message)); memuse++; - memset(response, 0, sizeof(admin_queue)+sizeof(admin_message)); response->num = 1; /* message */ response->am[0].message = ADMIN_TRACE_RESPONSE; @@ -350,4 +347,3 @@ void end_trace(void) - diff --git a/vbox.cpp b/vbox.cpp index 4585680..48dcbab 100644 --- a/vbox.cpp +++ b/vbox.cpp @@ -243,15 +243,8 @@ int VBoxPort::message_epoint(unsigned long epoint_id, int message_id, union para memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo)); /* link relation */ if (p_epointlist) - { - PERROR("PORT(%s) software error: epoint pointer is set in idle state, how bad!! exitting.\n", p_name); - exit(-1); - } - if (!(epointlist_new(epoint_id))) - { - PERROR("no memory for epointlist\n"); - exit(-1); - } + FATAL("PORT(%s) Epoint pointer is set in idle state, how bad!!\n", p_name); + epointlist_new(epoint_id); /* copy setup infos to port */ SCPY(p_vbox_extension, param->setup.dialinginfo.id); -- 2.13.6