Adding bridge between protocol handlers (ports)
authorAndreas Eversberg <jolly@eversberg.eu>
Sat, 14 Jan 2012 17:36:26 +0000 (18:36 +0100)
committerAndreas Eversberg <jolly@eversberg.eu>
Sat, 14 Jan 2012 17:36:26 +0000 (18:36 +0100)
This is required to bridge traffic beween non-mISDN handlers,
such as GSM, SIP and voice box. Also it bridges traffic between
mISDN handlers and non-mISDN handlers. It is the fundamental step
to get rid of mISDN (loop interface) for non-mISDN handlers.
This is required to bridge audio e.g. between SIP and GSM without
using mISDN. There will be no limitations on 'b-channels' anymore.

Still GSM and SIP requires mISDN, but this will be changed later.

With that bridge I cleaned up some code and also removed the
MESSAGE_DATA, which is not required anymore.

21 files changed:
Makefile.am
apppbx.cpp
apppbx.h
genext.c
joinpbx.cpp
joinpbx.h
mISDN.cpp
mISDN.h
macro.h
main.c
main.h
message.c
message.h
port.cpp
port.h
select.c
select.h
sip.cpp
trace.c
vbox.cpp
vbox.h

index a97a7ec..629bb50 100644 (file)
@@ -133,14 +133,13 @@ endif
 
 INCLUDES = $(all_includes) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) -Wall $(INSTALLATION_DEFINES)
 
 
 INCLUDES = $(all_includes) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) -Wall $(INSTALLATION_DEFINES)
 
-lcr_SOURCES = $(GSM_SOURCE) $(SS5_SOURCE) $(SIP_SOURCE) select.c action.cpp mISDN.cpp \
-       tones.c loop.c remote.cpp action_efi.cpp crypt.cpp mail.c trace.c \
-       action_vbox.cpp  dss1.cpp         main.c           \
-       vbox.cpp alawulaw.c       endpoint.cpp     interface.c     message.c \
-       apppbx.cpp       endpointapp.cpp  join.cpp        options.c       \
-       extension.c      joinpbx.cpp     port.cpp \
-       callerid.c       joinremote.cpp  route.c \
-       cause.c          socket_server.c
+lcr_SOURCES = \
+       main.c select.c trace.c \ options.c \ tones.c \ alawulaw.c \ cause.c \ interface.c \ message.c \ callerid.c \ socket_server.c \
+       port.cpp \ vbox.cpp \ mISDN.cpp \ dss1.cpp \ loop.c remote.cpp \
+       $(GSM_SOURCE) $(SS5_SOURCE) $(SIP_SOURCE) \
+       endpoint.cpp \ endpointapp.cpp \
+       apppbx.cpp \ route.c \ action.cpp action_efi.cpp \ action_vbox.cpp \ extension.c \ crypt.cpp \ mail.c \
+       join.cpp \ joinpbx.cpp \ joinremote.cpp
 
 lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread $(GSM_LIB) $(SIP_LIB)
 
 
 lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread $(GSM_LIB) $(SIP_LIB)
 
index d3937a7..1b119b2 100644 (file)
@@ -2621,17 +2621,6 @@ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, uni
 
 //     PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
        switch(message_type) {
 
 //     PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
        switch(message_type) {
-               case MESSAGE_DATA: /* data from port */
-               /* check if there is a call */
-               if (!ea_endpoint->ep_join_id)
-                       break;
-               /* continue if only one portlist */
-               if (ea_endpoint->ep_portlist->next != NULL)
-                       break;
-               /* forward message */
-               message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);  
-               break;
-
                case MESSAGE_TONE_EOF: /* tone is end of file */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
                if (e_action) {
                case MESSAGE_TONE_EOF: /* tone is end of file */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
                if (e_action) {
@@ -3235,6 +3224,19 @@ void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_ty
        }
 }
 
        }
 }
 
+/* join MESSAGE_BRIDE */
+void EndpointAppPBX::join_bridge(struct port_list *portlist, int message_type, union parameter *param)
+{
+       struct lcr_msg *message;
+
+       while(portlist) {
+               message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
+               memcpy(&message->param, param, sizeof(union parameter));
+               message_put(message);
+               portlist = portlist->next;
+       }
+}
+
 /* join MESSAGE_NOTIFY */
 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
 {
 /* join MESSAGE_NOTIFY */
 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
 {
@@ -3316,21 +3318,6 @@ void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, uni
 
        portlist = ea_endpoint->ep_portlist;
 
 
        portlist = ea_endpoint->ep_portlist;
 
-       /* send MESSAGE_DATA to port */
-       if (message_type == MESSAGE_DATA) {
-               if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
-                       /* skip if no port relation */
-                       if (!portlist)
-                               return;
-                       /* skip if more than one port relation */
-                       if (portlist->next)
-                               return;
-                       /* forward audio data to port */
-                       message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
-                       return;
-               }
-       }
-
 //     PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
        switch(message_type) {
                /* JOIN SENDS TONE message */
 //     PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
        switch(message_type) {
                /* JOIN SENDS TONE message */
@@ -3420,23 +3407,11 @@ void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, uni
                join_mISDNsignal(portlist, message_type, param);
                break;
 
                join_mISDNsignal(portlist, message_type, param);
                break;
 
-#if 0
-               kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
-               /* JOIN requests bchannel */
-               case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
-               /* only one port is expected to be connected to bchannel */
-               if (!portlist)
-                       break;
-               if (portlist->next)
-                       break;
-               e_join_pattern = 1;
-               SCPY(e_tone, "");
-               set_tone(portlist, NULL);
-               message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
-               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+               /* JOIN sends bridge message */
+               case MESSAGE_BRIDGE: /* bride message to port */
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bridge message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               join_bridge(portlist, message_type, param);
                break;
                break;
-#endif
 
                /* JOIN has pattern available */
                case MESSAGE_PATTERN: /* indicating pattern available */
 
                /* JOIN has pattern available */
                case MESSAGE_PATTERN: /* indicating pattern available */
index cfe99c1..552e7ca 100644 (file)
--- a/apppbx.h
+++ b/apppbx.h
@@ -214,6 +214,7 @@ class EndpointAppPBX : public EndpointApp
        void ea_message_join(unsigned int join_id, int message, union parameter *param);
        void join_crypt(struct port_list *portlist, int message_type, union parameter *param);
        void join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param);
        void ea_message_join(unsigned int join_id, int message, union parameter *param);
        void join_crypt(struct port_list *portlist, int message_type, union parameter *param);
        void join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param);
+       void join_bridge(struct port_list *portlist, int message_type, union parameter *param);
        void join_setup(struct port_list *portlist, int message_type, union parameter *param);
        void join_information(struct port_list *portlist, int message_type, union parameter *param);
        void join_overlap(struct port_list *portlist, int message_type, union parameter *param);
        void join_setup(struct port_list *portlist, int message_type, union parameter *param);
        void join_information(struct port_list *portlist, int message_type, union parameter *param);
        void join_overlap(struct port_list *portlist, int message_type, union parameter *param);
index 4d34bbe..e9de687 100644 (file)
--- a/genext.c
+++ b/genext.c
@@ -30,11 +30,11 @@ int fhuse = 0;
 struct isdn_cause isdn_cause[128];
 struct isdn_location isdn_location[16];
 
 struct isdn_cause isdn_cause[128];
 struct isdn_location isdn_location[16];
 
-void _printdebug(const char *function, int line, unsigned int mask, const char *fmt, ...)
+void _printdebug(const char *file, const char *function, int line, unsigned int mask, const char *fmt, ...)
 {
 }
 
 {
 }
 
-void _printerror(const char *function, int line, const char *fmt, ...)
+void _printerror(const char *file, const char *function, int line, const char *fmt, ...)
 {
        char buffer[4096];
        va_list args;
 {
        char buffer[4096];
        va_list args;
index 4b06540..a98765f 100644 (file)
@@ -367,15 +367,12 @@ void JoinPBX::bridge(void)
                }
 
                /*
                }
 
                /*
-                * request data from endpoint/port if:
-                * - two relations
-                * - any without mISDN
-                * in this case we bridge
+                * Bridge between port instances if:
+                * - one or all are not mISDN
                 */
                 */
-               message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
-               message->param.mISDNsignal.message = mISDNSIGNAL_JOINDATA;
-               message->param.mISDNsignal.joindata = (relations==2 && !allmISDN);
-               PDEBUG(DEBUG_JOIN, "join%d EP%d set joindata=%d\n", j_serial, relation->epoint_id, message->param.mISDNsignal.joindata);
+               message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE);
+               message->param.bridge_id = j_serial;
+               PDEBUG(DEBUG_JOIN, "join%u EP%u requests bridge=%u\n", j_serial, relation->epoint_id, message->param.bridge_id);
                message_put(message);
 
                relation = relation->next;
                message_put(message);
 
                relation = relation->next;
@@ -413,43 +410,6 @@ void JoinPBX::bridge(void)
        }
 }
 
        }
 }
 
-/*
- * bridging is only possible with two connected endpoints
- */
-void JoinPBX::bridge_data(unsigned int epoint_from, struct join_relation *relation_from, union parameter *param)
-{
-       struct join_relation *relation_to;
-
-       /* if we are alone */
-       if (!j_relation->next)
-               return;
-
-       /* if we are more than two */
-       if (j_relation->next->next)
-               return;
-
-       /* skip if source endpoint has NOT audio mode CONNECT */
-       if (relation_from->channel_state != 1)
-               return;
-
-       /* get destination relation */
-       relation_to = j_relation;
-       if (relation_to == relation_from) {
-               /* oops, we are the first, so destination is: */
-               relation_to = relation_to->next;
-       }
-
-       /* skip if destination endpoint has NOT audio mode CONNECT */
-       if (relation_to->channel_state != 1)
-               return;
-
-       /* now we may send our data to the endpoint where it
-        * will be delivered to the port
-        */
-//printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
-       message_forward(j_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param);
-}
-
 /* release join from endpoint
  * if the join has two relations, all relations are freed and the join will be
  * destroyed
 /* release join from endpoint
  * if the join has two relations, all relations are freed and the join will be
  * destroyed
@@ -651,7 +611,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
 //             joinpbx_debug(join,"Join::message_epoint");
 //     }
        if (options.deb & DEBUG_JOIN) {
 //             joinpbx_debug(join,"Join::message_epoint");
 //     }
        if (options.deb & DEBUG_JOIN) {
-               if (message_type != MESSAGE_DATA) {
+               if (message_type) {
                        cl = join_first;
                        while(cl) {
                                if (cl->j_type == JOIN_TYPE_PBX)
                        cl = join_first;
                        while(cl) {
                                if (cl->j_type == JOIN_TYPE_PBX)
@@ -772,12 +732,6 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
                }
                return;
 
                }
                return;
 
-               /* audio data */
-               case MESSAGE_DATA:
-               /* 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 */
                /* relations sends a connect */
                case MESSAGE_CONNECT:
                /* outgoing setup type becomes connected */
index 7c05eee..bf42c9a 100644 (file)
--- a/joinpbx.h
+++ b/joinpbx.h
@@ -66,7 +66,6 @@ class JoinPBX : public Join
        int j_partyline_jingle;         /* also play jingle on join/leave */
 
        void bridge(void);
        int j_partyline_jingle;         /* also play jingle on join/leave */
 
        void bridge(void);
-       void bridge_data(unsigned int epoint_from, struct join_relation *relation_from, union parameter *param);
        void remove_relation(struct join_relation *relation);
        struct join_relation *add_relation(void);
        int out_setup(unsigned int epoint_id, int message, union parameter *param, char *newnumber, char *newkeypad);
        void remove_relation(struct join_relation *relation);
        struct join_relation *add_relation(void);
        int out_setup(unsigned int epoint_id, int message, union parameter *param, char *newnumber, char *newkeypad);
index d683bcd..002f83f 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -141,7 +141,6 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti
        p_m_echo = 0;
        p_m_tone = 0;
        p_m_rxoff = 0;
        p_m_echo = 0;
        p_m_tone = 0;
        p_m_rxoff = 0;
-       p_m_joindata = 0;
        p_m_inband_send_on = 0;
        p_m_inband_receive_on = 0;
        p_m_dtmf = !mISDNport->ifport->nodtmf;
        p_m_inband_send_on = 0;
        p_m_inband_receive_on = 0;
        p_m_dtmf = !mISDNport->ifport->nodtmf;
@@ -1338,7 +1337,7 @@ void PmISDN::load_tx(void)
        }
 
        if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on || p_m_load) {
        }
 
        if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on || p_m_load) {
-               schedule_timer(&p_m_loadtimer, 0, ISDN_TRANSMIT*125);
+               schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
        }
 }
 
        }
 }
 
@@ -1364,8 +1363,6 @@ static int mISDN_timeout(struct lcr_timer *timer, void *instance, int i)
 void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
 {
        unsigned int cont = *((unsigned int *)data);
 void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
 {
        unsigned int cont = *((unsigned int *)data);
-       unsigned char *data_temp;
-       unsigned int length_temp;
        struct lcr_msg *message;
        unsigned char *p;
        int l;
        struct lcr_msg *message;
        unsigned char *p;
        int l;
@@ -1488,23 +1485,8 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
                cryptman_listen_bch(data, len);
        }
 
                cryptman_listen_bch(data, len);
        }
 
-       p = data;
-
-       /* send data to epoint */
-       if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) { /* only if we have an epoint object */
-               length_temp = len;
-               data_temp = p;
-               while(length_temp) {
-                       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
-                       message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
-                       memcpy(message->param.data.data, data_temp, message->param.data.len);
-                       message_put(message);
-                       if (length_temp <= sizeof(message->param.data.data))
-                               break;
-                       data_temp += sizeof(message->param.data.data);
-                       length_temp -= sizeof(message->param.data.data);
-               }
-       }
+       /* send to remote, if bridged */
+       bridge_tx(data, len);
 }
 
 
 }
 
 
@@ -1672,15 +1654,6 @@ void PmISDN::message_mISDNsignal(unsigned int epoint_id, int message_id, union p
                set_conf(oldconf, newconf);
                break;
 
                set_conf(oldconf, newconf);
                break;
 
-               case mISDNSIGNAL_JOINDATA:
-               if (p_m_joindata != param->mISDNsignal.joindata) {
-                       p_m_joindata = param->mISDNsignal.joindata;
-                       PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
-                       update_rxoff();
-               } else
-                       PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
-               break;
-               
                case mISDNSIGNAL_DELAY:
                if (p_m_delay != param->mISDNsignal.delay) {
                        p_m_delay = param->mISDNsignal.delay;
                case mISDNSIGNAL_DELAY:
                if (p_m_delay != param->mISDNsignal.delay) {
                        p_m_delay = param->mISDNsignal.delay;
@@ -1767,32 +1740,31 @@ void PmISDN::message_crypt(unsigned int epoint_id, int message_id, union paramet
  */
 int PmISDN::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
 {
  */
 int PmISDN::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
 {
-       if (Port::message_epoint(epoint_id, message_id, param))
-               return(1);
+       if (Port::message_epoint(epoint_id, message_id, param)) {
+               if (message_id == MESSAGE_BRIDGE)
+                       update_rxoff();
+               return 1;
+       }
 
        switch(message_id) {
 
        switch(message_id) {
-               case MESSAGE_DATA: /* tx-data from upper layer */
-               txfromup(param->data.data, param->data.len);
-               return(1);
-
                case MESSAGE_mISDNSIGNAL: /* user command */
                PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
                message_mISDNsignal(epoint_id, message_id, param);
                case MESSAGE_mISDNSIGNAL: /* user command */
                PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
                message_mISDNsignal(epoint_id, message_id, param);
-               return(1);
+               return 1;
 
                case MESSAGE_CRYPT: /* crypt control command */
                PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
                message_crypt(epoint_id, message_id, param);
 
                case MESSAGE_CRYPT: /* crypt control command */
                PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
                message_crypt(epoint_id, message_id, param);
-               return(1);
+               return 1;
        }
 
        }
 
-       return(0);
+       return 0;
 }
 
 void PmISDN::update_rxoff(void)
 {
        /* call bridges in user space OR crypto OR recording */
 }
 
 void PmISDN::update_rxoff(void)
 {
        /* call bridges in user space OR crypto OR recording */
-       if (p_m_joindata || p_m_crypt_msg_loops || p_m_crypt_listen || p_record || p_m_inband_receive_on) {
+       if (p_bridge || p_m_crypt_msg_loops || p_m_crypt_listen || p_record || p_m_inband_receive_on) {
                /* rx IS required */
                if (p_m_rxoff) {
                        /* turn on RX */
                /* rx IS required */
                if (p_m_rxoff) {
                        /* turn on RX */
@@ -2556,22 +2528,22 @@ void mISDNport_close(struct mISDNport *mISDNport)
 /*
  * enque data from upper buffer
  */
 /*
  * enque data from upper buffer
  */
-void PmISDN::txfromup(unsigned char *data, int length)
+int PmISDN::bridge_rx(unsigned char *data, int length)
 {
        unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
        struct mISDNhead *hh = (struct mISDNhead *)buf;
        int ret;
 
        if (p_m_b_index < 0)
 {
        unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
        struct mISDNhead *hh = (struct mISDNhead *)buf;
        int ret;
 
        if (p_m_b_index < 0)
-               return;
+               return -EIO;
        if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE)
        if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE)
-               return;
+               return -EINVAL;
 
        /* check if high priority tones exist
         * ignore data in this case
         */
        if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on)
 
        /* check if high priority tones exist
         * ignore data in this case
         */
        if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on)
-               return;
+               return -EBUSY;
 
        /* preload procedure
         * if transmit buffer in DSP module is empty,
 
        /* preload procedure
         * if transmit buffer in DSP module is empty,
@@ -2585,14 +2557,14 @@ void PmISDN::txfromup(unsigned char *data, int length)
                if (ret <= 0)
                        PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
                p_m_load += ISDN_LOAD;
                if (ret <= 0)
                        PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
                p_m_load += ISDN_LOAD;
-               schedule_timer(&p_m_loadtimer, 0, ISDN_TRANSMIT*125);
+               schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
        }
 
        /* drop if load would exceed ISDN_MAXLOAD
         * this keeps the delay not too high
         */
        if (p_m_load+length > ISDN_MAXLOAD)
        }
 
        /* drop if load would exceed ISDN_MAXLOAD
         * this keeps the delay not too high
         */
        if (p_m_load+length > ISDN_MAXLOAD)
-               return;
+               return -EINVAL;
 
        /* make and send frame */
        hh->prim = PH_DATA_REQ;
 
        /* make and send frame */
        hh->prim = PH_DATA_REQ;
@@ -2602,6 +2574,8 @@ void PmISDN::txfromup(unsigned char *data, int length)
        if (ret <= 0)
                PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
        p_m_load += length;
        if (ret <= 0)
                PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
        p_m_load += length;
+
+       return 0;
 }
 
 int PmISDN::inband_send(unsigned char *buffer, int len)
 }
 
 int PmISDN::inband_send(unsigned char *buffer, int len)
diff --git a/mISDN.h b/mISDN.h
index 859b073..c310023 100644 (file)
--- a/mISDN.h
+++ b/mISDN.h
@@ -132,10 +132,10 @@ class PmISDN : public Port
        int p_m_mute;                           /* if set, conf is disconnected */
        int p_m_tone;                           /* current kernel space tone */
        int p_m_rxoff;                          /* rx from driver is disabled */
        int p_m_mute;                           /* if set, conf is disconnected */
        int p_m_tone;                           /* current kernel space tone */
        int p_m_rxoff;                          /* rx from driver is disabled */
-//     int p_m_nodata;                         /* all parties within a conf are isdn ports, so pure bridging is possible */
        int p_m_txdata;                         /* get what we transmit */
        int p_m_dtmf;                           /* dtmf decoding is enabled */
        int p_m_txdata;                         /* get what we transmit */
        int p_m_dtmf;                           /* dtmf decoding is enabled */
-       int p_m_joindata;                       /* the call requires data due to no briging capability */
+
+       int bridge_rx(unsigned char *data, int len);
 
        struct lcr_timer p_m_loadtimer;         /* timer for audio transmission */
        virtual void update_load(void);
 
        struct lcr_timer p_m_loadtimer;         /* timer for audio transmission */
        virtual void update_load(void);
@@ -143,10 +143,6 @@ class PmISDN : public Port
        int p_m_load;                           /* current data in dsp tx buffer */
        unsigned int p_m_last_tv_sec;           /* time stamp of last tx_load call, (to sync audio data */
        unsigned int p_m_last_tv_msec;
        int p_m_load;                           /* current data in dsp tx buffer */
        unsigned int p_m_last_tv_sec;           /* time stamp of last tx_load call, (to sync audio data */
        unsigned int 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 */
        int p_m_crypt_msg_loops;                /* sending a message */
 
        int p_m_crypt;                          /* encryption is enabled */
        int p_m_crypt_msg_loops;                /* sending a message */
@@ -171,8 +167,6 @@ 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 */
        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 */
        int p_m_b_mode;                         /* bchannel mode */
        int p_m_hold;                           /* if port is on hold */
        struct lcr_timer p_m_timeout;           /* timeout of timers */
        int p_m_b_mode;                         /* bchannel mode */
        int p_m_hold;                           /* if port is on hold */
        struct lcr_timer p_m_timeout;           /* timeout of timers */
diff --git a/macro.h b/macro.h
index d97c41f..5d2bce5 100644 (file)
--- a/macro.h
+++ b/macro.h
@@ -63,9 +63,9 @@ static inline void sprint(char *dst, unsigned int siz, const char *fmt, ...)
 #define UNPRINT snprintf
 #define VUNPRINT vsnprintf
 
 #define UNPRINT snprintf
 #define VUNPRINT vsnprintf
 
+#define FATAL(fmt, arg...) _fatal(__FILE__, __FUNCTION__, __LINE__, fmt, ##arg)
 /* fatal error with error message and exit */
 /* fatal error with error message and exit */
-#define FATAL(fmt, arg...) fatal(__FUNCTION__, __LINE__, fmt, ##arg)
-static inline void fatal(const char *function, int line, const char *fmt, ...)
+static inline void _fatal(const char *file, const char *function, int line, const char *fmt, ...)
 {
        va_list args;
        char buffer[256];
 {
        va_list args;
        char buffer[256];
@@ -74,23 +74,23 @@ static inline void fatal(const char *function, int line, const char *fmt, ...)
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        va_end(args);
        buffer[sizeof(buffer)-1] = '\0';
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        va_end(args);
        buffer[sizeof(buffer)-1] = '\0';
-       fprintf(stderr, "FATAL ERROR in function %s, line %d: %s", function, line, buffer);
+       fprintf(stderr, "FATAL ERROR in function %s/%s, line %d: %s", file, function, line, buffer);
        fprintf(stderr, "This error is not recoverable, must exit here.\n");
 #ifdef DEBUG_FUNC
        fprintf(stderr, "This error is not recoverable, must exit here.\n");
 #ifdef DEBUG_FUNC
-       debug(function, line, "FATAL", buffer);
-       debug(function, line, "FATAL", (char *)"This error is not recoverable, must exit here.\n");
+       debug(file, function, line, "FATAL", buffer);
+       debug(file, function, line, "FATAL", (char *)"This error is not recoverable, must exit here.\n");
 #endif
        exit(EXIT_FAILURE);
 }
 
 /* memory allocation with setting to zero */
 #endif
        exit(EXIT_FAILURE);
 }
 
 /* memory allocation with setting to zero */
-#define MALLOC(size) _malloc(size, __FUNCTION__, __LINE__)
-static inline void *_malloc(unsigned int size, const char *function, int line)
+#define MALLOC(size) _malloc(size, __FILE__, __FUNCTION__, __LINE__)
+static inline void *_malloc(unsigned int size, const char *file, const char *function, int line)
 {
        void *addr;
        addr = malloc(size);
        if (!addr)
 {
        void *addr;
        addr = malloc(size);
        if (!addr)
-               fatal(function, line, "No memory for %d bytes.\n", size);
+               _fatal(file, function, line, "No memory for %d bytes.\n", size);
        memset(addr, 0, size);
        return addr;
 }
        memset(addr, 0, size);
        return addr;
 }
diff --git a/main.c b/main.c
index 07cfb8f..1f5872a 100644 (file)
--- a/main.c
+++ b/main.c
@@ -53,7 +53,7 @@ int last_debug = 0;
 int debug_newline = 1;
 int nooutput = 0;
 
 int debug_newline = 1;
 int nooutput = 0;
 
-void debug(const char *function, int line, const char *prefix, char *buffer)
+void debug(const char *file, const char *function, int line, const char *prefix, char *buffer)
 {
        time_t now;
        struct tm *now_tm;
 {
        time_t now;
        struct tm *now_tm;
@@ -73,7 +73,7 @@ void debug(const char *function, int line, const char *prefix, char *buffer)
                if (debug_newline)
                        printf("\033[32m%06d %s\033[37m%s", debug_count%1000000, prefix?prefix:"", prefix?" ":"");
                if (function)
                if (debug_newline)
                        printf("\033[32m%06d %s\033[37m%s", debug_count%1000000, prefix?prefix:"", prefix?" ":"");
                if (function)
-                       printf("(in %s() line %d): %s", function, line, buffer);
+                       printf("(in %s/%s() line %d): %s", file, function, line, buffer);
                else
                        printf("%s", buffer);
        }
                else
                        printf("%s", buffer);
        }
@@ -95,7 +95,7 @@ void debug(const char *function, int line, const char *prefix, char *buffer)
 }
 
 
 }
 
 
-void _printdebug(const char *function, int line, unsigned int mask, const char *fmt, ...)
+void _printdebug(const char *file, const char *function, int line, unsigned int mask, const char *fmt, ...)
 {
        char buffer[4096];
        va_list args;
 {
        char buffer[4096];
        va_list args;
@@ -109,12 +109,12 @@ void _printdebug(const char *function, int line, unsigned int mask, const char *
        buffer[sizeof(buffer)-1]=0;
        va_end(args);
 
        buffer[sizeof(buffer)-1]=0;
        va_end(args);
 
-       debug(function, line, "DEBUG", buffer);
+       debug(file, function, line, "DEBUG", buffer);
 
        pthread_mutex_unlock(&mutexd);
 }
 
 
        pthread_mutex_unlock(&mutexd);
 }
 
-void _printerror(const char *function, int line, const char *fmt, ...)
+void _printerror(const char *file, const char *function, int line, const char *fmt, ...)
 {
        char buffer[4096];
        va_list args;
 {
        char buffer[4096];
        va_list args;
@@ -127,7 +127,7 @@ void _printerror(const char *function, int line, const char *fmt, ...)
        va_end(args);
 
        if (options.deb)
        va_end(args);
 
        if (options.deb)
-               debug(function, line, "ERROR", buffer);
+               debug(file, function, line, "ERROR", buffer);
        else { /* only if we do not debug */
                if (function)
                        fprintf(stderr, "ERROR (in %s() line %d) %s", function, line, buffer);
        else { /* only if we do not debug */
                if (function)
                        fprintf(stderr, "ERROR (in %s() line %d) %s", function, line, buffer);
@@ -182,7 +182,7 @@ int main(int argc, char *argv[])
        struct sched_param      schedp;
        int                     created_mutexd = 0,/* created_mutext = 0,*/ created_mutexe = 0,
                                created_lock = 0, created_signal = 0, created_debug = 0,
        struct sched_param      schedp;
        int                     created_mutexd = 0,/* created_mutext = 0,*/ created_mutexe = 0,
                                created_lock = 0, created_signal = 0, created_debug = 0,
-                               created_misdn = 0;
+                               created_misdn = 0, created_message = 0;
        char                    tracetext[256], lock[128];
        char                    options_error[256];
        int                     polling = 0;
        char                    tracetext[256], lock[128];
        char                    options_error[256];
        int                     polling = 0;
@@ -457,6 +457,7 @@ init is done when interface is up
 
        /* init message */
        init_message();
 
        /* init message */
        init_message();
+       created_message = 1;
 
        /*** main loop ***/
        SPRINT(tracetext, "%s %s started, waiting for calls...", NAME, VERSION_STRING);
 
        /*** main loop ***/
        SPRINT(tracetext, "%s %s started, waiting for calls...", NAME, VERSION_STRING);
@@ -506,9 +507,6 @@ init is done when interface is up
        end_trace();
        ret=0;
 
        end_trace();
        ret=0;
 
-       /* clean messacleane */
-       cleanup_message();
-
        /* free all */
 free:
 
        /* free all */
 free:
 
@@ -528,7 +526,6 @@ free:
        }
 
        /* destroy objects */
        }
 
        /* destroy objects */
-
        while(port_first) {
                debug_count++;
                delete port_first;
        while(port_first) {
                debug_count++;
                delete port_first;
@@ -560,6 +557,10 @@ free:
                PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
        }
 
                PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
        }
 
+       /* clean messages */
+       if (created_message)
+               cleanup_message();
+
        /* free tones */
        if (toneset_first)
                free_tones();
        /* free tones */
        if (toneset_first)
                free_tones();
diff --git a/main.h b/main.h
index a0295b5..9a97f3a 100644 (file)
--- a/main.h
+++ b/main.h
@@ -51,14 +51,14 @@ extern int fhuse;
 
 extern FILE *debug_fp;
 
 
 extern FILE *debug_fp;
 
-#define PDEBUG(mask, fmt, arg...) _printdebug(__FUNCTION__, __LINE__, mask, fmt, ## arg)
-#define PERROR(fmt, arg...) _printerror(__FUNCTION__, __LINE__, fmt, ## arg)
-#define PDEBUG_RUNTIME(mask, fmt, arg...) _printdebug(NULL, 0, mask, fmt, ## arg)
-#define PERROR_RUNTIME(fmt, arg...) _printerror(NULL, 0, fmt, ## arg)
-void _printdebug(const char *function, int line, unsigned int mask, const char *fmt, ...);
-void _printerror(const char *function, int line, const char *fmt, ...);
+#define PDEBUG(mask, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, mask, fmt, ## arg)
+#define PERROR(fmt, arg...) _printerror(__FILE__, __FUNCTION__, __LINE__, fmt, ## arg)
+#define PDEBUG_RUNTIME(mask, fmt, arg...) _printdebug(NULL, NULL, 0, mask, fmt, ## arg)
+#define PERROR_RUNTIME(fmt, arg...) _printerror(NULL, NULL, 0, fmt, ## arg)
+void _printdebug(const char *file, const char *function, int line, unsigned int mask, const char *fmt, ...);
+void _printerror(const char *file, const char *function, int line, const char *fmt, ...);
 #define DEBUG_FUNC
 #define DEBUG_FUNC
-void debug(const char *function, int line, const char *prefix, char *buffer);
+void debug(const char *file, const char *function, int line, const char *prefix, char *buffer);
 
 #define DEBUG_CONFIG   0x0001
 #define DEBUG_MSG      0x0002
 
 #define DEBUG_CONFIG   0x0001
 #define DEBUG_MSG      0x0002
index e2f01ec..1e4d37d 100644 (file)
--- a/message.c
+++ b/message.c
@@ -49,7 +49,7 @@ struct lcr_msg *message_create(int id_from, int id_to, int flow, int type)
 }
 
 /* attaches a message to the end of the message chain */
 }
 
 /* attaches a message to the end of the message chain */
-void message_put(struct lcr_msg *message)
+void _message_put(struct lcr_msg *message, const char *file, int line)
 {
        if (message->id_to == 0) {
                PDEBUG(DEBUG_MSG, "message %s not written, because destination is 0.\n", messages_txt[message->type]);
 {
        if (message->id_to == 0) {
                PDEBUG(DEBUG_MSG, "message %s not written, because destination is 0.\n", messages_txt[message->type]);
@@ -57,8 +57,8 @@ void message_put(struct lcr_msg *message)
                return;
        }
        
                return;
        }
        
-       if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA)
-               PDEBUG(DEBUG_MSG, "message %s written from %ld to %ld (memory %x)\n", messages_txt[message->type], message->id_from, message->id_to, message);
+       if ((options.deb & DEBUG_MSG))
+               PDEBUG(DEBUG_MSG, "message %s written from %ld to %ld (memory %x at file %s, line %d)\n", messages_txt[message->type], message->id_from, message->id_to, message, file, line);
 
        *messagepointer_end = message;
        messagepointer_end = &(message->next);
 
        *messagepointer_end = message;
        messagepointer_end = &(message->next);
@@ -102,8 +102,7 @@ struct lcr_msg *message_get(void)
 
        message->keep = 0;
 
 
        message->keep = 0;
 
-       if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA)
-
+       if ((options.deb & DEBUG_MSG))
                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);
                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);
index c2076af..4cfc5b1 100644 (file)
--- a/message.h
+++ b/message.h
@@ -122,7 +122,6 @@ enum { /* diversion types */
 enum { /* isdnsignal */
        mISDNSIGNAL_VOLUME,             /* change volume */
        mISDNSIGNAL_CONF,               /* joint/split conference */
 enum { /* isdnsignal */
        mISDNSIGNAL_VOLUME,             /* change volume */
        mISDNSIGNAL_CONF,               /* joint/split conference */
-       mISDNSIGNAL_JOINDATA,           /* data required by join instance */
        mISDNSIGNAL_ECHO,               /* enable/disable echoe */
        mISDNSIGNAL_DELAY,              /* use delay or adaptive jitter */
 };
        mISDNSIGNAL_ECHO,               /* enable/disable echoe */
        mISDNSIGNAL_DELAY,              /* use delay or adaptive jitter */
 };
@@ -277,13 +276,6 @@ struct park_info {
        int len;
 };
 
        int len;
 };
 
-#define ISDN_TRANSMIT 256
-/* DATA */
-struct param_data {
-       unsigned char data[ISDN_TRANSMIT]; /* audio data */
-       int len; /* audio data */
-};
-
 struct param_play {
        char file[512]; /* file name */
        int offset; /* offset to start file at (in seconds) */
 struct param_play {
        char file[512]; /* file name */
        int offset; /* offset to start file at (in seconds) */
@@ -304,7 +296,6 @@ struct param_mISDNsignal {
        int tx_gain;
        int rx_gain;
        int conf;
        int tx_gain;
        int rx_gain;
        int conf;
-       int joindata;
        int tone;
        int echo;
        int delay;
        int tone;
        int echo;
        int delay;
@@ -352,7 +343,6 @@ union parameter {
        int state; /* MESSAGE_TIMEOUT */
        int knock; /* MESSAGE_KNOCK 0=off !0=on */
        int audiopath; /* MESSAGE_audiopath see RELATION_CHANNEL_* (join.h) */
        int state; /* MESSAGE_TIMEOUT */
        int knock; /* MESSAGE_KNOCK 0=off !0=on */
        int audiopath; /* MESSAGE_audiopath see RELATION_CHANNEL_* (join.h) */
-       struct param_data data; /* MESSAGE_DATA */
        struct param_play play; /* MESSAGE_VBOX_PLAY */
        int speed; /* MESSAGE_VBOX_PLAY_SPEED */
        struct param_counter counter; /* MESSAGE_TONE_COUNTER */
        struct param_play play; /* MESSAGE_VBOX_PLAY */
        int speed; /* MESSAGE_VBOX_PLAY_SPEED */
        struct param_counter counter; /* MESSAGE_TONE_COUNTER */
@@ -362,6 +352,7 @@ union parameter {
        struct param_hello hello; /* MESSAGE_HELLO */
        struct param_bchannel bchannel; /* MESSAGE_BCHANNEL */
        struct param_newref newref; /* MESSAGE_NEWREF */
        struct param_hello hello; /* MESSAGE_HELLO */
        struct param_bchannel bchannel; /* MESSAGE_BCHANNEL */
        struct param_newref newref; /* MESSAGE_NEWREF */
+       unsigned int bridge_id; /* MESSAGE_BRIDGE */
 };
 
 enum { /* message flow */
 };
 
 enum { /* message flow */
@@ -403,11 +394,9 @@ enum { /* messages between entities */
        MESSAGE_SUSPEND,        /* suspend port */
        MESSAGE_RESUME,         /* resume port */
        MESSAGE_AUDIOPATH,      /* set status of audio path to endpoint (to call, audio is also set) */
        MESSAGE_SUSPEND,        /* suspend port */
        MESSAGE_RESUME,         /* resume port */
        MESSAGE_AUDIOPATH,      /* set status of audio path to endpoint (to call, audio is also set) */
-//     MESSAGE_REMOTE_AUDIO,   /* tell remote to set audio status */
        MESSAGE_PATTERN,        /* pattern information tones available */
        MESSAGE_NOPATTERN,      /* pattern information tones unavailable */
        MESSAGE_CRYPT,          /* encryption message */
        MESSAGE_PATTERN,        /* pattern information tones available */
        MESSAGE_NOPATTERN,      /* pattern information tones unavailable */
        MESSAGE_CRYPT,          /* encryption message */
-       MESSAGE_DATA,           /* audio/hdlc data */
        MESSAGE_VBOX_PLAY,      /* play recorded file */
        MESSAGE_VBOX_PLAY_SPEED,/* change speed of file */
        MESSAGE_VBOX_TONE,      /* set answering VBOX tone */
        MESSAGE_VBOX_PLAY,      /* play recorded file */
        MESSAGE_VBOX_PLAY_SPEED,/* change speed of file */
        MESSAGE_VBOX_TONE,      /* set answering VBOX tone */
@@ -416,6 +405,7 @@ enum { /* messages between entities */
        MESSAGE_BCHANNEL,       /* request/assign/remove bchannel */
        MESSAGE_HELLO,          /* hello message for remote application */
        MESSAGE_NEWREF,         /* special message to create and inform ref */
        MESSAGE_BCHANNEL,       /* request/assign/remove bchannel */
        MESSAGE_HELLO,          /* hello message for remote application */
        MESSAGE_NEWREF,         /* special message to create and inform ref */
+       MESSAGE_BRIDGE,         /* control port bridge */
 };
 
 #define MESSAGES static const char *messages_txt[] = { \
 };
 
 #define MESSAGES static const char *messages_txt[] = { \
@@ -439,11 +429,9 @@ enum { /* messages between entities */
        "MESSAGE_SUSPEND", \
        "MESSAGE_RESUME", \
        "MESSAGE_AUDIOPATH", \
        "MESSAGE_SUSPEND", \
        "MESSAGE_RESUME", \
        "MESSAGE_AUDIOPATH", \
-/*     "MESSAGE_REMOTE_AUDIO",*/ \
        "MESSAGE_PATTERN", \
        "MESSAGE_NOPATTERN", \
        "MESSAGE_CRYPT", \
        "MESSAGE_PATTERN", \
        "MESSAGE_NOPATTERN", \
        "MESSAGE_CRYPT", \
-       "MESSAGE_DATA", \
        "MESSAGE_VBOX_PLAY", \
        "MESSAGE_VBOX_PLAY_SPEED", \
        "MESSAGE_VBOX_TONE", \
        "MESSAGE_VBOX_PLAY", \
        "MESSAGE_VBOX_PLAY_SPEED", \
        "MESSAGE_VBOX_TONE", \
@@ -452,11 +440,13 @@ enum { /* messages between entities */
        "MESSAGE_BCHANNEL", \
        "MESSAGE_HELLO", \
        "MESSAGE_NEWREF", \
        "MESSAGE_BCHANNEL", \
        "MESSAGE_HELLO", \
        "MESSAGE_NEWREF", \
+       "MESSAGE_BRIDGE", \
 };
 
 
 struct lcr_msg *message_create(int id_from, int id_to, int flow, int type);
 };
 
 
 struct lcr_msg *message_create(int id_from, int id_to, int flow, int type);
-void message_put(struct lcr_msg *message);
+#define message_put(m) _message_put(m, __FILE__, __LINE__)
+void _message_put(struct lcr_msg *message, const char *file, int line);
 struct lcr_msg *message_forward(int id_from, int id_to, int flow, union parameter *param);
 struct lcr_msg *message_get(void);
 void message_free(struct lcr_msg *message);
 struct lcr_msg *message_forward(int id_from, int id_to, int flow, union parameter *param);
 struct lcr_msg *message_get(void);
 void message_free(struct lcr_msg *message);
index a083fa2..74f8aac 100644 (file)
--- a/port.cpp
+++ b/port.cpp
@@ -54,6 +54,9 @@ class Port *port_first = NULL;
 
 unsigned int port_serial = 1; /* must be 1, because 0== no port */
 
 
 unsigned int port_serial = 1; /* must be 1, because 0== no port */
 
+struct port_bridge *p_bridge_first;
+
+static void remove_bridge(struct port_bridge *bridge, class Port *port);
 
 /* free epointlist relation
  */
 
 /* free epointlist relation
  */
@@ -146,7 +149,7 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
 {
        class Port *temp, **tempp;
 
 {
        class Port *temp, **tempp;
 
-       PDEBUG(DEBUG_PORT, "new port of type %d, name '%s'\n", type, portname);
+       PDEBUG(DEBUG_PORT, "new port of type 0x%x, name '%s'\n", type, portname);
 
        /* initialize object */
        if (settings)
 
        /* initialize object */
        if (settings)
@@ -169,6 +172,7 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
        memset(&p_redirinfo, 0, sizeof(p_redirinfo));
        memset(&p_capainfo, 0, sizeof(p_capainfo));
        p_echotest = 0;
        memset(&p_redirinfo, 0, sizeof(p_redirinfo));
        memset(&p_capainfo, 0, sizeof(p_capainfo));
        p_echotest = 0;
+       p_bridge = 0;
 
        /* call recording */
        p_record = NULL;
 
        /* call recording */
        p_record = NULL;
@@ -202,13 +206,18 @@ Port::~Port(void)
        class Port *temp, **tempp;
        struct lcr_msg *message;
 
        class Port *temp, **tempp;
        struct lcr_msg *message;
 
+       PDEBUG(DEBUG_PORT, "removing port of type 0x%x, name '%s'\n", p_type, p_name);
+
+       if (p_bridge) {
+               PDEBUG(DEBUG_PORT, "Removing us from bridge %u\n", p_bridge->bridge_id);
+               remove_bridge(p_bridge, this);
+       }
+
        if (p_record)
                close_record(0, 0);
 
        classuse--;
 
        if (p_record)
                close_record(0, 0);
 
        classuse--;
 
-       PDEBUG(DEBUG_PORT, "removing port of type %d, name '%s'\n", p_type, p_name);
-
        /* disconnect port from endpoint */
        while(p_epointlist) {
                /* send disconnect */
        /* disconnect port from endpoint */
        while(p_epointlist) {
                /* send disconnect */
@@ -589,38 +598,42 @@ try_loop:
 }
 
 
 }
 
 
-/* endpoint sends messages to the port
- * this is called by the message_epoint inherited by child classes
- * therefor a return=1 means: stop, no more processing
+/* Endpoint sends messages to the port
+ * This is called by the message_epoint, inherited by child classes.
+ * Therefor a return 1 means: "already handled here"
  */
 //extern struct lcr_msg *dddebug;
 int Port::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
 {
        /* check if we got audio data from one remote port */
        switch(message_id) {
  */
 //extern struct lcr_msg *dddebug;
 int Port::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
 {
        /* check if we got audio data from one remote port */
        switch(message_id) {
-               case MESSAGE_TONE: /* play tone */
-               PDEBUG(DEBUG_PORT, "PORT(%s) isdn port with (caller id %s) setting tone '%s' dir '%s'\n", p_name, p_callerinfo.id, param->tone.name, param->tone.dir);
+       case MESSAGE_TONE: /* play tone */
+               PDEBUG(DEBUG_PORT, "PORT(%s) setting tone '%s' dir '%s'\n", p_name, param->tone.name, param->tone.dir);
                set_tone(param->tone.dir,param->tone.name);
                set_tone(param->tone.dir,param->tone.name);
-               return(1);
+               return 1;
 
 
-               case MESSAGE_VBOX_TONE: /* play tone of answering machine */
+       case MESSAGE_VBOX_TONE: /* play tone of answering machine */
                PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine tone '%s' '%s'\n", p_name, param->tone.dir, param->tone.name);
                set_vbox_tone(param->tone.dir, param->tone.name);
                PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine tone '%s' '%s'\n", p_name, param->tone.dir, param->tone.name);
                set_vbox_tone(param->tone.dir, param->tone.name);
-               return(1);
+               return 1;
 
 
-               case MESSAGE_VBOX_PLAY: /* play recording of answering machine */
+       case MESSAGE_VBOX_PLAY: /* play recording of answering machine */
                PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine file to play '%s' (offset %d seconds)\n", p_name, param->play.file, param->play.offset);
                set_vbox_play(param->play.file, param->play.offset);
                PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine file to play '%s' (offset %d seconds)\n", p_name, param->play.file, param->play.offset);
                set_vbox_play(param->play.file, param->play.offset);
-               return(1);
+               return 1;
 
 
-               case MESSAGE_VBOX_PLAY_SPEED: /* set speed of playback (recording of answering machine) */
+       case MESSAGE_VBOX_PLAY_SPEED: /* set speed of playback (recording of answering machine) */
                PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine playback speed %d (times)\n", p_name, param->speed);
                set_vbox_speed(param->speed);
                PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine playback speed %d (times)\n", p_name, param->speed);
                set_vbox_speed(param->speed);
-               return(1);
+               return 1;
 
 
+       case MESSAGE_BRIDGE: /* create / join / leave / destroy bridge */
+               PDEBUG(DEBUG_PORT, "PORT(%s) bridging to id %d\n", p_name, param->bridge_id);
+               bridge(param->bridge_id);
+               return 1;
        }
 
        }
 
-       return(0);
+       return 0;
 }
 
 
 }
 
 
@@ -1154,3 +1167,125 @@ void Port::update_load(void)
 {
 }
 
 {
 }
 
+
+/*
+ * bridge handling
+ */
+
+static void remove_bridge(struct port_bridge *bridge, class Port *port)
+{
+       struct port_bridge **temp = &p_bridge_first;
+       while (*temp) {
+               if (*temp == bridge) {
+                       int remove = 0;
+
+                       /* Remove us from bridge. If bridge is empty, remove it completely. */
+                       if (bridge->sunrise == port) {
+                               bridge->sunrise = NULL;
+                               if (!bridge->sunset)
+                                       remove = 1;
+                       }
+                       if (bridge->sunset == port) {
+                               bridge->sunset = NULL;
+                               if (!bridge->sunrise)
+                                       remove = 1;
+                       }
+                       if (remove) {
+                               PDEBUG(DEBUG_PORT, "Remove bridge %u\n", bridge->bridge_id);
+                               *temp = bridge->next;
+                               FREE(bridge, sizeof(struct port_bridge));
+                               memuse--;
+                       }
+                       return;
+               }
+               temp = &((*temp)->next);
+       }
+       PERROR("Bridge %p not found in list\n", bridge);
+}
+
+void Port::bridge(unsigned int bridge_id)
+{
+       /* Remove bridge, if we leave bridge or if we join a different bridge. */
+       if (p_bridge && bridge_id != p_bridge->bridge_id) {
+               PDEBUG(DEBUG_PORT, "Remove port %u from bridge %u, because out new bridge is %u\n", p_serial, p_bridge->bridge_id, bridge_id);
+               remove_bridge(p_bridge, this);
+               p_bridge = NULL;
+       }
+
+       /* if we leave bridge */
+       if (!bridge_id)
+               return;
+
+       /* find bridge */
+       if (!p_bridge) {
+               struct port_bridge *temp = p_bridge_first;
+
+               while (temp) {
+                       if (temp->bridge_id == bridge_id)
+                               break;
+                       temp = temp->next;
+               }
+               p_bridge = temp;
+               if (p_bridge)
+                       PDEBUG(DEBUG_PORT, "Port %d found existing bridge %u.\n", p_serial, p_bridge->bridge_id);
+       }
+
+       /* create bridge */
+       if (!p_bridge) {
+               struct port_bridge **temp = &p_bridge_first;
+
+               p_bridge = (struct port_bridge *) MALLOC(sizeof(struct port_bridge));
+               memuse++;
+               p_bridge->bridge_id = bridge_id;
+               p_bridge->sunrise = this;
+
+               /* attach bridge instance to list */
+               while (*temp)
+                       temp = &((*temp)->next);
+               *temp = p_bridge;
+               PDEBUG(DEBUG_PORT, "Port %d creating not existing bridge %u.\n", p_serial, p_bridge->bridge_id);
+       }
+
+       /* already joined */
+       if (p_bridge->sunrise == this || p_bridge->sunset == this)
+               return;
+
+       /* join bridge */
+       if (!p_bridge->sunrise) {
+               p_bridge->sunrise = this;
+               return;
+       }
+       if (!p_bridge->sunset) {
+               p_bridge->sunset = this;
+               return;
+       }
+       
+       PERROR("Bridge ID %u cannot be joined by port %u, because it is already occupied by ports %u and %u.\n", p_bridge->bridge_id, p_serial, p_bridge->sunrise->p_serial, p_bridge->sunset->p_serial);
+       p_bridge = NULL;
+}
+
+/* send data to remote Port */
+int Port::bridge_tx(unsigned char *data, int len)
+{
+       class Port *to_port = NULL;
+
+       /* get remote port from bridge */
+       if (!p_bridge)
+               return -EINVAL;
+       if (p_bridge->sunrise == this)
+               to_port = p_bridge->sunset;
+       if (p_bridge->sunset == this)
+               to_port = p_bridge->sunrise;
+       if (!to_port)
+               return -EINVAL;
+
+//     printf("Traffic: %u -> %u (bridge %u)\n", p_serial, to_port->p_serial, p_bridge->bridge_id);
+       return to_port->bridge_rx(data, len);
+}
+
+/* receive data from remote Port (dummy, needs to be inherited) */
+int Port::bridge_rx(unsigned char *data, int len)
+{
+       return 0; /* datenklo */
+}
+
diff --git a/port.h b/port.h
index 0d6a5f9..066ace7 100644 (file)
--- a/port.h
+++ b/port.h
@@ -111,6 +111,8 @@ enum { /* event list from listening to tty */
 #define RECORD_BUFFER_LENGTH   1024 // must be a binary border & must be greater 256, because 256 will be written if buffer overflows
 #define RECORD_BUFFER_MASK     1023
 
 #define RECORD_BUFFER_LENGTH   1024 // must be a binary border & must be greater 256, because 256 will be written if buffer overflows
 #define RECORD_BUFFER_MASK     1023
 
+#define PORT_TRANSMIT          256 // how much to transmit via bridge, if it is not defined by received data length
+
 /* structure of epoint_list */
 struct epoint_list {
        struct epoint_list      *next;
 /* structure of epoint_list */
 struct epoint_list {
        struct epoint_list      *next;
@@ -147,6 +149,16 @@ struct port_settings {
        int no_seconds;
 };
 
        int no_seconds;
 };
 
+/* port bridge instance */
+struct port_bridge {
+       struct port_bridge *next;               /* next bridge node */
+       unsigned int bridge_id;                 /* unique ID to identify bridge */
+       class Port *sunrise;                    /* one side of the bridge */
+       class Port *sunset;                     /* other side of the bridge */
+};
+
+extern struct port_bridge *p_bridge_first;
+
 /* generic port class */
 class Port
 {
 /* generic port class */
 class Port
 {
@@ -189,6 +201,12 @@ class Port
        /* endpoint relation */
        struct epoint_list *p_epointlist;       /* endpoint relation */
 
        /* endpoint relation */
        struct epoint_list *p_epointlist;       /* endpoint relation */
 
+       /* audio bridging */
+       struct port_bridge *p_bridge;           /* linked to a port bridge or NULL */
+       void bridge(unsigned int bridge_id);    /* join a bridge */
+       int bridge_tx(unsigned char *data, int len); /* used to transmit data to remote port */
+       virtual int bridge_rx(unsigned char *data, int len); /* function to be inherited, so data is received */
+
        /* state */
        int p_state;                            /* state of port */
        void new_state(int state);              /* set new state */
        /* state */
        int p_state;                            /* state of port */
        void new_state(int state);              /* set new state */
index 8763739..3ae8a20 100644 (file)
--- a/select.c
+++ b/select.c
@@ -371,10 +371,10 @@ void _del_work(struct lcr_work *work, const char *func)
 #endif
 }
 
 #endif
 }
 
-void trigger_work(struct lcr_work *work)
+void _trigger_work(struct lcr_work *work, const char *func)
 {
        if (!work->inuse) {
 {
        if (!work->inuse) {
-               FATAL("Work not added\n");
+               FATAL("Work not added, (called from func %s)\n", func);
        }
 
        /* event already triggered */
        }
 
        /* event already triggered */
index c4e1418..36d0eeb 100644 (file)
--- a/select.h
+++ b/select.h
@@ -57,6 +57,7 @@ struct lcr_work {
 int _add_work(struct lcr_work *work, int (*cb)(struct lcr_work *work, void *instance, int index), void *instance, int index, const char *func);
 #define del_work(a) _del_work(a, __func__);
 void _del_work(struct lcr_work *work, const char *func);
 int _add_work(struct lcr_work *work, int (*cb)(struct lcr_work *work, void *instance, int index), void *instance, int index, const char *func);
 #define del_work(a) _del_work(a, __func__);
 void _del_work(struct lcr_work *work, const char *func);
-void trigger_work(struct lcr_work *work);
+#define trigger_work(a) _trigger_work(a, __func__);
+void _trigger_work(struct lcr_work *work, const char *func);
 
 
 
 
diff --git a/sip.cpp b/sip.cpp
index adcc057..40c5572 100644 (file)
--- a/sip.cpp
+++ b/sip.cpp
@@ -1078,18 +1078,15 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
        class Endpoint *epoint;
 
        if (PmISDN::message_epoint(epoint_id, message_id, param))
        class Endpoint *epoint;
 
        if (PmISDN::message_epoint(epoint_id, message_id, param))
-               return(1);
+               return 1;
 
        epoint = find_epoint_id(epoint_id);
        if (!epoint) {
                PDEBUG(DEBUG_SIP, "PORT(%s) no endpoint object found where the message is from.\n", p_name);
 
        epoint = find_epoint_id(epoint_id);
        if (!epoint) {
                PDEBUG(DEBUG_SIP, "PORT(%s) no endpoint object found where the message is from.\n", p_name);
-               return(0);
+               return 0;
        }
 
        switch(message_id) {
        }
 
        switch(message_id) {
-               case MESSAGE_DATA:
-               return(1);
-
                case MESSAGE_ALERTING: /* call is ringing on LCR side */
                if (p_state != PORT_STATE_IN_SETUP
                 && p_state != PORT_STATE_IN_PROCEEDING)
                case MESSAGE_ALERTING: /* call is ringing on LCR side */
                if (p_state != PORT_STATE_IN_SETUP
                 && p_state != PORT_STATE_IN_PROCEEDING)
@@ -1099,7 +1096,7 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
                add_trace("respond", "value", "180 Ringing");
                end_trace();
                new_state(PORT_STATE_IN_ALERTING);
                add_trace("respond", "value", "180 Ringing");
                end_trace();
                new_state(PORT_STATE_IN_ALERTING);
-               return(1);
+               return 1;
 
                case MESSAGE_CONNECT: /* call is connected on LCR side */
                if (p_state != PORT_STATE_IN_SETUP
 
                case MESSAGE_CONNECT: /* call is connected on LCR side */
                if (p_state != PORT_STATE_IN_SETUP
@@ -1107,22 +1104,22 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
                 && p_state != PORT_STATE_IN_ALERTING)
                        return 0;
                message_connect(epoint_id, message_id, param);
                 && p_state != PORT_STATE_IN_ALERTING)
                        return 0;
                message_connect(epoint_id, message_id, param);
-               return(1);
+               return 1;
 
                case MESSAGE_DISCONNECT: /* call has been disconnected */
                case MESSAGE_RELEASE: /* call has been released */
                message_release(epoint_id, message_id, param);
 
                case MESSAGE_DISCONNECT: /* call has been disconnected */
                case MESSAGE_RELEASE: /* call has been released */
                message_release(epoint_id, message_id, param);
-               return(1);
+               return 1;
 
                case MESSAGE_SETUP: /* dial-out command received from epoint */
                message_setup(epoint_id, message_id, param);
 
                case MESSAGE_SETUP: /* dial-out command received from epoint */
                message_setup(epoint_id, message_id, param);
-               return(1);
+               return 1;
 
                default:
                PDEBUG(DEBUG_SIP, "PORT(%s) SP port with (caller id %s) received an unsupported message: %d\n", p_name, p_callerinfo.id, message_id);
        }
 
 
                default:
                PDEBUG(DEBUG_SIP, "PORT(%s) SP port with (caller id %s) received an unsupported message: %d\n", p_name, p_callerinfo.id, message_id);
        }
 
-       return(0);
+       return 0;
 }
 
 int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
 }
 
 int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
diff --git a/trace.c b/trace.c
index a810d8c..ffecfbb 100644 (file)
--- a/trace.c
+++ b/trace.c
@@ -274,7 +274,7 @@ void _end_trace(const char *__file, int __line)
                if (string) {
                        /* process debug */
                        if (options.deb)
                if (string) {
                        /* process debug */
                        if (options.deb)
-                               debug(NULL, 0, "TRACE", string);
+                               debug(NULL, NULL, 0, "TRACE", string);
                        /* process log */
                        if (options.log[0]) {
                                fp = fopen(options.log, "a");
                        /* process log */
                        if (options.log[0]) {
                                fp = fopen(options.log, "a");
index 28daf09..c8c3012 100644 (file)
--- a/vbox.cpp
+++ b/vbox.cpp
@@ -103,7 +103,7 @@ void VBoxPort::send_announcement(void)
 {
        struct lcr_msg  *message;
        unsigned int    tosend;
 {
        struct lcr_msg  *message;
        unsigned int    tosend;
-       unsigned char   buffer[ISDN_TRANSMIT];
+       unsigned char   buffer[PORT_TRANSMIT + PORT_TRANSMIT]; /* use twice of the buffer, so we can send more in case of delayed main loop execution */
        class Endpoint  *epoint;
        int             temp;
        struct timeval current_time;
        class Endpoint  *epoint;
        int             temp;
        struct timeval current_time;
@@ -118,7 +118,7 @@ void VBoxPort::send_announcement(void)
 
        /* set time the first time */
        if (!p_vbox_audio_start)
 
        /* set time the first time */
        if (!p_vbox_audio_start)
-               p_vbox_audio_start = now - ISDN_TRANSMIT;
+               p_vbox_audio_start = now - PORT_TRANSMIT;
        
        /* calculate the number of bytes */
        tosend = (unsigned int)(now - p_vbox_audio_start) - p_vbox_audio_transferred;
        
        /* calculate the number of bytes */
        tosend = (unsigned int)(now - p_vbox_audio_start) - p_vbox_audio_transferred;
@@ -126,7 +126,7 @@ void VBoxPort::send_announcement(void)
                tosend = sizeof(buffer);
 
        /* schedule next event */
                tosend = sizeof(buffer);
 
        /* schedule next event */
-       temp = ISDN_TRANSMIT + ISDN_TRANSMIT - tosend;
+       temp = PORT_TRANSMIT + PORT_TRANSMIT - tosend;
        if (temp < 0)
                temp = 0;
        schedule_timer(&p_vbox_announce_timer, 0, temp*125);
        if (temp < 0)
                temp = 0;
        schedule_timer(&p_vbox_announce_timer, 0, temp*125);
@@ -184,13 +184,17 @@ void VBoxPort::send_announcement(void)
        } else {
                if (p_record)
                        record(buffer, tosend, 0); // from down
        } else {
                if (p_record)
                        record(buffer, tosend, 0); // from down
-               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
-               message->param.data.len = tosend;
-               memcpy(message->param.data.data, buffer, tosend);
-               message_put(message);
+               /* send to remote, if bridged */
+               bridge_tx(buffer, tosend);
        }
 }
 
        }
 }
 
+int VBoxPort::bridge_rx(unsigned char *data, int len)
+{
+       if (p_record)
+               record(data, len, 1); // from up
+       return 0;
+}
 
 /*
  * endpoint sends messages to the vbox port
 
 /*
  * endpoint sends messages to the vbox port
@@ -211,10 +215,6 @@ int VBoxPort::message_epoint(unsigned int epoint_id, int message_id, union param
        }
 
        switch(message_id) {
        }
 
        switch(message_id) {
-               case MESSAGE_DATA:
-               record(param->data.data, param->data.len, 1); // from up
-               return(1);
-
                case MESSAGE_DISCONNECT: /* call has been disconnected */
                new_state(PORT_STATE_OUT_DISCONNECT);
                vbox_trace_header(this, "DISCONNECT to VBox", DIRECTION_OUT);
                case MESSAGE_DISCONNECT: /* call has been disconnected */
                new_state(PORT_STATE_OUT_DISCONNECT);
                vbox_trace_header(this, "DISCONNECT to VBox", DIRECTION_OUT);
diff --git a/vbox.h b/vbox.h
index dd9d4aa..69cf83c 100644 (file)
--- a/vbox.h
+++ b/vbox.h
@@ -18,6 +18,8 @@ class VBoxPort : public Port
        int message_epoint(unsigned int epoint_id, int message, union parameter *param);
        void send_announcement(void);
 
        int message_epoint(unsigned int epoint_id, int message, union parameter *param);
        void send_announcement(void);
 
+       int bridge_rx(unsigned char *data, int len);
+
        private:
        struct EndpointAppPBX *p_vbox_apppbx;           /* pbx application */
        unsigned int p_vbox_timeout;                    /* timeout for recording */
        private:
        struct EndpointAppPBX *p_vbox_apppbx;           /* pbx application */
        unsigned int p_vbox_timeout;                    /* timeout for recording */