added exporting/importing bchannel stacks to the remote application
[lcr.git] / apppbx.cpp
index 7dbf24e..375980a 100644 (file)
@@ -83,8 +83,8 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
        e_cfnr_release = 0;
        e_cfnr_call = 0;
        e_password_timeout = 0;
-       e_multipoint_cause = CAUSE_NOUSER;
-       e_multipoint_location = LOCATION_PRIVATE_LOCAL;
+       e_multipoint_cause = 0;
+       e_multipoint_location = 0;
        e_dialing_queue[0] = '\0';
        e_crypt = CRYPT_OFF;
        e_crypt_state = CM_ST_NULL;
@@ -201,13 +201,13 @@ void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *prese
                }
                if (ifmsn)
                {
-                       trace_header("SCREEN (found in list)", DIRECTION_IN);
+                       trace_header("SCREEN (found in MSN list)", DIRECTION_IN);
                        add_trace("msn", NULL, "%s", id);
                        end_trace();
                }
                if (!ifmsn && msn1) // not in list, first msn given
                {
-                       trace_header("SCREEN (not found in list)", DIRECTION_IN);
+                       trace_header("SCREEN (not found MSN in list)", DIRECTION_IN);
                        add_trace("msn", "given", "%s", id);
                        add_trace("msn", "used", "%s", msn1);
                        end_trace();
@@ -240,7 +240,7 @@ void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *prese
        }
        if (ifscreen) // match
        {
-               trace_header("SCREEN (found in list)", out?DIRECTION_OUT:DIRECTION_IN);
+               trace_header("SCREEN (found in screen list)", out?DIRECTION_OUT:DIRECTION_IN);
                switch(*type)
                {
                        case INFO_NTYPE_UNKNOWN:
@@ -399,8 +399,8 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                        e_dtmf_last = 0;
                        e_cfnr_release = 0;
                        e_cfnr_call = 0;
-                       e_multipoint_cause = CAUSE_NOUSER;
-                       e_multipoint_location = LOCATION_PRIVATE_LOCAL;
+                       e_multipoint_cause = 0;
+                       e_multipoint_location = 0;
                        e_dialing_queue[0] = '\0';
                        e_crypt = 0;
                        e_crypt_state = CM_ST_NULL;
@@ -1398,8 +1398,8 @@ int EndpointAppPBX::handler(void)
                        {
                                e_redial = 0;
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
-                               e_multipoint_cause = CAUSE_NOUSER;
-                               e_multipoint_location = LOCATION_PRIVATE_LOCAL;
+                               e_multipoint_cause = 0;
+                               e_multipoint_location = 0;
                                new_state(EPOINT_STATE_IN_OVERLAP);
                                e_join_pattern = 0;
                                process_dialing();
@@ -1477,8 +1477,8 @@ int EndpointAppPBX::handler(void)
                                ea_endpoint->free_portlist(portlist);
                        }
                        /* put on hold */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_HOLD;
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = CHANNEL_STATE_HOLD;
                        message_put(message);
                        /* indicate no patterns */
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
@@ -1562,8 +1562,8 @@ void EndpointAppPBX::hookflash(void)
        }
        /* dialtone after pressing the hash key */
        process_hangup(e_join_cause, e_join_location);
-       e_multipoint_cause = CAUSE_NOUSER;
-       e_multipoint_location = LOCATION_PRIVATE_LOCAL;
+       e_multipoint_cause = 0;
+       e_multipoint_location = 0;
        port = find_port_id(ea_endpoint->ep_portlist->port_id);
        if (port)
        {
@@ -1614,7 +1614,6 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
        memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
        memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
        e_dtmf = param->setup.dtmf;
-
        /* screen incoming caller id */
        interface = interface_first;
        while(interface)
@@ -1774,7 +1773,8 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
        /* turn off dtmf detection, in case dtmf is sent with keypad information */
        if (e_dtmf)
        {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received dialing information, so dtmf is now disabled, to prevent double detection by keypad+dtmf.\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
+               trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
+               end_trace();
                e_dtmf = 0;
        }
 
@@ -1801,21 +1801,29 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
        }
 
        /* keypad when connected */
-       if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
+       if (e_state == EPOINT_STATE_CONNECT)
        {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
-               /* processing keypad function */
-               if (param->information.id[0] == '0')
+               if (e_ext.keypad)
                {
-                       hookflash();
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
+                       /* processing keypad function */
+                       if (param->information.id[0] == '0')
+                       {
+                               hookflash();
+                       }
+                       if (param->information.id[0])
+                               keypad_function(param->information.id[0]);
+               } else
+               {
+                       trace_header("DTMF (not enabled by extension's settings)", DIRECTION_IN);
+                       end_trace();
                }
-               if (param->information.id[0])
-                       keypad_function(param->information.id[0]);
                return;
        }
        if (e_state != EPOINT_STATE_IN_OVERLAP)
        {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
+               trace_header("DTMF (ignored, not connected and not dialing)", DIRECTION_IN);
+               end_trace();
                return;
        }
        if (!param->information.id[0])
@@ -1841,15 +1849,16 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
 /* port MESSAGE_DTMF */
 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
 {
-       trace_header("DTMF", DIRECTION_IN);
-       add_trace("digit", NULL, "%c", param->dtmf);
-       end_trace();
        /* only if dtmf detection is enabled */
        if (!e_dtmf)
        {
-               PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
+               trace_header("DTMF (disabled)", DIRECTION_IN);
+               end_trace();
                return;
        }
+       trace_header("DTMF", DIRECTION_IN);
+       add_trace("digit", NULL, "%c", param->dtmf);
+       end_trace();
 
 #if 0
 NOTE: vbox is now handled due to overlap state
@@ -1994,8 +2003,8 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type,
                message_put(message);
 
                /* connect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_CONNECT;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_CONNECT;
                message_put(message);
        } else
        {
@@ -2004,8 +2013,8 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type,
                message_put(message);
 
                /* disconnect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_HOLD;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_HOLD;
                message_put(message);
        }
        new_state(EPOINT_STATE_OUT_OVERLAP);
@@ -2037,8 +2046,8 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ
                message_put(message);
 
                /* connect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_CONNECT;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_CONNECT;
                message_put(message);
        } else
        {
@@ -2047,8 +2056,8 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ
                message_put(message);
 
                /* disconnect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_HOLD;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_HOLD;
                message_put(message);
        }
        /* if we are in a call */
@@ -2079,8 +2088,8 @@ void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type,
                message_put(message);
 
                /* connect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_CONNECT;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_CONNECT;
                message_put(message);
        } else
        {
@@ -2089,8 +2098,8 @@ void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type,
                message_put(message);
 
                /* disconnect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_HOLD;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_HOLD;
                message_put(message);
        }
        /* if we are in a call */
@@ -2190,31 +2199,32 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        e_cfnr_call = e_cfnr_release = 0;
        if (e_ext.number[0])
                e_dtmf = 1; /* allow dtmf */
-//             if (call_countrelations(ea_endpoint->ep_join_id) == 2)
+
+       /* modify colp */
+       /* other calls with no caller id (or not available for the extension) and force colp */
+       if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
        {
-               /* modify colp */
-               /* other calls with no caller id (or not available for the extension) and force colp */
-               if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
+               e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
+               if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
                {
-                       e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
-                       if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
+                       port = find_port_id(portlist->port_id);
+                       if (port)
                        {
-                               port = find_port_id(portlist->port_id);
-                               if (port)
-                               {
-                                       SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
-                                       e_connectinfo.present = INFO_PRESENT_ALLOWED;
-                               }
+                               SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
+                               e_connectinfo.present = INFO_PRESENT_ALLOWED;
                        }
                }
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
-               memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
-               message_put(message);
        }
+
+       /* send connect to join */
        if (ea_endpoint->ep_join_id)
        {
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_CONNECT;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
+               memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
+               message_put(message);
+
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_CONNECT;
                message_put(message);
        } else if (!e_adminid)
        {
@@ -2369,8 +2379,15 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
        } else
        {
                /* use multipoint cause if no connect yet */
-               cause = e_multipoint_cause;
-               location = e_multipoint_location;
+               if (e_multipoint_cause)
+               {
+                       cause = e_multipoint_cause;
+                       location = e_multipoint_location;
+               } else
+               {
+                       cause = CAUSE_NOUSER;
+                       location = LOCATION_PRIVATE_LOCAL;
+               }
        }
 
        e_cfnr_call = e_cfnr_release = 0;
@@ -2378,7 +2395,7 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
        /* process hangup */
        process_hangup(e_join_cause, e_join_location);
        e_multipoint_cause = 0;
-       e_multipoint_location = LOCATION_PRIVATE_LOCAL;
+       e_multipoint_location = 0;
 
        if (message_type == MESSAGE_DISCONNECT)
        {
@@ -2406,8 +2423,8 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
                        message_put(message);
                        /* connect audio, if not already */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = CHANNEL_STATE_CONNECT;
                        message_put(message);
                        /* send disconnect */
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
@@ -2540,8 +2557,8 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
                /* tell call about it */
                if (ea_endpoint->ep_join_id)
                {
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_HOLD;
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = CHANNEL_STATE_HOLD;
                        message_put(message);
                }
                break;
@@ -2565,8 +2582,8 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
                /* tell call about it */
                if (ea_endpoint->ep_join_id)
                {
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = CHANNEL_STATE_CONNECT;
                        message_put(message);
                }
                break;
@@ -2884,6 +2901,17 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                port_resume(portlist, message_type, param);
                break;
 
+#if 0
+               /* port assigns bchannel */
+               case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel message %d from port.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
+               /* only one port is expected to be connected to bchannel */
+               message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
+               break;
+#endif
+
+
                default:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
        }
@@ -2971,8 +2999,8 @@ void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type,
        if (e_join_pattern && e_ext.own_setup)
        {
                /* disconnect audio */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_HOLD;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_HOLD;
                message_put(message);
        }
        if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
@@ -2997,11 +3025,11 @@ void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_typ
        if (e_join_pattern)
        {
                /* connect / disconnect audio */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
                if (e_ext.own_proceeding)
-                       message->param.channel = CHANNEL_STATE_HOLD;
+                       message->param.audiopath = CHANNEL_STATE_HOLD;
                else
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+                       message->param.audiopath = CHANNEL_STATE_CONNECT;
                message_put(message);
        }
 //                     UCPY(e_join_tone, "proceeding");
@@ -3025,11 +3053,11 @@ void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type,
        if (e_join_pattern)
        {
                /* connect / disconnect audio */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
                if (e_ext.own_alerting)
-                       message->param.channel = CHANNEL_STATE_HOLD;
+                       message->param.audiopath = CHANNEL_STATE_HOLD;
                else
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+                       message->param.audiopath = CHANNEL_STATE_CONNECT;
                message_put(message);
        }
        if (portlist)
@@ -3109,17 +3137,18 @@ void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type,
        }
        set_tone(portlist, NULL);
        e_join_pattern = 0;
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-       message->param.channel = CHANNEL_STATE_CONNECT;
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+       message->param.audiopath = CHANNEL_STATE_CONNECT;
        message_put(message);
        e_start = now;
 }
 
 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
-void EndpointAppPBX::join_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
+void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
 {
        char cause[16];
        struct message *message;
+       struct port_list *portlist = NULL;
 
 
        /* be sure that we are active */
@@ -3146,11 +3175,11 @@ void EndpointAppPBX::join_disconnect_release(struct port_list *portlist, int mes
                if (e_state==EPOINT_STATE_IN_OVERLAP)
                {
                        new_state(EPOINT_STATE_IN_PROCEEDING);
-                       if (portlist)
+                       if (ea_endpoint->ep_portlist)
                        {
-                               message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
+                               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
                                message_put(message);
-                               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+                               logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
                        }
 /* caused the error, that the first knock sound was not there */
 /*                                     set_tone(portlist, "proceeding"); */
@@ -3158,6 +3187,7 @@ void EndpointAppPBX::join_disconnect_release(struct port_list *portlist, int mes
                /* send display of powerdialing */
                if (e_ext.display_dialing)
                {
+                       portlist = ea_endpoint->ep_portlist;
                        while (portlist)
                        {
                                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
@@ -3213,12 +3243,13 @@ void EndpointAppPBX::join_disconnect_release(struct port_list *portlist, int mes
                e_join_pattern = 0;
        } else /* else we enable audio */
        {
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_CONNECT;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = CHANNEL_STATE_CONNECT;
                message_put(message);
        }
        /* send disconnect message */
        SCPY(e_tone, cause);
+       portlist = ea_endpoint->ep_portlist;
        while(portlist)
        {
                set_tone(portlist, cause);
@@ -3254,8 +3285,8 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
                        }
 
                        /* disconnect audio */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_HOLD;
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = CHANNEL_STATE_HOLD;
                        message_put(message);
 
                        /* get dialing info */
@@ -3429,7 +3460,7 @@ void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, u
        }
 }
 
-/* call sends messages to the endpoint
+/* JOIN sends messages to the endpoint
  */
 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
 {
@@ -3438,7 +3469,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
 
        if (!join_id)
        {
-               PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
+               PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
                return;
        }
 
@@ -3447,7 +3478,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
        /* send MESSAGE_DATA to port */
        if (message_type == MESSAGE_DATA)
        {
-               if (join_id == ea_endpoint->ep_join_id) // still linked with call
+               if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
                {
                        /* skip if no port relation */
                        if (!portlist)
@@ -3461,28 +3492,28 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                }
        }
 
-//     PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active call (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
+//     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)
        {
-               /* CALL SENDS CRYPT message */
+               /* JOIN SENDS CRYPT message */
                case MESSAGE_CRYPT:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
                join_crypt(portlist, message_type, param);
                break;
 
-               /* CALL sends INFORMATION message */
+               /* JOIN sends INFORMATION message */
                case MESSAGE_INFORMATION:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.id);
                join_information(portlist, message_type, param);
                break;
 
-               /* CALL sends FACILITY message */
+               /* JOIN sends FACILITY message */
                case MESSAGE_FACILITY:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                join_facility(portlist, message_type, param);
                break;
 
-               /* CALL sends OVERLAP message */
+               /* JOIN sends OVERLAP message */
                case MESSAGE_OVERLAP:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_SETUP
@@ -3494,7 +3525,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_overlap(portlist, message_type, param);
                break;
 
-               /* CALL sends PROCEEDING message */
+               /* JOIN sends PROCEEDING message */
                case MESSAGE_PROCEEDING:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if(e_state!=EPOINT_STATE_IN_OVERLAP)
@@ -3505,7 +3536,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_proceeding(portlist, message_type, param);
                break;
 
-               /* CALL sends ALERTING message */
+               /* JOIN sends ALERTING message */
                case MESSAGE_ALERTING:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_OVERLAP
@@ -3517,7 +3548,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_alerting(portlist, message_type, param);
                break;
 
-               /* CALL sends CONNECT message */
+               /* JOIN sends CONNECT message */
                case MESSAGE_CONNECT:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_OVERLAP
@@ -3530,27 +3561,43 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_connect(portlist, message_type, param);
                break;
 
-               /* CALL sends DISCONNECT/RELEASE message */
-               case MESSAGE_DISCONNECT: /* call disconnect */
-               case MESSAGE_RELEASE: /* call releases */
+               /* JOIN sends DISCONNECT/RELEASE message */
+               case MESSAGE_DISCONNECT: /* JOIN disconnect */
+               case MESSAGE_RELEASE: /* JOIN releases */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
-               join_disconnect_release(portlist, message_type, param);
+               join_disconnect_release(message_type, param);
                break;
 
-               /* CALL sends SETUP message */
+               /* JOIN sends SETUP message */
                case MESSAGE_SETUP:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from terminal='%s',id='%s' to id='%s' (dialing itype=%d)\n", ea_endpoint->ep_serial, param->setup.callerinfo.extension, param->setup.callerinfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.itype);
                join_setup(portlist, message_type, param);
-               return;
                break;
 
-               /* CALL sends special mISDNSIGNAL message */
+               /* JOIN sends special mISDNSIGNAL message */
                case MESSAGE_mISDNSIGNAL: /* isdn message to port */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                join_mISDNsignal(portlist, message_type, param);
                break;
 
-               /* CALL has pattern available */
+#if 0
+               /* 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);
+               break;
+#endif
+
+               /* JOIN has pattern available */
                case MESSAGE_PATTERN: /* indicating pattern available */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (!e_join_pattern)
@@ -3564,18 +3611,18 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                                portlist = portlist->next;
                        }
                        /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = CHANNEL_STATE_CONNECT;
                        message_put(message);
 //                     /* tell remote epoint to connect audio also, because we like to hear the patterns */
 //                     message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
-//                     message->param.channel = CHANNEL_STATE_CONNECT;
+//                     message->param.audiopath = CHANNEL_STATE_CONNECT;
 //                     message_put(message);
 // patterns are available, remote already connected audio
                }
                break;
 
-               /* CALL has no pattern available */
+               /* JOIN has no pattern available */
                case MESSAGE_NOPATTERN: /* indicating no pattern available */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_join_pattern)
@@ -3583,23 +3630,23 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                        PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
                        e_join_pattern = 0;
                        /* disconnect our audio tx and rx */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_HOLD;
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = CHANNEL_STATE_HOLD;
                        message_put(message);
                }
                break;
 
 #if 0
-               /* CALL (dunno at the moment) */
+               /* JOIN (dunno at the moment) */
                case MESSAGE_REMOTE_AUDIO:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-               message->param.channel = param->channel;
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+               message->param.audiopath = param->channel;
                message_put(message);
                break;
 #endif
 
-               /* CALL sends a notify message */
+               /* JOIN sends a notify message */
                case MESSAGE_NOTIFY:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                join_notify(portlist, message_type, param);
@@ -3725,13 +3772,13 @@ reject:
                PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
                goto reject;
        }
-       if (joinpbx->c_type != JOIN_TYPE_PBX)
+       if (join->j_type != JOIN_TYPE_PBX)
        {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
                goto reject;
        }
        joinpbx = (class JoinPBX *)join;
-       relation = joinpbx->c_relation;
+       relation = joinpbx->j_relation;
        if (!relation)
        {
                PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
@@ -3760,7 +3807,7 @@ reject:
                PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
                while(debug_c)
                {
-                       PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->c_serial);
+                       PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
                        debug_c = debug_c->next;
                }
                PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
@@ -3816,12 +3863,12 @@ reject:
        message_put(message);
 
        /* we send a connect to the audio path (not for vbox) */
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CHANNEL);
-       message->param.channel = CHANNEL_STATE_CONNECT;
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+       message->param.audiopath = CHANNEL_STATE_CONNECT;
        message_put(message);
 
        /* beeing paranoid, we make call update */
-       joinpbx->c_updatebridge = 1;
+       joinpbx->j_updatebridge = 1;
 
        if (options.deb & DEBUG_EPOINT)
        {
@@ -3834,7 +3881,7 @@ reject:
                PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
                while(debug_c)
                {
-                       PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->c_serial);
+                       PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
                        debug_c = debug_c->next;
                }
                PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
@@ -3873,7 +3920,7 @@ void EndpointAppPBX::join_join(void)
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
                return;
        }
-       if (our_join->c_type != JOIN_TYPE_PBX)
+       if (our_join->j_type != JOIN_TYPE_PBX)
        {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
                return;
@@ -3958,21 +4005,21 @@ void EndpointAppPBX::join_join(void)
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
                return;
        }
-       if (other_join->c_type != JOIN_TYPE_PBX)
+       if (other_join->j_type != JOIN_TYPE_PBX)
        {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
                return;
        }
        other_joinpbx = (class JoinPBX *)other_join;
-       if (our_joinpbx->c_partyline && other_joinpbx->c_partyline)
+       if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
        {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
                return;
        }
 
        /* remove relation to endpoint for join on hold */
-       other_relation = other_joinpbx->c_relation;
-       other_relation_pointer = &other_joinpbx->c_relation;
+       other_relation = other_joinpbx->j_relation;
+       other_relation_pointer = &other_joinpbx->j_relation;
        while(other_relation)
        {
                if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
@@ -3990,8 +4037,8 @@ void EndpointAppPBX::join_join(void)
                temp_epoint = find_epoint_id(other_relation->epoint_id);
                if (temp_epoint)
                {
-                       if (temp_epoint->ep_join_id == other_join->c_serial)
-                               temp_epoint->ep_join_id = our_join->c_serial;
+                       if (temp_epoint->ep_join_id == other_join->j_serial)
+                               temp_epoint->ep_join_id = our_join->j_serial;
                }
 
                other_relation_pointer = &other_relation->next;
@@ -4000,32 +4047,32 @@ void EndpointAppPBX::join_join(void)
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
 
        /* join call relations */
-       our_relation = our_joinpbx->c_relation;
-       our_relation_pointer = &our_joinpbx->c_relation;
+       our_relation = our_joinpbx->j_relation;
+       our_relation_pointer = &our_joinpbx->j_relation;
        while(our_relation)
        {
                our_relation_pointer = &our_relation->next;
                our_relation = our_relation->next;
        }
-       *our_relation_pointer = other_joinpbx->c_relation;
-       other_joinpbx->c_relation = NULL;
+       *our_relation_pointer = other_joinpbx->j_relation;
+       other_joinpbx->j_relation = NULL;
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
 
        /* release endpoint on hold */
-       message = message_create(other_joinpbx->c_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
+       message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
        message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
        message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
        message_put(message);
        
        /* if we are not a partyline, we get partyline state from other join */
-       our_joinpbx->c_partyline += other_joinpbx->c_partyline; 
+       our_joinpbx->j_partyline += other_joinpbx->j_partyline; 
 
        /* remove empty join */
        delete other_join;
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
 
        /* mixer must update */
-       our_joinpbx->c_updatebridge = 1; /* update mixer flag */
+       our_joinpbx->j_updatebridge = 1; /* update mixer flag */
 
        /* we send a retrieve to that endpoint */
        // mixer will update the hold-state of the join and send it to the endpoints is changes
@@ -4064,14 +4111,14 @@ int EndpointAppPBX::check_external(char **errstr, class Port **port)
                *errstr = "No Call";
                return(1);
        }
-       if (join->c_type != JOIN_TYPE_PBX)
+       if (join->j_type != JOIN_TYPE_PBX)
        {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
                *errstr = "No PBX Call";
                return(1);
        }
        joinpbx = (class JoinPBX *)join;
-       relation = joinpbx->c_relation;
+       relation = joinpbx->j_relation;
        if (!relation)
        {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
@@ -4433,6 +4480,33 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                end_trace();
                break;
 
+#if 0
+               case MESSAGE_BCHANNEL:
+               trace_header("BCHANNEL", dir);
+               switch(param->bchannel.type)
+               {
+                       case BCHANNEL_REQUEST:
+                       add_trace("type", NULL, "request");
+                       break;
+                       case BCHANNEL_ASSIGN:
+                       add_trace("type", NULL, "assign");
+                       break;
+                       case BCHANNEL_ASSIGN_ACK:
+                       add_trace("type", NULL, "assign_ack");
+                       break;
+                       case BCHANNEL_REMOVE:
+                       add_trace("type", NULL, "remove");
+                       break;
+                       case BCHANNEL_REMOVE_ACK:
+                       add_trace("type", NULL, "remove_ack");
+                       break;
+               }
+               if (param->bchannel.addr)
+                       add_trace("address", NULL, "%x", param->bchannel.addr);
+               end_trace();
+               break;
+#endif
+
                default:
                PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
        }