Cleanup: Make interface name be part of Port class
[lcr.git] / mISDN.cpp
index 3961fd8..cb7576f 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -37,7 +37,9 @@ struct mISDNport *mISDNport_first;
 unsigned char mISDN_rand[256];
 int mISDN_rand_count = 0;
 
 unsigned char mISDN_rand[256];
 int mISDN_rand_count = 0;
 
+#ifdef OLD_MT_ASSIGN
 unsigned int mt_assign_pid = ~0;
 unsigned int mt_assign_pid = ~0;
+#endif
 
 int mISDNsocket = -1;
 static int upqueue_pipe[2];
 
 int mISDNsocket = -1;
 static int upqueue_pipe[2];
@@ -120,7 +122,7 @@ int load_timer(struct lcr_timer *timer, void *instance, int index);
 /*
  * constructor
  */
 /*
  * constructor
  */
-PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Port(type, portname, settings)
+PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, struct interface *interface, int channel, int exclusive, int mode) : Port(type, portname, settings, interface)
 {
        p_m_mISDNport = mISDNport;
        p_m_portnum = mISDNport->portnum;
 {
        p_m_mISDNport = mISDNport;
        p_m_portnum = mISDNport->portnum;
@@ -136,17 +138,17 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti
        p_m_mute = 0;
        p_m_txdata = 0;
        p_m_delay = 0;
        p_m_mute = 0;
        p_m_txdata = 0;
        p_m_delay = 0;
+       p_m_tx_dejitter = 0;
+       p_m_preload = ISDN_LOAD;
+       p_m_disable_dejitter = 0;
        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;
        memset(&p_m_timeout, 0, sizeof(p_m_timeout));
        add_timer(&p_m_timeout, mISDN_timeout, this, 0);
        p_m_inband_send_on = 0;
        p_m_inband_receive_on = 0;
        p_m_dtmf = !mISDNport->ifport->nodtmf;
        memset(&p_m_timeout, 0, sizeof(p_m_timeout));
        add_timer(&p_m_timeout, mISDN_timeout, this, 0);
-       p_m_remote_ref = 0; /* channel shall be exported to given remote */
-       p_m_remote_id = 0; /* remote admin socket */
        SCPY(p_m_pipeline, mISDNport->ifport->interface->pipeline);
        
        /* audio */
        SCPY(p_m_pipeline, mISDNport->ifport->interface->pipeline);
        
        /* audio */
@@ -486,6 +488,8 @@ static void _bchannel_configure(struct mISDNport *mISDNport, int i)
                ph_control(mISDNport, port, handle, (port->p_m_txdata)?DSP_TXDATA_ON:DSP_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
        if (port->p_m_delay && mode == B_MODE_TRANSPARENT)
                ph_control(mISDNport, port, handle, DSP_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
                ph_control(mISDNport, port, handle, (port->p_m_txdata)?DSP_TXDATA_ON:DSP_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
        if (port->p_m_delay && mode == B_MODE_TRANSPARENT)
                ph_control(mISDNport, port, handle, DSP_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
+       if (port->p_m_tx_dejitter && mode == B_MODE_TRANSPARENT)
+               ph_control(mISDNport, port, handle, DSP_TX_DEJITTER, port->p_m_tx_dejitter, "DSP-TX_DEJITTER", port->p_m_tx_dejitter);
        if (port->p_m_tx_gain && mode == B_MODE_TRANSPARENT)
                ph_control(mISDNport, port, handle, DSP_VOL_CHANGE_TX, port->p_m_tx_gain, "DSP-TX_GAIN", port->p_m_tx_gain);
        if (port->p_m_rx_gain && mode == B_MODE_TRANSPARENT)
        if (port->p_m_tx_gain && mode == B_MODE_TRANSPARENT)
                ph_control(mISDNport, port, handle, DSP_VOL_CHANGE_TX, port->p_m_tx_gain, "DSP-TX_GAIN", port->p_m_tx_gain);
        if (port->p_m_rx_gain && mode == B_MODE_TRANSPARENT)
@@ -564,22 +568,6 @@ It may be linked to a Port class, that likes to reactivate it.
 See above.
 After deactivating bchannel, and if not used, the bchannel becomes idle again.
 
 See above.
 After deactivating bchannel, and if not used, the bchannel becomes idle again.
 
-Also the bchannel may be exported, but only if the state is or becomes idle:
-
-- B_STATE_EXPORTING
-The bchannel assignment has been sent to the remove application.
-
-- B_STATE_REMOTE
-The bchannel assignment is acknowledged by the remote application.
-
-- B_STATE_IMPORTING
-The bchannel is re-imported by mISDN port object.
-
-- B_STATE_IDLE
-See above.
-After re-importing bchannel, and if not used, the bchannel becomes idle again.
-
-
 A bchannel can have the following events:
 
 - B_EVENT_USE
 A bchannel can have the following events:
 
 - B_EVENT_USE
@@ -594,33 +582,8 @@ The bchannel is not required by Port class anymore
 - B_EVENT_DEACTIVATED
 The bchannel becomes inactive.
 
 - B_EVENT_DEACTIVATED
 The bchannel becomes inactive.
 
-- B_EVENT_EXPORTED
-The bchannel is now used by remote application.
-
-- B_EVENT_IMPORTED
-The bchannel is not used by remote application.
-
-- B_EVENT_EXPORTREQUEST
-The bchannel shall be exported to the remote application.
-
-- B_EVENT_IMPORTREQUEST
-The bchannel is released from the remote application.
-
 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
 
 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
 
-if an export request is receive by remote application, p_m_remote_* is set.
-the b_remote_*[index] indicates if and where the channel is exported to. (set from the point on, where export is initiated, until imported is acknowledged.)
-- set on export request from remote application (if port is assigned)
-- set on channel use, if requested by remote application (p_m_remote_*)
-- cleared on drop request
-
-the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
-the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
-the bchannel import/export is acknowledged with stack given.
-
-if exporting, b_remote_*[index] is set to the remote socket id.
-if importing has been acknowledged. b_remote_*[index] is cleared.
-
 */
 
 /*
 */
 
 /*
@@ -635,19 +598,14 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
        class PmISDN *b_port = mISDNport->b_port[i];
        int state = mISDNport->b_state[i];
        int timer = -1; // no change
        class PmISDN *b_port = mISDNport->b_port[i];
        int state = mISDNport->b_state[i];
        int timer = -1; // no change
-       unsigned int p_m_remote_ref = 0;
-       unsigned int p_m_remote_id = 0;
        int p_m_tx_gain = 0;
        int p_m_rx_gain = 0;
        char *p_m_pipeline = NULL;
        unsigned char *p_m_crypt_key = NULL;
        int p_m_crypt_key_len = 0;
        int p_m_crypt_key_type = 0;
        int p_m_tx_gain = 0;
        int p_m_rx_gain = 0;
        char *p_m_pipeline = NULL;
        unsigned char *p_m_crypt_key = NULL;
        int p_m_crypt_key_len = 0;
        int p_m_crypt_key_type = 0;
-       unsigned int portid = (mISDNport->portnum<<8) + i+1+(i>=15);
 
        if (b_port) {
 
        if (b_port) {
-               p_m_remote_id = b_port->p_m_remote_id;
-               p_m_remote_ref = b_port->p_m_remote_ref;
                p_m_tx_gain = b_port->p_m_tx_gain;
                p_m_rx_gain = b_port->p_m_rx_gain;
                p_m_pipeline = b_port->p_m_pipeline;
                p_m_tx_gain = b_port->p_m_tx_gain;
                p_m_rx_gain = b_port->p_m_rx_gain;
                p_m_pipeline = b_port->p_m_pipeline;
@@ -663,140 +621,38 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        FATAL("bchannel must be linked to a Port class\n");
                switch(state) {
                        case B_STATE_IDLE:
                        FATAL("bchannel must be linked to a Port class\n");
                switch(state) {
                        case B_STATE_IDLE:
-                       if (p_m_remote_ref) {
-                               /* export bchannel */
-                               message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0);
-                               chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                               add_trace("type", NULL, "assign");
-                               add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                               end_trace();
-                               state = B_STATE_EXPORTING;
-                               mISDNport->b_remote_id[i] = p_m_remote_id;
-                               mISDNport->b_remote_ref[i] = p_m_remote_ref;
-                       } else {
-                               /* create stack and send activation request */
-                               if (_bchannel_create(mISDNport, i)) {
-                                       _bchannel_activate(mISDNport, i, 1, 0);
-                                       state = B_STATE_ACTIVATING;
-                                       timer = B_TIMER_ACTIVATING;
-                               }
+                       /* create stack and send activation request */
+                       if (_bchannel_create(mISDNport, i)) {
+                               _bchannel_activate(mISDNport, i, 1, 0);
+                               state = B_STATE_ACTIVATING;
+                               timer = B_TIMER_ACTIVATING;
                        }
                        break;
 
                        case B_STATE_ACTIVATING:
                        }
                        break;
 
                        case B_STATE_ACTIVATING:
-                       case B_STATE_EXPORTING:
                        /* do nothing, because it is already activating */
                        break;
 
                        /* do nothing, because it is already activating */
                        break;
 
-                       case B_STATE_DEACTIVATING:
-                       case B_STATE_IMPORTING:
-                       /* do nothing, because we must wait until we can reactivate */
-                       break;
-
                        default:
                        /* problems that might ocurr:
                         * B_EVENT_USE is received when channel already in use.
                        default:
                        /* problems that might ocurr:
                         * B_EVENT_USE is received when channel already in use.
-                        * bchannel exported, but not freed by other port
                         */
                        PERROR("Illegal event %d at state %d, please correct.\n", event, state);
                }
                break;
 
                         */
                        PERROR("Illegal event %d at state %d, please correct.\n", event, state);
                }
                break;
 
-               case B_EVENT_EXPORTREQUEST:
-               /* special case where the bchannel is requested by remote */
-               if (!p_m_remote_ref) {
-                       PERROR("export request without remote channel set, please correct.\n");
-                       break;
-               }
-               switch(state) {
-                       case B_STATE_IDLE:
-                       /* in case, the bchannel is exported right after seize_bchannel */
-                       /* export bchannel */
-                       /* p_m_remote_id is set, when this event happens. */
-                       message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0);
-                       chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                       add_trace("type", NULL, "assign");
-                       add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                       end_trace();
-                       state = B_STATE_EXPORTING;
-                       mISDNport->b_remote_id[i] = p_m_remote_id;
-                       mISDNport->b_remote_ref[i] = p_m_remote_ref;
-                       break;
-
-                       case B_STATE_ACTIVATING:
-                       case B_STATE_EXPORTING:
-                       /* do nothing, because it is already activating */
-                       break;
-
-                       case B_STATE_DEACTIVATING:
-                       case B_STATE_IMPORTING:
-                       /* do nothing, because we must wait until we can reactivate */
-                       break;
-
-                       case B_STATE_ACTIVE:
-                       /* bchannel is active, so we deactivate */
-                       _bchannel_activate(mISDNport, i, 0, 0);
-                       state = B_STATE_DEACTIVATING;
-                       timer = B_TIMER_DEACTIVATING;
-                       break;
-
-                       default:
-                       /* problems that might ocurr:
-                        * ... when channel already in use.
-                        * bchannel exported, but not freed by other port
-                        */
-                       PERROR("Illegal event %d at state %d, please correct.\n", event, state);
-               }
-               break;
-
-               case B_EVENT_IMPORTREQUEST:
-               /* special case where the bchannel is released by remote */
-               if (p_m_remote_ref) {
-                       PERROR("import request with remote channel set, please correct.\n");
-                       break;
-               }
-               switch(state) {
-                       case B_STATE_IDLE:
-                       case B_STATE_ACTIVE:
-                       /* bchannel is not exported */
-                       break;
-
-                       case B_STATE_ACTIVATING:
-                       case B_STATE_EXPORTING:
-                       /* do nothing because we must wait until bchanenl is active before deactivating */
-                       break;
-
-                       case B_STATE_REMOTE:
-                       /* bchannel is exported, so we re-import */
-                       message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0, 0);
-                       chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                       add_trace("type", NULL, "remove");
-                       add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                       end_trace();
-                       state = B_STATE_IMPORTING;
-                       break;
-
-                       case B_STATE_DEACTIVATING:
-                       case B_STATE_IMPORTING:
-                       /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
-                       break;
-
-                       default:
-                       PERROR("Illegal event %d at state %d, please correct.\n", event, state);
-               }
-               break;
 
                case B_EVENT_ACTIVATED:
                timer = 0;
                switch(state) {
                        case B_STATE_ACTIVATING:
 
                case B_EVENT_ACTIVATED:
                timer = 0;
                switch(state) {
                        case B_STATE_ACTIVATING:
-                       if (b_port && !p_m_remote_id) {
+                       if (b_port) {
                                /* bchannel is active and used by Port class, so we configure bchannel */
                                _bchannel_configure(mISDNport, i);
                                state = B_STATE_ACTIVE;
                                b_port->p_m_load = 0;
                        } else {
                                /* bchannel is active and used by Port class, so we configure bchannel */
                                _bchannel_configure(mISDNport, i);
                                state = B_STATE_ACTIVE;
                                b_port->p_m_load = 0;
                        } else {
-                               /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
+                               /* bchannel is active, but not used anymore (or has wrong stack config), so we deactivate */
                                _bchannel_activate(mISDNport, i, 0, 0);
                                state = B_STATE_DEACTIVATING;
                                timer = B_TIMER_DEACTIVATING;
                                _bchannel_activate(mISDNport, i, 0, 0);
                                state = B_STATE_DEACTIVATING;
                                timer = B_TIMER_DEACTIVATING;
@@ -808,31 +664,6 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                }
                break;
 
                }
                break;
 
-               case B_EVENT_EXPORTED:
-               switch(state) {
-                       case B_STATE_EXPORTING:
-                       if (b_port && p_m_remote_ref && p_m_remote_ref==mISDNport->b_remote_ref[i]) {
-                               /* remote export done */
-                               state = B_STATE_REMOTE;
-                       } else {
-                               /* bchannel is now exported, but we need bchannel back
-                                * OR bchannel is not used anymore
-                                * OR bchannel has been exported to an obsolete ref,
-                                * so reimport, to later export to new remote */
-                               message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0, 0);
-                               chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                               add_trace("type", NULL, "remove");
-                               add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                               end_trace();
-                               state = B_STATE_IMPORTING;
-                       }
-                       break;
-
-                       default:
-                       PERROR("Illegal event %d at state %d, please correct.\n", event, state);
-               }
-               break;
-
                case B_EVENT_DROP:
                if (!b_port)
                        FATAL("bchannel must be linked to a Port class\n");
                case B_EVENT_DROP:
                if (!b_port)
                        FATAL("bchannel must be linked to a Port class\n");
@@ -842,7 +673,6 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        break;
 
                        case B_STATE_ACTIVATING:
                        break;
 
                        case B_STATE_ACTIVATING:
-                       case B_STATE_EXPORTING:
                        /* do nothing because we must wait until bchanenl is active before deactivating */
                        break;
 
                        /* do nothing because we must wait until bchanenl is active before deactivating */
                        break;
 
@@ -853,18 +683,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        timer = B_TIMER_DEACTIVATING;
                        break;
 
                        timer = B_TIMER_DEACTIVATING;
                        break;
 
-                       case B_STATE_REMOTE:
-                       /* bchannel is exported, so we re-import */
-                       message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0, 0);
-                       chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                       add_trace("type", NULL, "remove");
-                       add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                       end_trace();
-                       state = B_STATE_IMPORTING;
-                       break;
-
                        case B_STATE_DEACTIVATING:
                        case B_STATE_DEACTIVATING:
-                       case B_STATE_IMPORTING:
                        /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
                        break;
 
                        /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
                        break;
 
@@ -884,22 +703,11 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        _bchannel_destroy(mISDNport, i);
                        state = B_STATE_IDLE;
                        if (b_port) {
                        _bchannel_destroy(mISDNport, i);
                        state = B_STATE_IDLE;
                        if (b_port) {
-                               /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
-                               if (p_m_remote_ref) {
-                                       message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0);
-                                       chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                                       add_trace("type", NULL, "assign");
-                                       add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                                       end_trace();
-                                       state = B_STATE_EXPORTING;
-                                       mISDNport->b_remote_id[i] = p_m_remote_id;
-                                       mISDNport->b_remote_ref[i] = p_m_remote_ref;
-                               } else {
-                                       if (_bchannel_create(mISDNport, i)) {
-                                               _bchannel_activate(mISDNport, i, 1, 0);
-                                               state = B_STATE_ACTIVATING;
-                                               timer = B_TIMER_ACTIVATING;
-                                       }
+                               /* bchannel is now deactivate, but is requied by Port class, so we reactivate */
+                               if (_bchannel_create(mISDNport, i)) {
+                                       _bchannel_activate(mISDNport, i, 1, 0);
+                                       state = B_STATE_ACTIVATING;
+                                       timer = B_TIMER_ACTIVATING;
                                }
                        }
                        break;
                                }
                        }
                        break;
@@ -909,39 +717,6 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                }
                break;
 
                }
                break;
 
-               case B_EVENT_IMPORTED:
-               switch(state) {
-                       case B_STATE_IMPORTING:
-                       state = B_STATE_IDLE;
-                       mISDNport->b_remote_id[i] = 0;
-                       mISDNport->b_remote_ref[i] = 0;
-                       if (b_port) {
-                               /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
-                               if (p_m_remote_ref) {
-                                       message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type, 0);
-                                       chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                                       add_trace("type", NULL, "assign");
-                                       add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                                       end_trace();
-                                       state = B_STATE_EXPORTING;
-                                       mISDNport->b_remote_id[i] = p_m_remote_id;
-                                       mISDNport->b_remote_ref[i] = p_m_remote_ref;
-                               } else {
-                                       if (_bchannel_create(mISDNport, i)) {
-                                               _bchannel_activate(mISDNport, i, 1, 0);
-                                               state = B_STATE_ACTIVATING;
-                                               timer = B_TIMER_ACTIVATING;
-                                       }
-                               }
-                       }
-                       break;
-
-                       default:
-                       /* ignore, because not assigned */
-                       ;
-               }
-               break;
-
                case B_EVENT_TIMEOUT:
                timer = 0;
                switch(state) {
                case B_EVENT_TIMEOUT:
                timer = 0;
                switch(state) {
@@ -1080,101 +855,6 @@ void PmISDN::drop_bchannel(void)
        p_m_b_exclusive = 0;
 }
 
        p_m_b_exclusive = 0;
 }
 
-/* process bchannel export/import message from join */
-void message_bchannel_from_remote(class JoinRemote *joinremote, int type, unsigned int handle)
-{
-       class Endpoint *epoint;
-       class Port *port;
-       class PmISDN *isdnport;
-       struct mISDNport *mISDNport;
-       int i, ii;
-
-       switch(type) {
-               case BCHANNEL_REQUEST:
-               /* find the port object for the join object ref */
-               if (!(epoint = find_epoint_id(joinremote->j_epoint_id))) {
-                       PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
-                       return;
-               }
-               if (!epoint->ep_portlist) {
-                       PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
-                       return;
-               }
-               if (epoint->ep_portlist->next) {
-                       PERROR("join %d has enpoint %d with more than one port. this shall not happen to remote joins.\n", joinremote->j_serial, epoint->ep_serial);
-               }
-               if (!(port = find_port_id(epoint->ep_portlist->port_id))) {
-                       PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
-                       return;
-               }
-               if ((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN) {
-                       PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
-               }
-               isdnport = (class PmISDN *)port;
-
-               /* assign */
-               if (isdnport->p_m_remote_id) {
-                       PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
-                       break;
-               }
-               mISDNport = isdnport->p_m_mISDNport;
-               i = isdnport->p_m_b_index;
-               chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
-               add_trace("type", NULL, "export request");
-               end_trace();
-               isdnport->p_m_remote_ref = joinremote->j_remote_ref;
-               isdnport->p_m_remote_id = joinremote->j_remote_id;
-               if (mISDNport && i>=0) {
-                       bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
-               }
-               break;
-
-               case BCHANNEL_RELEASE:
-               case BCHANNEL_ASSIGN_ACK:
-               case BCHANNEL_REMOVE_ACK:
-               /* find mISDNport for stack ID */
-               mISDNport = mISDNport_first;
-               while(mISDNport) {
-                       i = 0;
-                       ii = mISDNport->b_num;
-                       while(i < ii) {
-                               if ((unsigned int)(mISDNport->portnum<<8)+i+1+(i>=15) == handle)
-                                       break;
-                               i++;
-                       }
-                       if (i != ii)
-                               break;
-                       mISDNport = mISDNport->next;
-               }
-               if (!mISDNport) {
-                       PERROR("received assign/remove ack for bchannel's handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
-                       break;
-               }
-               
-               if (type!=BCHANNEL_RELEASE) {
-                       /* ack */
-                       chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
-                       add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
-                       end_trace();
-                       bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
-               } else {
-                       /* release */
-                       isdnport = mISDNport->b_port[i];
-                       chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
-                       add_trace("type", NULL, "import request");
-                       end_trace();
-                       if (isdnport) {
-                               isdnport->p_m_remote_ref = 0;
-                               isdnport->p_m_remote_id = 0;
-                       }
-                       bchannel_event(mISDNport, i, B_EVENT_IMPORTREQUEST);
-               }
-               break;
-               default:
-               PERROR("received wrong bchannel message type %d from remote\n", type);
-       }
-}
-
 
 /*
  * handler
 
 /*
  * handler
@@ -1201,31 +881,31 @@ times have no skew.
 
 * levels
 there are two levels:
 
 * 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.
+p_m_preload will give the load that have to be kept in dsp.
+ISDN_MAXLOAD (2*p_m_preload) 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
 
 * 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
+whenever load is below p_m_preload, load is filled up to p_m_preload
 if no more data is available, load becomes empty again.
 
 'load' variable:
 if no more data is available, load becomes empty again.
 
 'load' variable:
-0                    ISDN_LOAD           ISDN_MAXLOAD
+0                    p_m_preload           ISDN_MAXLOAD
 +--------------------+----------------------+
 |                    |                      |
 +--------------------+----------------------+
 
 +--------------------+----------------------+
 |                    |                      |
 +--------------------+----------------------+
 
-on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
-0                    ISDN_LOAD           ISDN_MAXLOAD
+on empty load or on load below p_m_preload, the load is inceased to p_m_preload:
+0                    p_m_preload           ISDN_MAXLOAD
 +--------------------+----------------------+
 |TTTTTTTTTTTTTTTTTTTT|                      |
 +--------------------+----------------------+
 
 +--------------------+----------------------+
 |TTTTTTTTTTTTTTTTTTTT|                      |
 +--------------------+----------------------+
 
-on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
-0                    ISDN_LOAD           ISDN_MAXLOAD
+on empty load, remote-audio causes the load with the remote audio to be increased to p_m_preload.
+0                    p_m_preload           ISDN_MAXLOAD
 +--------------------+----------------------+
 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
 +--------------------+----------------------+
 +--------------------+----------------------+
 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
 +--------------------+----------------------+
@@ -1234,7 +914,7 @@ on empty load, remote-audio causes the load with the remote audio to be increase
 void PmISDN::update_load(void)
 {
        /* don't trigger load event if: */
 void PmISDN::update_load(void)
 {
        /* don't trigger load event if: */
-       if (!p_tone_name[0] && !p_m_crypt_msg_loops && !p_m_inband_send_on)
+       if (!p_tone_name[0] && !p_m_crypt_msg_loops && !p_m_inband_send_on && !(p_bridge && p_m_disable_dejitter && p_m_preload > 0))
                return;
 
        /* don't trigger load event if event already active */
                return;
 
        /* don't trigger load event if event already active */
@@ -1279,9 +959,9 @@ void PmISDN::load_tx(void)
 
                /* to send data, tone must be on */
                if ((p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on) /* what tones? */
 
                /* to send data, tone must be on */
                if ((p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on) /* what tones? */
-                && (p_m_load < ISDN_LOAD) /* not too much load? */
+                && (p_m_load < p_m_preload) /* not too much load? */
                 && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones || p_m_inband_send_on)) { /* connected or inband-tones? */
                 && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones || p_m_inband_send_on)) { /* connected or inband-tones? */
-                       int tosend = ISDN_LOAD - p_m_load, length; 
+                       int tosend = p_m_preload - p_m_load, length; 
                        unsigned char buf[MISDN_HEADER_LEN+tosend];
                        struct mISDNhead *frm = (struct mISDNhead *)buf;
                        unsigned char *p = buf+MISDN_HEADER_LEN;
                        unsigned char buf[MISDN_HEADER_LEN+tosend];
                        struct mISDNhead *frm = (struct mISDNhead *)buf;
                        unsigned char *p = buf+MISDN_HEADER_LEN;
@@ -1324,19 +1004,19 @@ void PmISDN::load_tx(void)
                        }
 
                        /* send data */
                        }
 
                        /* send data */
-                       if (ISDN_LOAD - p_m_load - tosend > 0) {
+                       if (p_m_preload - p_m_load - tosend > 0) {
                                frm->prim = PH_DATA_REQ;
                                frm->id = 0;
                                frm->prim = PH_DATA_REQ;
                                frm->id = 0;
-                               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
+                               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+p_m_preload-p_m_load-tosend, 0, NULL, 0);
                                if (ret <= 0)
                                if (ret <= 0)
-                                       PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_sock[p_m_b_index].fd, ISDN_LOAD-p_m_load-tosend);
-                               p_m_load += ISDN_LOAD - p_m_load - tosend;
+                                       PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_sock[p_m_b_index].fd, p_m_preload-p_m_load-tosend);
+                               p_m_load += p_m_preload - p_m_load - tosend;
                        }
                }
        }
 
        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);
        }
 }
 
        }
 }
 
@@ -1362,8 +1042,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;
@@ -1448,6 +1126,9 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
        if (p_m_inband_receive_on)
                inband_receive(data, len);
 
        if (p_m_inband_receive_on)
                inband_receive(data, len);
 
+       /* send to remote, if bridged */
+       bridge_tx(data, len);
+
        /* calls will not process any audio data unless
         * the call is connected OR tones feature is enabled.
         */
        /* calls will not process any audio data unless
         * the call is connected OR tones feature is enabled.
         */
@@ -1485,24 +1166,6 @@ 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);
-               }
-       }
 }
 
 
 }
 
 
@@ -1670,15 +1333,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;
@@ -1765,32 +1419,40 @@ 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;
+
+               case MESSAGE_DISABLE_DEJITTER:
+               PDEBUG(DEBUG_ISDN, "PmISDN(%s) received de-jitter disable order.\n", p_name);
+               p_m_disable_dejitter = 1;
+               p_m_preload = param->queue;
+               update_rxoff();
+               return 1;
        }
 
        }
 
-       return(0);
+       return 0;
 }
 
 void PmISDN::update_rxoff(void)
 {
 }
 
 void PmISDN::update_rxoff(void)
 {
+       int tx_dejitter = 0;
+
        /* call bridges in user space OR crypto OR recording */
        /* 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 */
@@ -1833,6 +1495,16 @@ void PmISDN::update_rxoff(void)
                                        ph_control(p_m_mISDNport, this, p_m_mISDNport->b_sock[p_m_b_index].fd, DSP_TXDATA_OFF, 0, "DSP-TXDATA", 0);
                }
        }
                                        ph_control(p_m_mISDNport, this, p_m_mISDNport->b_sock[p_m_b_index].fd, DSP_TXDATA_OFF, 0, "DSP-TXDATA", 0);
                }
        }
+       /* dejitter on bridge */
+       if (p_bridge && !p_m_disable_dejitter)
+               tx_dejitter = 1;
+       if (p_m_tx_dejitter != tx_dejitter) {
+               p_m_tx_dejitter = tx_dejitter;
+               PDEBUG(DEBUG_BCHANNEL, "we change dejitter mode to delay=%d.\n", p_m_tx_dejitter);
+               if (p_m_b_index > -1)
+                       if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
+                               ph_control(p_m_mISDNport, this, p_m_mISDNport->b_sock[p_m_b_index].fd, DSP_TX_DEJITTER, p_m_tx_dejitter, "DSP-TX_DEJITTER", p_m_tx_dejitter);
+       }
 }
 
 static int mISDN_upqueue(struct lcr_fd *fd, unsigned int what, void *instance, int i)
 }
 
 static int mISDN_upqueue(struct lcr_fd *fd, unsigned int what, void *instance, int i)
@@ -1854,98 +1526,96 @@ static int mISDN_upqueue(struct lcr_fd *fd, unsigned int what, void *instance, i
        mISDNport = mISDNport_first;
        while(mISDNport) {
                /* handle queued up-messages (d-channel) */
        mISDNport = mISDNport_first;
        while(mISDNport) {
                /* handle queued up-messages (d-channel) */
-               if (!mISDNport->isloopback) {
-                       while ((mb = mdequeue(&mISDNport->upqueue))) {
-                               l3m = &mb->l3;
-                               switch(l3m->type) {
-                                       case MPH_ACTIVATE_IND:
-                                       if (mISDNport->l1link != 1) {
-                                               l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
-                                               end_trace();
-                                               mISDNport->l1link = 1;
-                                       }
+               while ((mb = mdequeue(&mISDNport->upqueue))) {
+                       l3m = &mb->l3;
+                       switch(l3m->type) {
+                               case MPH_ACTIVATE_IND:
+                               if (mISDNport->l1link != 1) {
+                                       l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
+                                       end_trace();
+                                       mISDNport->l1link = 1;
+                               }
+                               break;
+       
+                               case MPH_DEACTIVATE_IND:
+                               if (mISDNport->l1link != 0) {
+                                       l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
+                                       end_trace();
+                                       mISDNport->l1link = 0;
+                               }
+                               break;
+
+                               case MPH_INFORMATION_IND:
+                               PDEBUG(DEBUG_ISDN, "Received MPH_INFORMATION_IND for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
+                               switch (l3m->pid) {
+                                       case L1_SIGNAL_LOS_ON:
+                                       mISDNport->los = 1;
                                        break;
                                        break;
-               
-                                       case MPH_DEACTIVATE_IND:
-                                       if (mISDNport->l1link != 0) {
-                                               l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
-                                               end_trace();
-                                               mISDNport->l1link = 0;
-                                       }
+                                       case L1_SIGNAL_LOS_OFF:
+                                       mISDNport->los = 0;
                                        break;
                                        break;
+                                       case L1_SIGNAL_AIS_ON:
+                                       mISDNport->ais = 1;
+                                       break;
+                                       case L1_SIGNAL_AIS_OFF:
+                                       mISDNport->ais = 0;
+                                       break;
+                                       case L1_SIGNAL_RDI_ON:
+                                       mISDNport->rdi = 1;
+                                       break;
+                                       case L1_SIGNAL_RDI_OFF:
+                                       mISDNport->rdi = 0;
+                                       break;
+                                       case L1_SIGNAL_SLIP_TX:
+                                       mISDNport->slip_tx++;
+                                       break;
+                                       case L1_SIGNAL_SLIP_RX:
+                                       mISDNport->slip_rx++;
+                                       break;
+                               }
+                               break;
 
 
-                                       case MPH_INFORMATION_IND:
-                                       PDEBUG(DEBUG_ISDN, "Received MPH_INFORMATION_IND for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
-                                       switch (l3m->pid) {
-                                               case L1_SIGNAL_LOS_ON:
-                                               mISDNport->los = 1;
-                                               break;
-                                               case L1_SIGNAL_LOS_OFF:
-                                               mISDNport->los = 0;
-                                               break;
-                                               case L1_SIGNAL_AIS_ON:
-                                               mISDNport->ais = 1;
-                                               break;
-                                               case L1_SIGNAL_AIS_OFF:
-                                               mISDNport->ais = 0;
-                                               break;
-                                               case L1_SIGNAL_RDI_ON:
-                                               mISDNport->rdi = 1;
-                                               break;
-                                               case L1_SIGNAL_RDI_OFF:
-                                               mISDNport->rdi = 0;
-                                               break;
-                                               case L1_SIGNAL_SLIP_TX:
-                                               mISDNport->slip_tx++;
-                                               break;
-                                               case L1_SIGNAL_SLIP_RX:
-                                               mISDNport->slip_rx++;
-                                               break;
+                               case MT_L2ESTABLISH:
+                               l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
+                               add_trace("tei", NULL, "%d", l3m->pid);
+                               end_trace();
+                               mISDNport->l2link = 1;
+                               if (l3m->pid < 128)
+                                       mISDNport->l2mask[l3m->pid >> 3] |= (1 << (l3m->pid & 7));
+                               if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127) {
+                                       if (mISDNport->l2establish.active) {
+                                               unsched_timer(&mISDNport->l2establish);
+                                               PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
                                        }
                                        }
-                                       break;
+                               }
+                               break;
 
 
-                                       case MT_L2ESTABLISH:
-                                       l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
+                               case MT_L2RELEASE:
+                               if (l3m->pid < 128)
+                                       mISDNport->l2mask[l3m->pid >> 3] &= ~(1 << (l3m->pid & 7));
+                               if (!mISDNport->l2establish.active) {
+                                       l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
                                        add_trace("tei", NULL, "%d", l3m->pid);
                                        end_trace();
                                        add_trace("tei", NULL, "%d", l3m->pid);
                                        end_trace();
-                                       mISDNport->l2link = 1;
-                                       if (l3m->pid < 128)
-                                               mISDNport->l2mask[l3m->pid >> 3] |= (1 << (l3m->pid & 7));
-                                       if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127) {
-                                               if (mISDNport->l2establish.active) {
-                                                       unsched_timer(&mISDNport->l2establish);
-                                                       PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
-                                               }
-                                       }
-                                       break;
-
-                                       case MT_L2RELEASE:
-                                       if (l3m->pid < 128)
-                                               mISDNport->l2mask[l3m->pid >> 3] &= ~(1 << (l3m->pid & 7));
-                                       if (!mISDNport->l2establish.active) {
-                                               l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
-                                               add_trace("tei", NULL, "%d", l3m->pid);
-                                               end_trace();
-                                               /* down if not nt-ptmp */ 
-                                               if (!mISDNport->ntmode || mISDNport->ptp)
-                                                       mISDNport->l2link = 0;
-                                       }
-                                       if (!mISDNport->isloopback && (!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127) {
-                                               if (!mISDNport->l2establish.active && mISDNport->l2hold) {
-                                                       PDEBUG(DEBUG_ISDN, "set timer and establish.\n");
-                                                       schedule_timer(&mISDNport->l2establish, 5, 0);
-                                                       mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
-                                               }
+                                       /* down if not nt-ptmp */ 
+                                       if (!mISDNport->ntmode || mISDNport->ptp)
+                                               mISDNport->l2link = 0;
+                               }
+                               if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127) {
+                                       if (!mISDNport->l2establish.active && mISDNport->l2hold) {
+                                               PDEBUG(DEBUG_ISDN, "set timer and establish.\n");
+                                               schedule_timer(&mISDNport->l2establish, 5, 0);
+                                               mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
                                        }
                                        }
-                                       break;
-
-                                       default:
-                                       /* l3-data is sent to LCR */
-                                       stack2manager(mISDNport, l3m->type, l3m->pid, l3m);
                                }
                                }
-                               /* free message */
-                               free_l3_msg(l3m);
+                               break;
+
+                               default:
+                               /* l3-data is sent to LCR */
+                               stack2manager(mISDNport, l3m->type, l3m->pid, l3m);
                        }
                        }
+                       /* free message */
+                       free_l3_msg(l3m);
                }
                mISDNport = mISDNport->next;
        }
                }
                mISDNport = mISDNport->next;
        }
@@ -1957,8 +1627,8 @@ static int l2establish_timeout(struct lcr_timer *timer, void *instance, int i)
 {
        struct mISDNport *mISDNport = (struct mISDNport *)instance;
 
 {
        struct mISDNport *mISDNport = (struct mISDNport *)instance;
 
-       if (!mISDNport->isloopback && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) {
-//             PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
+       if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) {
+               PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
                mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
                schedule_timer(&mISDNport->l2establish, 5, 0); /* 5 seconds */
        }
                mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
                schedule_timer(&mISDNport->l2establish, 5, 0); /* 5 seconds */
        }
@@ -2027,7 +1697,6 @@ static int b_sock_callback(struct lcr_fd *fd, unsigned int what, void *instance,
 static int b_timer_timeout(struct lcr_timer *timer, void *instance, int i)
 {
        struct mISDNport *mISDNport = (struct mISDNport *)instance;
 static int b_timer_timeout(struct lcr_timer *timer, void *instance, int i)
 {
        struct mISDNport *mISDNport = (struct mISDNport *)instance;
-puts("fires");
 
        bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
 
 
        bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
 
@@ -2045,6 +1714,7 @@ int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3
        struct mISDNport *mISDNport = (struct mISDNport *)ml3->priv;
        struct mbuffer *mb;
 
        struct mISDNport *mISDNport = (struct mISDNport *)ml3->priv;
        struct mbuffer *mb;
 
+#ifdef OLD_MT_ASSIGN
        /* special MT_ASSIGN handling:
         *
         * if we request a PID from mlayer, we always do it while lcr is locked.
        /* special MT_ASSIGN handling:
         *
         * if we request a PID from mlayer, we always do it while lcr is locked.
@@ -2062,6 +1732,7 @@ int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3
                mt_assign_pid = pid;
                return(0);
        }
                mt_assign_pid = pid;
                return(0);
        }
+#endif
        /* queue message, create, if required */
        if (!l3m) {
                l3m = alloc_l3_msg();
        /* queue message, create, if required */
        if (!l3m) {
                l3m = alloc_l3_msg();
@@ -2117,7 +1788,6 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        int force_nt = ifport->nt;
        int l1hold = ifport->l1hold;
        int l2hold = ifport->l2hold;
        int force_nt = ifport->nt;
        int l1hold = ifport->l1hold;
        int l2hold = ifport->l2hold;
-       int loop = 0;
        int ss5 = ifport->ss5;
        int i, cnt;
        int pri, bri, pots;
        int ss5 = ifport->ss5;
        int i, cnt;
        int pri, bri, pots;
@@ -2126,25 +1796,6 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        struct mISDN_devinfo devinfo;
        unsigned int protocol, prop;
 
        struct mISDN_devinfo devinfo;
        unsigned int protocol, prop;
 
-#if defined WITH_GSM_BS && defined WITH_GSM_MS
-       loop = ifport->gsm_ms | ifport->gsm_bs;
-#else
-#ifdef WITH_GSM_BS
-       loop = ifport->gsm_bs;
-#endif
-#ifdef WITH_GSM_MS
-       loop = ifport->gsm_ms;
-#endif
-#endif
-//printf("%s == %s\n", ifport->portname, options.loopback_int);
-       if (!strcmp(ifport->portname, options.loopback_lcr))
-               loop = 1;
-
-       if (loop) {
-               if (mISDNloop_open())
-                       return NULL;
-       }
-
        /* check port counts */
        ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
        if (ret < 0) {
        /* check port counts */
        ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
        if (ret < 0) {
@@ -2159,10 +1810,7 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        if (port < 0) {
                port = mISDN_getportbyname(mISDNsocket, cnt, ifport->portname);
                if (port < 0) {
        if (port < 0) {
                port = mISDN_getportbyname(mISDNsocket, cnt, ifport->portname);
                if (port < 0) {
-                       if (loop)
-                               PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface?.\n", ifport->portname);
-                       else
-                               PERROR_RUNTIME("Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", ifport->portname);
+                       PERROR_RUNTIME("Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", ifport->portname);
                        return(NULL);
                }
                // note: 'port' has still the port number
                        return(NULL);
                }
                // note: 'port' has still the port number
@@ -2276,21 +1924,14 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
                mISDNportp = &((*mISDNportp)->next);
        mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
        add_timer(&mISDNport->l2establish, l2establish_timeout, mISDNport, 0);
                mISDNportp = &((*mISDNportp)->next);
        mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
        add_timer(&mISDNport->l2establish, l2establish_timeout, mISDNport, 0);
-       if (loop | ss5) {
-               /* loop/ss5 link is always active */
+       if (ss5) {
+               /* ss5 link is always active */
                mISDNport->l1link = 1;
                mISDNport->l2link = 1;
        } else {
                mISDNport->l1link = -1;
                mISDNport->l2link = -1;
        }
                mISDNport->l1link = 1;
                mISDNport->l2link = 1;
        } else {
                mISDNport->l1link = -1;
                mISDNport->l2link = -1;
        }
-#ifdef WITH_GSM_BS
-       mISDNport->gsm_bs = ifport->gsm_bs;
-#endif
-#ifdef WITH_GSM_MS
-       mISDNport->gsm_ms = ifport->gsm_ms;
-#endif
-       mISDNport->isloopback = loop;
        pmemuse++;
        *mISDNportp = mISDNport;
 
        pmemuse++;
        *mISDNportp = mISDNport;
 
@@ -2302,7 +1943,7 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        if (ss5) {
                /* try to keep interface enabled */
                l1hold = 1;
        if (ss5) {
                /* try to keep interface enabled */
                l1hold = 1;
-               l2hold = 1;
+               l2hold = 0;
        }
        /* set l2hold */
        switch (l2hold) {
        }
        /* set l2hold */
        switch (l2hold) {
@@ -2332,56 +1973,23 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        if (l2hold) // supports layer 2 hold
               prop |= (1 << MISDN_FLG_L2_HOLD);
        /* open layer 3 and init upqueue */
        if (l2hold) // supports layer 2 hold
               prop |= (1 << MISDN_FLG_L2_HOLD);
        /* open layer 3 and init upqueue */
-       if (loop) {
-               unsigned long on = 1;
-               struct sockaddr_mISDN addr;
-
-               if (devinfo.nrbchan < 8) {
-                       printf("loop port %d has a low number of bchannels. (only %d) remember that all interfaces that requires a loopback could run out of channels\n", port, devinfo.nrbchan);
-//                     mISDNport_close(mISDNport);
-//                     return(NULL);
-               }
-
-               if ((mISDNport->lcr_sock = socket(PF_ISDN, SOCK_DGRAM, (bri) ? ISDN_P_TE_S0 : ISDN_P_TE_E1)) < 0) {
-                       PERROR_RUNTIME("loop port %d failed to open socket.\n", port);
-                       mISDNport_close(mISDNport);
-                       return(NULL);
-               }
-               /* set nonblocking io */
-               if (ioctl(mISDNport->lcr_sock, FIONBIO, &on) < 0) {
-                       PERROR_RUNTIME("loop port %d failed to set socket into nonblocking io.\n", port);
-                       mISDNport_close(mISDNport);
-                       return(NULL);
-               }
-               /* bind socket to dchannel */
-               memset(&addr, 0, sizeof(addr));
-               addr.family = AF_ISDN;
-               addr.dev = port;
-               addr.channel = 0;
-               if (bind(mISDNport->lcr_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-                       PERROR_RUNTIME("loop port %d failed to bind socket. (errno %d)\n", port, errno);
-                       mISDNport_close(mISDNport);
-                       return(NULL);
-               }
-       } else {
-               /* queue must be initializes, because l3-thread may send messages during open_layer3() */
-               mqueue_init(&mISDNport->upqueue);
-               mISDNport->ml3 = open_layer3(port, protocol, prop , do_layer3, mISDNport);
-               if (!mISDNport->ml3) {
-                       mqueue_purge(&mISDNport->upqueue);
-                       PERROR_RUNTIME("open_layer3() failed for port %d\n", port);
-                       start_trace(port,
-                               ifport->interface,
-                               NULL,
-                               NULL,
-                               DIRECTION_NONE,
-                               CATEGORY_CH,
-                               0,
-                               "PORT (open failed)");
-                       end_trace();
-                       mISDNport_close(mISDNport);
-                       return(NULL);
-               }
+       /* queue must be initializes, because l3-thread may send messages during open_layer3() */
+       mqueue_init(&mISDNport->upqueue);
+       mISDNport->ml3 = open_layer3(port, protocol, prop , do_layer3, mISDNport);
+       if (!mISDNport->ml3) {
+               mqueue_purge(&mISDNport->upqueue);
+               PERROR_RUNTIME("open_layer3() failed for port %d\n", port);
+               start_trace(port,
+                       ifport->interface,
+                       NULL,
+                       NULL,
+                       DIRECTION_NONE,
+                       CATEGORY_CH,
+                       0,
+                       "PORT (open failed)");
+               end_trace();
+               mISDNport_close(mISDNport);
+               return(NULL);
        }
 
        SCPY(mISDNport->name, devinfo.name);
        }
 
        SCPY(mISDNport->name, devinfo.name);
@@ -2403,7 +2011,7 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        }
 
        /* if ptp, pull up the link */
        }
 
        /* if ptp, pull up the link */
-       if (!mISDNport->isloopback && mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) {
+       if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode)) {
                mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
                l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
                add_trace("tei", NULL, "%d", 0);
                mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
                l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
                add_trace("tei", NULL, "%d", 0);
@@ -2516,18 +2124,12 @@ void mISDNport_close(struct mISDNport *mISDNport)
        del_timer(&mISDNport->l2establish);
 
        /* close layer 3, if open */
        del_timer(&mISDNport->l2establish);
 
        /* close layer 3, if open */
-       if (!mISDNport->isloopback && mISDNport->ml3) {
+       if (mISDNport->ml3) {
                close_layer3(mISDNport->ml3);
        }
 
                close_layer3(mISDNport->ml3);
        }
 
-       /* close gsm socket, if open */
-       if (mISDNport->isloopback && mISDNport->lcr_sock > -1) {
-               close(mISDNport->lcr_sock);
-       }
-
        /* purge upqueue */
        /* purge upqueue */
-       if (!mISDNport->isloopback)
-               mqueue_purge(&mISDNport->upqueue);
+       mqueue_purge(&mISDNport->upqueue);
 
        /* remove from list */
        mISDNportp = &mISDNport_first;
 
        /* remove from list */
        mISDNportp = &mISDNport_first;
@@ -2550,45 +2152,53 @@ void mISDNport_close(struct mISDNport *mISDNport)
 
 
 /*
 
 
 /*
- * enque data from upper buffer
+ * enque data from remote port
  */
  */
-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)];
+       unsigned char buf[MISDN_HEADER_LEN+((length>p_m_preload)?length:p_m_preload)];
        struct mISDNhead *hh = (struct mISDNhead *)buf;
        int ret;
 
        if (p_m_b_index < 0)
        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;
+
+       /* run load-timer when bridged and dejitter is disabled */
+       if (!p_m_loadtimer.active && p_m_disable_dejitter && p_m_preload > 0)
+               update_load();
 
        /* 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 it to DSP_LOAD to prevent jitter gaps.
 
        /* preload procedure
         * if transmit buffer in DSP module is empty,
         * preload it to DSP_LOAD to prevent jitter gaps.
+        * 
+        * if load runs empty, preload again.
         */
         */
-       if (p_m_load == 0 && ISDN_LOAD > 0) {
+       if (p_m_disable_dejitter && p_m_load == 0 && p_m_preload > 0) {
+//printf("preload=%d\n", p_m_preload);
                hh->prim = PH_DATA_REQ; 
                hh->id = 0;
                hh->prim = PH_DATA_REQ; 
                hh->id = 0;
-               memset(buf+MISDN_HEADER_LEN, (options.law=='a')?0x2a:0xff, ISDN_LOAD);
-               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+ISDN_LOAD, 0, NULL, 0);
+               memset(buf+MISDN_HEADER_LEN, silence, p_m_preload);
+               ret = sendto(p_m_mISDNport->b_sock[p_m_b_index].fd, buf, MISDN_HEADER_LEN+p_m_preload, 0, NULL, 0);
                if (ret <= 0)
                        PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
                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);
+               p_m_load += p_m_preload;
+               schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
        }
 
        /* drop if load would exceed ISDN_MAXLOAD
         * this keeps the delay not too high
         */
        }
 
        /* drop if load would exceed ISDN_MAXLOAD
         * this keeps the delay not too high
         */
-       if (p_m_load+length > ISDN_MAXLOAD)
-               return;
+//printf("load=%d len=%d 2*preload=%d\n", p_m_load, length, p_m_preload << 1);
+       if (p_m_disable_dejitter && p_m_preload > 0 && p_m_load+length > (p_m_preload << 1))
+               return -EINVAL;
 
        /* make and send frame */
        hh->prim = PH_DATA_REQ;
 
        /* make and send frame */
        hh->prim = PH_DATA_REQ;
@@ -2598,6 +2208,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)