backup
authorSuper User <root@isdn.jolly.ten>
Sun, 15 Jul 2007 10:01:27 +0000 (12:01 +0200)
committerSuper User <root@isdn.jolly.ten>
Sun, 15 Jul 2007 10:01:27 +0000 (12:01 +0200)
38 files changed:
Makefile
README
action.cpp
admin.h
admin_client.c
admin_server.c
admin_server.h
apppbx.cpp
apppbx.h
call.cpp
call.h
callpbx.cpp
callpbx.h
cause.c
cause.h
crypt.cpp
dss1.cpp
endpoint.cpp
endpoint.h
extension.h
genrc.c
ie.cpp
interface.c
mISDN.cpp
mISDN.h
mail.c
main.c
main.h
message.c
message.h
port.cpp
port.h
route.c
route.h
todo.txt
tones.c
trace.c
vbox.cpp

index 420653d..c06b281 100644 (file)
--- 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 (file)
--- 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...
 
index b77d937..3e8ba8b 100644 (file)
@@ -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 (file)
--- 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;
index 2bffa73..5ab45f6 100644 (file)
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <curses.h>
-#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);
index 1bb07af..c972ea5 100644 (file)
@@ -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(&param, 0, sizeof(param));
+                               param.disconnectinfo.cause = CAUSE_OUTOFORDER;
+                               param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+                               ((class CallAsterisk *)call)->message_asterisk(0, MESSAGE_RELEASE, &param);
+                               /* 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--;
                        }
                }
index 1b472bb..d83c451 100644 (file)
@@ -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);
 
 
 
index 06ff785..23e20ac 100644 (file)
@@ -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:"<empty>");
+               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:"<empty>");
-                       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:"<empty>");
-                       end_trace();
+               } else
+               {
+                       UNCPY(id, ifscreen->result, idsize);
+                       id[idsize-1] = '\0';
                }
+               add_trace("used", "id", "%s", id[0]?id:"<empty>");
+               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, &param->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, &param->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;
index a3fa660..a4baef1 100644 (file)
--- 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);
 };
 
 
index a566080..38f6b19 100644 (file)
--- 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 (file)
--- 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 */
index 418654d..7fede81 100644 (file)
@@ -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);
 }
 
+
index c84d89a..755bdc5 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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);
index 2b75792..7868ceb 100644 (file)
--- 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)
        }
 }
 
+
index 61c8921..e561c07 100644 (file)
--- 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);
index 53d2149..819f779 100644 (file)
@@ -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--;
 }
 
index 744f3ea..fb8e8d2 100644 (file)
@@ -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 */
index f62eb96..692906e 100644 (file)
@@ -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 (file)
--- a/genrc.c
+++ b/genrc.c
@@ -13,7 +13,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
-#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 (file)
--- 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];
        }
index 7b90d15..1a17842 100644 (file)
@@ -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 */
index c53b758..9a492de 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- 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"
index 0e4fd67..daa0992 100644 (file)
--- 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--;
 }
 
index fc00c02..c45867d 100644 (file)
--- 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);
 
index abd480d..0fdfd39 100644 (file)
--- 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 (file)
--- 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 (file)
--- a/route.c
+++ b/route.c
@@ -91,7 +91,11 @@ struct cond_defs cond_defs[] = {
        { "busy",       MATCH_BUSY,     COND_TYPE_STRING,
          "busy=<extension>[,...]","Matches if any of the given extension is busy."},
        { "notbusy",    MATCH_IDLE,     COND_TYPE_STRING,
-         "notbusy<extension>[,...]","Matches if any of the given extension is not busy."},
+         "notbusy=<extension>[,...]","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 (file)
--- 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 */
index 079294f..60ef972 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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)
 
 
 
-
index 4585680..48dcbab 100644 (file)
--- 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, &param->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);