Added 'extern' flag to interface.conf.
[lcr.git] / apppbx.cpp
index 15fa438..25521dd 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************\
 **                                                                           **
-** PBX4Linux                                                                 **
+** Linux Call Router                                                         **
 **                                                                           **
 **---------------------------------------------------------------------------**
 ** Copyright: Andreas Eversberg                                              **
 \*****************************************************************************/ 
 
 
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <poll.h>
 #include "main.h"
 
-
 class EndpointAppPBX *apppbx_first = NULL;
 
 /*
  * EndpointAppPBX constructor
  */
-EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
+EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
 {
        class EndpointAppPBX **apppointer;
 
@@ -39,8 +30,9 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
 
        /* initialize */
         memset(&e_ext, 0, sizeof(struct extension));
+       // *************** NOTE: also change value in read_extension() **************
        e_ext.rights = 4; /* international */
-       e_ext.rxvol = e_ext.txvol = 256;
+       e_ext.rx_gain = e_ext.tx_gain = 0;
         e_state = EPOINT_STATE_IDLE;
         e_ext.number[0] = '\0';
        e_extension_interface[0] = '\0';
@@ -50,7 +42,7 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
         memset(&e_redirinfo, 0, sizeof(struct redir_info));
         memset(&e_capainfo, 0, sizeof(struct capa_info));
         e_start = e_stop = 0;
-//      e_origin = 0;
+       e_origin = origin;
        e_ruleset = ruleset_main;
        if (e_ruleset)
                e_rule = e_ruleset->rule_first;
@@ -60,12 +52,12 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
        e_match_timeout = 0;
        e_match_to_action = NULL;
         e_select = 0;
-        e_extdialing = e_dialinginfo.number;
+        e_extdialing = e_dialinginfo.id;
 //        e_knocking = 0;
 //        e_knocktime = 0;
        e_hold = 0;
-//        e_call_tone[0] = e_hold_tone[0] = '\0';
-        e_call_pattern /*= e_hold_pattern*/ = 0;
+//        e_join_tone[0] = e_hold_tone[0] = '\0';
+        e_join_pattern /*= e_hold_pattern*/ = 0;
         e_redial = 0;
        e_tone[0] = '\0';
        e_adminid = 0; // will be set, if call was initiated via admin socket
@@ -81,11 +73,12 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
         e_dtmf = 0;
         e_dtmf_time = 0;
         e_dtmf_last = 0;
+       e_enablekeypad = 0;
        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;
@@ -95,7 +88,7 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
        e_vbox[0] = '\0';
        e_tx_state = NOTIFY_STATE_ACTIVE;
        e_rx_state = NOTIFY_STATE_ACTIVE;
-       e_call_cause = e_call_location = 0;
+       e_join_cause = e_join_location = 0;
 /*********************************
  *********************************
  ********* ATTENTION *************
@@ -117,8 +110,7 @@ EndpointAppPBX::~EndpointAppPBX(void)
        /* detach */
        temp =apppbx_first;
        tempp = &apppbx_first;
-       while(temp)
-       {
+       while(temp) {
                if (temp == this)
                        break;
 
@@ -126,10 +118,7 @@ EndpointAppPBX::~EndpointAppPBX(void)
                temp = temp->next;
        }
        if (temp == 0)
-       {
-               PERROR("error: endpoint not in endpoint's list, exitting.\n");
-               exit(-1);
-       }
+               FATAL("Endpoint not in endpoint's list.\n");
        *tempp = next;
 
 }
@@ -138,37 +127,22 @@ EndpointAppPBX::~EndpointAppPBX(void)
 /*
  * trace header for application
  */
-void EndpointAppPBX::trace_header(char *name, int direction)
+void EndpointAppPBX::trace_header(const char *name, int direction)
 {
-       char msgtext[sizeof(trace.name)];
+       struct trace _trace;
 
-       SCPY(msgtext, name);
+       char msgtext[sizeof(_trace.name)];
 
-       /* add direction */
-       if (direction)
-       {
-               if (p_m_ntmode)
-               {
-                       if (direction == DIRECTION_OUT)
-                               SCAT(msgtext, " N->U");
-                       else
-                               SCAT(msgtext, " N<-U");
-               } else
-               {
-                       if (direction == DIRECTION_OUT)
-                               SCAT(msgtext, " U->N");
-                       else
-                               SCAT(msgtext, " U<-N");
-               }
-       }
+       SCPY(msgtext, name);
 
        /* init trace with given values */
        start_trace(0,
                    NULL,
-                   nationalize(e_callerinfo.id, e_callerinfo.ntype),
-                   e_dialinginfo.number,
+                   numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
+                   e_dialinginfo.id,
                    direction,
-                   CATEGORY_AP,
+                   CATEGORY_EP,
+                   ea_endpoint->ep_serial,
                    msgtext);
 }
 
@@ -179,158 +153,65 @@ EPOINT_STATE_NAMES
  */
 void EndpointAppPBX::new_state(int state)
 {
-       if (e_state != state)
-       {
+#if 0
+       if (e_state != state) {
                trace_header("NEW STATE", DIRECTION_NONE);
                add_trace("state", "old", "%s", state_name[e_state]);
                add_trace("state", "new", "%s", state_name[state]);
+               end_trace();
        }
+#endif
        e_state = state;
 }
 
 
-/* screen caller id
- * out==0: incomming caller id, out==1: outgoing caller id
+/* release join and port (as specified)
  */
-void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present)
-{
-       struct interface        *interface;
-
-       interface = interface_first;
-       while(interface)
-       {
-               if (!strcmp(e_callerinfo.interface, interface->name))
-               {
-                       break;
-               }
-               interface = interface->next;
-       }
-add logging
-       if (interface)
-       {
-               /* screen incoming caller id */
-               if (!out)
-               {
-                       /* check for MSN numbers, use first MSN if no match */
-                       msn1 = NULL;
-                       ifmsn = interface->ifmsn;
-                       while(ifmns)
-                       {
-                               if (!msn1)
-                                       msn1 = ifmns->msn;
-                               if (!strcmp(ifmns->mns, id))
-                               {
-                                       break;
-                               }
-                               ifmsn = ifmsn->next;
-                       }
-                       if (!ifmns && mns1) // not in list, first msn given
-                               UNCPY(id, msn1, idsize);
-                       id[idsize-1] = '\0';
-               }
-       
-               /* check screen list */
-               if (out)
-                       iscreen = interface->ifscreen_out;
-               else
-                       iscreen = interface->ifscreen_in;
-               while (ifscreen)
-               {
-                       if (ifcreen->match_type==-1 || ifscreen->match_type==*type)
-                       if (ifcreen->match_present==-1 || ifscreen->match_present==*present)
-                       {
-                               if (strchr(ifcreen->match_id,'%'))
-                               {
-                                       if (!strncmp(ifscreen->match_id, id, strchr(ifscreen->match_id,'%')-ifscreen->match_id))
-                                               break;
-                               } else
-                               {
-                                       if (!strcmp(ifscreen->match_id, id))
-                                               break;
-                               }
-                       }
-                       ifscreen = ifscreen->next;
-               }
-               if (ifscreen) // match
-               {
-                       if (ifscren->result_type != -1)
-                               *type = ifscreen->result_type;
-                       if (ifscren->result_present != -1)
-                               *present = ifscreen->result_present;
-                       if (strchr(ifscreen->match_id,'%'))
-                       {
-                               SCPY(suffix, strchr(ifscreen->match_id,'%') - ifscreen->match_id + id);
-                               UNCPY(id, ifscreen->result_id);
-                               id[idsize-1] = '\0';
-                               if (strchr(ifscreen->result_id,'%'))
-                               {
-                                       *strchr(ifscreen->result_id,'%') = '\0';
-                                       UNCAT(id, suffix, idsize);
-                                       id[idsize-1] = '\0';
-                               }
-                       } else
-                       {
-                               UNCPY(id, ifscreen->result_id, idsize);
-                               id[idsize-1] = '\0';
-                       }
-               }
-       }
-}
-
-/* release call and port (as specified)
- */
-void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
+void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
 {
        struct port_list *portlist;
-       struct message *message;
+       struct lcr_msg *message;
        char cause[16];
-       class Call *call;
 
        /* message to test call */
-       admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0);
+       admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
 
        /* if a release is pending */
-       if (release==RELEASE_CALL || release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation);
-               if (ea_endpoint->ep_call_id)
-               {
-                       call = find_call_id(ea_endpoint->ep_call_id);
-                       if (call)
-                               call->release(ea_endpoint->ep_serial, 0, calllocation, callcause);
+       if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
+               if (ea_endpoint->ep_join_id) {
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
+                       message->param.disconnectinfo.cause = joincause;
+                       message->param.disconnectinfo.location = joinlocation;
+                       message_put(message);
+                       ea_endpoint->ep_join_id = 0;
                }
-               ea_endpoint->ep_call_id = 0;
-               e_call_pattern = 0;
+               e_join_pattern = 0;
 #if 0
-               if (release != RELEASE_PORT_CALLONLY)
-               {
+               if (release != RELEASE_PORT_JOINONLY) {
                        if (e_hold_id)
-                               call_release(e_hold_id, ea_endpoint->ep_serial, 1, calllocation, callcause);
+                               join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
                        e_hold_id = 0;
                }
 #endif
        }
-       if (release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
-       {
+       if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
-               while((portlist = ea_endpoint->ep_portlist))
-               {
-                       if (portlist->port_id)
-                       {
+               while((portlist = ea_endpoint->ep_portlist)) {
+                       if (portlist->port_id) {
                                SPRINT(cause, "cause_%02x", portcause);
                                set_tone(portlist, cause);
                                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
                                message->param.disconnectinfo.cause = portcause;
                                message->param.disconnectinfo.location = portlocation;
                                message_put(message);
-                               logmessage(message);
+                               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                        }
                        ea_endpoint->free_portlist(portlist);
                }
 
                /* if callback is enabled, call back with the given caller id */
-               if (e_callback)
-               {
+               if (e_callback) {
                        /* reset some stuff */
                        new_state(EPOINT_STATE_IDLE);
                        memset(&e_connectinfo, 0, sizeof(struct connect_info));
@@ -344,15 +225,16 @@ void EndpointAppPBX::release(int release, int calllocation, int callcause, int p
                        e_match_timeout = 0;
                        e_match_to_action = NULL;
                        //e_select = 0;
-                       e_extdialing = e_dialinginfo.number;
+                       e_extdialing = e_dialinginfo.id;
                        e_connectedmode = 0;
                        e_dtmf = 0;
                        e_dtmf_time = 0;
                        e_dtmf_last = 0;
+                       e_enablekeypad = 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;
@@ -363,33 +245,29 @@ void EndpointAppPBX::release(int release, int calllocation, int callcause, int p
                        e_vbox[0] = '\0';
                        e_tx_state = NOTIFY_STATE_ACTIVE;
                        e_rx_state = NOTIFY_STATE_ACTIVE;
-                       e_call_cause = e_call_location = 0;
+                       e_join_cause = e_join_location = 0;
                        e_rule_nesting = 0;
                        /* the caller info of the callback user */
                        memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
                        memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
                        /* create dialing by callerinfo */
-                       if (e_ext.number[0] && e_extension_interface[0])
-                       {
+                       if (e_ext.number[0] && e_extension_interface[0]) {
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
                                /* create callback to the current terminal */
-                               SCPY(e_dialinginfo.number, e_ext.number);
+                               SCPY(e_dialinginfo.id, e_ext.number);
                                SCPY(e_dialinginfo.interfaces, e_extension_interface);
                                e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
                                e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
-                       } else
-                       {
-                               if (e_cbto[0])
-                               {
-                                       SCPY(e_dialinginfo.number, e_cbto);
-                               } else
-                               {
+                       } else {
+                               if (e_cbto[0]) {
+                                       SCPY(e_dialinginfo.id, e_cbto);
+                               } else {
                                        /* numberrize caller id and use it to dial to the callback */
-                                       SCPY(e_dialinginfo.number, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
+                                       SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
                                }
                                e_dialinginfo.itype = INFO_ITYPE_ISDN;
                                e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
-                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.number);
+                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
                        }
                        return;
                }
@@ -402,22 +280,20 @@ void EndpointAppPBX::release(int release, int calllocation, int callcause, int p
 
 
 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
-void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *ntype, int *present, int *screen, char *voip, char *intern, char *name)
+void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
 {
-       PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d voip='%s' intern='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (voip)?voip:"NULL", (intern)?intern:"NULL", (name)?name:"NULL");
+       PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
 
        /* caller id is not restricted, so we do nothing */
        if (*present != INFO_PRESENT_RESTRICTED)
                return;
 
        /* only extensions are restricted */
-       if (!intern)
-               return;
-       if (!intern[0])
+       if (!ext->number[0])
                return;
 
        /* if we enabled anonymouse ignore */
-       if (anon_ignore)
+       if (ext->anon_ignore)
                return;
 
        /* else we remove the caller id */
@@ -430,39 +306,36 @@ void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *n
 // maybe we should not make voip address anonymous
 //     if (voip)
 //             voip[0] = '\0';
-// maybe it's no fraud to present internal id
-//     if (intern)
-//             intern[0] = '\0';
+// maybe it's no fraud to present extension id
+//     if (extension)
+//             extension[0] = '\0';
        if (name)
                name[0] = '\0';
 }
 
 /* used display message to display callerid as available */
-char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *voip, char *intern, char *name)
+char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
 {
        static char display[81];
 
        display[0] = '\0';
-       char *cid = numberrize_callerinfo(id, ntype);
+       const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
 
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d voip='%s' intern='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (voip)?voip:"NULL", (intern)?intern:"NULL", (name)?name:"NULL");
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
 
        if (!id)
                id = "";
-       if (!voip)
-               voip = "";
-       if (!intern)
-               intern = "";
+       if (!extension)
+               extension = "";
        if (!name)
                name = "";
 
        /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
 
        /* internal extension's caller id */
-       if (intern[0] && e_ext.display_int)
-       {
+       if (extension[0] && e_ext.display_int) {
                if (!display[0])
-                       SCAT(display, intern);
+                       SCAT(display, extension);
                if (display[0])
                        SCAT(display, " ");
                if (itype == INFO_ITYPE_VBOX)
@@ -472,12 +345,9 @@ char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int
        }
 
        /* external caller id */
-       if (!intern[0] && !voip[0] && e_ext.display_ext)
-       {
-               if (!display[0])
-               {
-                       if (!cid[0])
-                       {
+       if (!extension[0] && e_ext.display_ext) {
+               if (!display[0]) {
+                       if (!cid[0]) {
                                if (present == INFO_PRESENT_RESTRICTED)
                                        SCAT(display, "anonymous");
                                else
@@ -488,19 +358,8 @@ char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int
                }
        }
 
-       /* voip caller id */
-       if (voip[0] && e_ext.display_voip)
-       {
-               if (!display[0] && cid[0])
-                               SCAT(display, cid);
-               if (display[0])
-                               SCAT(display, " ");
-               SCAT(display, voip);
-       }
-
        /* display if callerid is anonymouse but available due anon-ignore */
-       if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
-       {
+       if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
                if (!cid[0])
                        SCAT(display, "unknown");
                else 
@@ -509,12 +368,9 @@ char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int
        }
 
        /* display if callerid is anonymouse but available due anon-ignore */
-       if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
-       {
-               if (!display[0])
-               {
-                       if (!id[0])
-                       {
+       if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
+               if (!display[0]) {
+                       if (!id[0]) {
                                if (present == INFO_PRESENT_RESTRICTED)
                                        SCAT(display, "anonymous");
                                else
@@ -527,8 +383,7 @@ char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int
        }
 
        /* caller name */
-       if (name[0] && e_ext.display_name)
-       {
+       if (name[0] && e_ext.display_name) {
                if (!display[0] && cid[0])
                                SCAT(display, cid);
                if (display[0])
@@ -545,19 +400,17 @@ char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int
 void EndpointAppPBX::notify_active(void)
 {
        struct port_list *portlist = ea_endpoint->ep_portlist;
-       struct message *message;
+       struct lcr_msg *message;
        int notify = 0;
 
-       switch(e_tx_state)
-       {
+       switch(e_tx_state) {
                case NOTIFY_STATE_ACTIVE:
                /* we are already active, so we don't do anything */
                break;
 
                case NOTIFY_STATE_SUSPEND:
                notify = INFO_NOTIFY_USER_RESUMED;
-               while(portlist)
-               {
+               while(portlist) {
                        set_tone(portlist, NULL);
                        portlist = portlist->next;
                }
@@ -566,8 +419,7 @@ void EndpointAppPBX::notify_active(void)
 
                case NOTIFY_STATE_HOLD:
                notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
-               while(portlist)
-               {
+               while(portlist) {
                        set_tone(portlist, NULL);
                        portlist = portlist->next;
                }
@@ -576,8 +428,7 @@ void EndpointAppPBX::notify_active(void)
 
                case NOTIFY_STATE_CONFERENCE:
                notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
-               while(portlist)
-               {
+               while(portlist) {
                        set_tone(portlist, NULL);
                        portlist = portlist->next;
                }
@@ -589,12 +440,11 @@ void EndpointAppPBX::notify_active(void)
        }
 
        if (notify)
-       while(portlist)
-       {
+       while(portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
                message->param.notifyinfo.notify = notify;
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                portlist = portlist->next;
        }
 }
@@ -607,23 +457,20 @@ void EndpointAppPBX::keypad_function(char digit)
 {
 
        /* we must be in a call, in order to send messages to the call */
-       if (e_ext.number[0] == '\0')
-       {
+       if (e_ext.number[0] == '\0') {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
                return;
        }
 
-       switch(digit)
-       {
+       switch(digit) {
                /* join conference */
                case '3':
-               if (ea_endpoint->ep_call_id == 0)
-               {
+               if (ea_endpoint->ep_join_id == 0) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
                        break;
                }
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
-               join_call();
+               join_join();
                break;
 
                /* crypt shared */
@@ -651,9 +498,9 @@ void EndpointAppPBX::keypad_function(char digit)
 
 
 /* set tone pattern for port */
-void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
+void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
        if (!tone)
                tone = "";
@@ -661,13 +508,8 @@ void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
        /* store for suspended processes */
        SCPY(e_tone, tone);
 
-       if (!portlist)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
-               return;
-       }
 
-       if (e_call_pattern /* pattern are provided */
+       if (e_join_pattern /* pattern are provided */
         && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
         && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
         && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
@@ -678,19 +520,20 @@ void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
         && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
         && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
         && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
-        && tone[0] && !!strncmp(tone,"crypt_*",6))
-       {
+        && tone[0] && !!strncmp(tone,"crypt_*",6)) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
                tone = "";
        }
 
-       if (portlist)
-       {
+       if (portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
-               SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
+               SCPY(message->param.tone.dir, e_ext.tones_dir);
                SCPY(message->param.tone.name, tone);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+       } else {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
+               return;
        }
 }
 
@@ -700,61 +543,75 @@ void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
  * if no ifname was given, any interface that is not an extension
  * will be searched.
  */
-static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
+struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
 {
        struct interface *interface;
+       struct interface_port *ifport, *ifport_start;
+       struct select_channel *selchannel; 
        struct mISDNport *mISDNport;
+       int index, i;
+       int there_is_an_external = 0;
 
        interface = interface_first;
 
        /* first find the given interface or, if not given, one with no extension */
        checknext:
-       if (!interface)
-               return(null);
+       if (!interface) {
+               if (!there_is_an_external && !(ifname && ifname[0])) {
+                       trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
+                       add_trace("info", NULL, "Add 'external' parameter to interface.conf.");
+                       end_trace();
+               }
+               return(NULL);
+       }
 
        /* check for given interface */
-       if (ifname)
-       {
-               if (!strcasecmp(interface->name, ifname))
-               {
+       if (ifname && ifname[0]) {
+               if (!strcasecmp(interface->name, ifname)) {
                        /* found explicit interface */
-                       printlog("%3d  interface %s found as given\n", ea_endpoint->ep_serial, ifname);
-                       goto found;
+                       trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
+                       add_trace("interface", NULL, "%s", ifname);
+                       end_trace();
+                       goto foundif;
                }
 
-       } else
-       {
-               if (!interface->extension)
-               {
+       } else {
+               if (interface->external) {
+                       there_is_an_external = 1;
                        /* found non extension */
-                       printlog("%3d  interface %s found, that is not an extension\n", ea_endpoint->ep_serial, interface->name);
-                       goto found;
+                       trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
+                       add_trace("interface", NULL, "%s", interface->name);
+                       end_trace();
+                       goto foundif;
                }
        }
 
        interface = interface->next;
        goto checknext;
+foundif:
 
        /* see if interface has ports */
-       if (!interface->ifport)
-       {
+       if (!interface->ifport) {
                /* no ports */
-               printlog("%3d  interface %s has no active ports, skipping.\n", ea_endpoint->ep_serial, interface->name);
+               trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
+               add_trace("interface", NULL, "%s", interface->name);
+               end_trace();
                interface = interface->next;
                goto checknext;
        }
 
        /* select port by algorithm */
-       ifport_start = interface->port;
+       ifport_start = interface->ifport;
        index = 0;
-       if (interface->hunt == HUNT_ROUNDROBIN)
-       {
-               while(ifport_start->next && index<interface->hunt_next)
-               {
+       if (interface->hunt == HUNT_ROUNDROBIN) {
+               while(ifport_start->next && index<interface->hunt_next) {
                        ifport_start = ifport_start->next;
-                       i++;
+                       index++;
                }
-               printlog("%3d  starting with port#%d position %d (round-robin)\n", ea_endpoint->ep_serial, ifport_start->portnum, index);
+               trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
+               add_trace("port", NULL, "%d", ifport_start->portnum);
+               add_trace("position", NULL, "%d", index);
+               end_trace();
        }
 
        /* loop ports */
@@ -762,78 +619,114 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
        nextport:
 
        /* see if port is available */
-       if (!ifport->mISDNport)
-       {
-               printlog("%3d  port#%d position %d is not available, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
+       if (!ifport->mISDNport) {
+               trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
+               add_trace("port", NULL, "%d", ifport->portnum);
+               add_trace("position", NULL, "%d", index);
+               end_trace();
                goto portbusy;
        }
        mISDNport = ifport->mISDNport;
 
-#warning admin block auch bei incomming calls
-#warning calls releasen, wenn port entfernt wird, geblockt wird
        /* see if port is administratively blocked */
-       if (ifport->block)
-       {
-               printlog("%3d  port#%d position %d is administratively blocked, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
+       if (ifport->block) {
+               trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
+               add_trace("port", NULL, "%d", ifport->portnum);
+               add_trace("position", NULL, "%d", index);
+               end_trace();
                goto portbusy;
        }
 
-       /* see if link is up */
-       if (mISDNport->ptp && !mISDNport->l2link)
-       {
-               printlog("%3d  port#%d position %d is ptp but layer 2 is down.\n", ea_endpoint->ep_serial, ifport->portnum, index);
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
+       /* see if link is up on PTP*/
+       if (mISDNport->l2hold && mISDNport->l2link<1) {
+               trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
+               add_trace("port", NULL, "%d", ifport->portnum);
+               add_trace("position", NULL, "%d", index);
+               end_trace();
                goto portbusy;
        }
 
        /* check for channel form selection list */
        *channel = 0;
-       selchannel = ifport->selchannel;
-       while(selchannel)
-       {
-               switch(selchannel->channel)
-               {
+       selchannel = ifport->out_channel;
+       while(selchannel) {
+               switch(selchannel->channel) {
                        case CHANNEL_FREE: /* free channel */
-                       if (mISDNport->b_inuse >= mISDNport->b_num)
+                       if (mISDNport->b_reserved >= mISDNport->b_num)
                                break; /* all channel in use or reserverd */
                        /* find channel */
                        i = 0;
-                       while(i < mISDNport->b_num)
-                       {
-                               if (mISDNport->b_port[i] == NULL)
-                               {
+                       while(i < mISDNport->b_num) {
+                               if (mISDNport->b_port[i] == NULL) {
                                        *channel = i+1+(i>=15);
-                                       printlog("%3d  port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
+                                       trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
+                                       add_trace("port", NULL, "%d", ifport->portnum);
+                                       add_trace("position", NULL, "%d", index);
+                                       add_trace("channel", NULL, "%d", *channel);
+                                       end_trace();
                                        break;
                                }
                                i++;
                        }
+                       if (*channel)
+                               break;
+                       trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
+                       add_trace("port", NULL, "%d", ifport->portnum);
+                       add_trace("position", NULL, "%d", index);
+                       end_trace();
                        break;
 
                        case CHANNEL_ANY: /* don't ask for channel */
-                       if (mISDNport->b_inuse >= mISDNport->b_num)
-                       {
+                       if (mISDNport->b_reserved >= mISDNport->b_num) {
+                               trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
+                               add_trace("port", NULL, "%d", ifport->portnum);
+                               add_trace("position", NULL, "%d", index);
+                               add_trace("total", NULL, "%d", mISDNport->b_num);
+                               add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
+                               end_trace();
                                break; /* all channel in use or reserverd */
                        }
-                       printlog("%3d  port#%d position %d using with 'any channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
-                       *channel = SEL_CHANNEL_ANY;
+                       trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
+                       add_trace("port", NULL, "%d", ifport->portnum);
+                       add_trace("position", NULL, "%d", index);
+                       end_trace();
+                       *channel = CHANNEL_ANY;
                        break;
 
                        case CHANNEL_NO: /* call waiting */
-                       printlog("%3d  port#%d position %d using with 'no channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
-                       *channel = SEL_CHANNEL_NO;
+                       trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
+                       add_trace("port", NULL, "%d", ifport->portnum);
+                       add_trace("position", NULL, "%d", index);
+                       end_trace();
+                       *channel = CHANNEL_NO;
                        break;
 
                        default:
-                       if (selchannel->channel<1 || selchannel->channel==16)
+                       if (selchannel->channel<1 || selchannel->channel==16) {
+                               trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
+                               add_trace("port", NULL, "%d", ifport->portnum);
+                               add_trace("position", NULL, "%d", index);
+                               add_trace("channel", NULL, "%d", selchannel->channel);
+                               end_trace();
                                break; /* invalid channels */
+                       }
                        i = selchannel->channel-1-(selchannel->channel>=17);
-                       if (i >= mISDNport->b_num)
+                       if (i >= mISDNport->b_num) {
+                               trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
+                               add_trace("port", NULL, "%d", ifport->portnum);
+                               add_trace("position", NULL, "%d", index);
+                               add_trace("channel", NULL, "%d", selchannel->channel);
+                               add_trace("channels", NULL, "%d", mISDNport->b_num);
+                               end_trace();
                                break; /* channel not in port */
-                       if (mISDNport->b_port[i] == NULL)
-                       {
+                       }
+                       if (mISDNport->b_port[i] == NULL) {
                                *channel = selchannel->channel;
-                               printlog("%3d  port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
+                               trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
+                               add_trace("port", NULL, "%d", ifport->portnum);
+                               add_trace("position", NULL, "%d", index);
+                               add_trace("channel", NULL, "%d", *channel);
+                               end_trace();
                                break;
                        }
                        break;
@@ -844,11 +737,9 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
        }
 
        /* if channel was found, return mISDNport and channel */
-       if (*channel)
-       {
+       if (*channel) {
                /* setting next port to start next time */
-               if (interface->hunt == HUNT_ROUNDROBIN)
-               {
+               if (interface->hunt == HUNT_ROUNDROBIN) {
                        index++;
                        if (!ifport->next)
                                index = 0;
@@ -858,20 +749,27 @@ static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
                return(mISDNport);
        }
 
-       printlog("%3d  port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport->portnum, index);
+       trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
+       add_trace("port", NULL, "%d", ifport->portnum);
+       add_trace("position", NULL, "%d", index);
+       end_trace();
 
        portbusy:
        /* go next port, until all ports are checked */
        index++;
        ifport = ifport->next;
-       if (!ifport)
-       {
+       if (!ifport) {
                index = 0;
                ifport = interface->ifport;
        }
        if (ifport != ifport_start)
                goto nextport;
 
+       if (!ifname) {
+               interface = interface->next;
+               goto checknext;
+       }
+
        return(NULL); /* no port found */
 }
 
@@ -883,12 +781,11 @@ void EndpointAppPBX::out_setup(void)
 {
        struct dialing_info     dialinginfo;
        class Port              *port;
-//     class pdss1             *pdss1;
        struct port_list        *portlist;
-       struct message          *message;
+       struct lcr_msg          *message;
        int                     anycall = 0;
        int                     cause = CAUSE_RESSOURCEUNAVAIL;
-       char                    *p;
+       const char              *p;
        char                    cfp[64];
        struct mISDNport        *mISDNport;
        char                    portname[32];
@@ -896,12 +793,15 @@ void EndpointAppPBX::out_setup(void)
        class EndpointAppPBX    *atemp;
 //     char                    allowed_ports[256];
 //     char                    exten[256];
-       int                     i, ii;
-       int                     use;
        char                    ifname[sizeof(e_ext.interfaces)],
                                number[256];
        struct port_settings    port_settings;
        int                     channel = 0;
+       int                     earlyb;
+       int                     mode = B_MODE_TRANSPARENT;
+
+       /* set bchannel mode */
+       mode = e_capainfo.source_mode;
 
        /* create settings for creating port */
        memset(&port_settings, 0, sizeof(port_settings));
@@ -909,56 +809,43 @@ void EndpointAppPBX::out_setup(void)
                SCPY(port_settings.tones_dir, e_ext.tones_dir);
        else
                SCPY(port_settings.tones_dir, options.tones_dir);
-       port_settings.tout_setup = e_ext.tout_setup;
-       port_settings.tout_dialing = e_ext.tout_dialing;
-       port_settings.tout_proceeding = e_ext.tout_proceeding;
-       port_settings.tout_alerting = e_ext.tout_alerting;
-       port_settings.tout_disconnect = e_ext.tout_disconnect;
-//     port_settings.tout_hold = e_ext.tout_hold;
-//     port_settings.tout_park = e_ext.tout_park;
        port_settings.no_seconds = e_ext.no_seconds;
        
        /* NOTE: currently the try_card feature is not supported. it should be used later to try another card, if the outgoing call fails on one port */
 
        /* check what dialinginfo.itype we got */
-       switch(e_dialinginfo.itype)
-       {
+       switch(e_dialinginfo.itype) {
                /* *********************** call to extension or vbox */
                case INFO_ITYPE_ISDN_EXTENSION:
                /* check if we deny incoming calls when we use an extension */
-               if (e_ext.noknocking)
-               {
+               if (e_ext.noknocking) {
                        atemp = apppbx_first;
-                       while(atemp)
-                       {
+                       while(atemp) {
                                if (atemp != this)
                                if (!strcmp(atemp->e_ext.number, e_ext.number))
                                        break;
                                atemp = atemp->next;
                        }
-                       if (atemp)
-                       {
+                       if (atemp) {
                                PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
-                               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ call, port */
+                               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
                                return; /* must exit here */
                        }
                }
                /* FALL THROUGH !!!! */
                case INFO_ITYPE_VBOX:
                /* get dialed extension's info */
-//             SCPY(exten, e_dialinginfo.number);
+//             SCPY(exten, e_dialinginfo.id);
 //             if (strchr(exten, ','))
 //                     *strchr(exten, ',') = '\0';
 //             if (!read_extension(&e_ext, exten))
-               if (!read_extension(&e_ext, e_dialinginfo.number))
-               {
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.number);
-                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
+               if (!read_extension(&e_ext, e_dialinginfo.id)) {
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
 
-               if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
-               {
+               if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
                        p = "vbox";
                        goto vbox_only;
@@ -966,11 +853,9 @@ void EndpointAppPBX::out_setup(void)
 
                /* string from unconditional call forward (cfu) */
                p = e_ext.cfu;
-               if (*p)
-               {
+               if (*p) {
                        /* present to forwarded party */
-                       if (e_ext.anon_ignore && e_callerinfo.id[0])
-                       {
+                       if (e_ext.anon_ignore && e_callerinfo.id[0]) {
                                e_callerinfo.present = INFO_PRESENT_ALLOWED;
                        }
                        if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
@@ -979,18 +864,13 @@ void EndpointAppPBX::out_setup(void)
 
                /* string from busy call forward (cfb) */
                p = e_ext.cfb;
-               if (*p)
-               {
+               if (*p) {
                        class EndpointAppPBX *checkapp = apppbx_first;
-                       while(checkapp)
-                       {
-                               if (checkapp != this) /* any other endpoint except our own */
-                               {
-                                       if (!strcmp(checkapp->e_ext.number, e_ext.number))
-                                       {
+                       while(checkapp) {
+                               if (checkapp != this) { /* any other endpoint except our own */
+                                       if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
                                                /* present to forwarded party */
-                                               if (e_ext.anon_ignore && e_callerinfo.id[0])
-                                               {
+                                               if (e_ext.anon_ignore && e_callerinfo.id[0]) {
                                                        e_callerinfo.present = INFO_PRESENT_ALLOWED;
                                                }
                                                if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
@@ -1003,20 +883,16 @@ void EndpointAppPBX::out_setup(void)
 
                /* string from no-response call forward (cfnr) */
                p = e_ext.cfnr;
-               if (*p)
-               {
+               if (*p) {
                        /* when cfnr is done, out_setup() will setup the call */
-                       if (e_cfnr_call)
-                       {
+                       if (e_cfnr_call) {
                                /* present to forwarded party */
-                               if (e_ext.anon_ignore && e_callerinfo.id[0])
-                               {
+                               if (e_ext.anon_ignore && e_callerinfo.id[0]) {
                                        e_callerinfo.present = INFO_PRESENT_ALLOWED;
                                }
                                goto cfnr_only;
                        }
-                       if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
-                       {
+                       if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
                                e_cfnr_release = now + e_ext.cfnr_delay;
                                e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) setting time for call-forward-busy to %s with delay %ld.\n", ea_endpoint->ep_serial, e_ext.cfnr, e_ext.cfnr_delay);
@@ -1025,9 +901,8 @@ void EndpointAppPBX::out_setup(void)
 
                /* call to all internal interfaces */
                p = e_ext.interfaces;
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple calls for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
-               while(*p)
-               {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
+               while(*p) {
                        ifname[0] = '\0';
                        while(*p!=',' && *p!='\0')
                                if (*p > ' ')
@@ -1038,85 +913,91 @@ void EndpointAppPBX::out_setup(void)
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
                        /* hunt for mISDNport and create Port */
                        mISDNport = hunt_port(ifname, &channel);
-                       if (!mISDNport)
-                       {
-                               printlog("%3d  endpoint INTERFACE '%s' not found or busy\n", ea_endpoint->ep_serial, ifname);
-                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' not found or too busy to accept calls.\n", ea_endpoint->ep_serial, e_ext.interfaces);
+                       if (!mISDNport) {
+                               trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
+                               add_trace("interface", NULL, "%s", ifname);
+                               end_trace();
                                continue;
                        }
                        /* creating INTERNAL port */
-                       SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
-                       port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport.channel_force);
+                       SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+                       if (!mISDNport->gsm)
+                               port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+                       else
+#ifdef WITH_GSM
+                               port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+#else
+                               port = NULL;
+#endif
                        if (!port)
-                       {
-                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port '%s' failed to create\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                               goto check_anycall_intern;
-                       }
+                               FATAL("No memory for Port instance\n");
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
                        memset(&dialinginfo, 0, sizeof(dialinginfo));
-                       SCPY(dialinginfo.number, e_dialinginfo.number);
+                       SCPY(dialinginfo.id, e_dialinginfo.id);
                        dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
                        dialinginfo.ntype = e_dialinginfo.ntype;
                        /* create port_list relation */
-                       portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
-                       if (!portlist)
-                       {
+                       portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
+                       if (!portlist) {
                                PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
                                delete port;
                                goto check_anycall_intern;
                        }
                        /* directory.list */
-                       if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
-                       {
+                       if (e_callerinfo.id[0] && e_ext.display_name) {
                                dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
                                if (dirname)
                                        SCPY(e_callerinfo.name, dirname);
                        }
 //                     dss1 = (class Pdss1 *)port;
                        /* message */
-//printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
+//printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
                        memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
                        memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
                        memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
                        memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
 //terminal                     SCPY(message->param.setup.from_terminal, e_ext.number);
-//terminal                     if (e_dialinginfo.number)
-//terminal                             SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
+//terminal                     if (e_dialinginfo.id)
+//terminal                             SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
                        /* handle restricted caller ids */
-                       apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
-                       apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
+                       apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+                       apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+                       apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
                        /* display callerid if desired for extension */
-                       SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
+                       SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
                        /* use cnip, if enabld */
-                       if (!e_ext.centrex)
-                               message->param.setup.callerinfo.name[0] = '\0';
+       //              if (!e_ext.centrex)
+       //                      message->param.setup.callerinfo.name[0] = '\0';
                        /* screen clip if prefix is required */
-                       if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
-                       {
+                       if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
                                SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
-                               SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
+                               SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
                                message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
                        }
+                       if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
+                               SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
+                               SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
+                               message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
+                       }
                        /* use internal caller id */
-                       if (e_callerinfo.intern[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
-                       {
-                               SCPY(message->param.setup.callerinfo.id, e_callerinfo.intern);
+                       if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
+                               SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
                                message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
+                               message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
                        }
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                        anycall = 1;
                }
 
                /* string from parallel call forward (cfp) */
                p = e_ext.cfp;
-               if (*p)
-               {
-                       if (e_ext.anon_ignore && e_callerinfo.id[0])
-                       {
+               if (*p) {
+                       if (e_ext.anon_ignore && e_callerinfo.id[0]) {
                                e_callerinfo.present = INFO_PRESENT_ALLOWED;
+                               e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
                        }
                }
 
@@ -1124,14 +1005,12 @@ void EndpointAppPBX::out_setup(void)
                cfu_only: /* entry point for cfu */
                cfb_only: /* entry point for cfb */
                cfnr_only: /* entry point for cfnr */
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
 //             i=0;
-               while(*p)
-               {
-                       /* only if vbox should be dialed, and terminal is given */
+               while(*p) {
                        earlyb = 0;
-                       if (!strcmp(p, "vbox") && e_ext.number[0])
-                       {
+                       /* only if vbox should be dialed, and terminal is given */
+                       if (!strcmp(p, "vbox") && e_ext.number[0]) {
                                /* go to the end of p */
                                p += strlen(p);
 
@@ -1139,143 +1018,94 @@ void EndpointAppPBX::out_setup(void)
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
                                /* alloc port */
                                if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
-                               {
-                                       PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
-                                       break;
-                               }
+                                       FATAL("No memory for VBOX Port instance\n");
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
                                UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
-                       } else
-                       {
+                       } else {
                                cfp[0] = '\0';
                                while(*p!=',' && *p!='\0')
                                        SCCAT(cfp, *p++);
                                if (*p == ',')
                                        p++;
-               hier auch wie oben
                                /* external call */
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
                                /* hunt for mISDNport and create Port */
-                               mISDNport = mISDNport_first;
-                               port = NULL;
-                               while(mISDNport)
-                               {
-                                       /* check for external or given interface */
-                                       if (((!e_dialinginfo.interfaces[0])&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
-                                       {
-                                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                               cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
-                                               /* if PTP, skip all down links */
-                                               if (mISDNport->ptp && !mISDNport->l2link)
-                                               {
-                                                       printlog("%3d  endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
-                                                       mISDNport = mISDNport->next;
-                                                       continue;
-                                               }
-                                               /* if no channel is available */
-                                               if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
-                                               {
-                                                       use = 0;
-                                                       i = 0;
-                                                       ii = mISDNport->b_num;
-                                                       while(i < ii)
-                                                       {
-                                                               if (mISDNport->b_state[i])
-                                                                       use++;
-                                                               i++;
-                                                       }
-                                                       if (use >= mISDNport->b_num)
-                                                       {
-                                                               printlog("%3d  endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is not single link port_list NT-modem OR no channel available.\n", ea_endpoint->ep_serial);
-                                                               mISDNport = mISDNport->next;
-                                                               continue;
-                                                       }
-                                               }
-                                               /* found interface */
-                                               printlog("%3d  endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                               break;
-                                       }
-                                       mISDNport = mISDNport->next;
-                               }
-                               if (mISDNport)
-                               {
+                               mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
+                               if (mISDNport) {
                                        /* creating EXTERNAL port*/
-                                       SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
-                                       port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
-                                       earlyb = mISDNport->is_earlyb;
-                               } else
-                               {
+                                       SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+                                               port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+                                       if (!port)
+                                               FATAL("No memory for Port instance\n");
+                                       earlyb = mISDNport->earlyb;
+                               } else {
                                        port = NULL;
-                                       printlog("%3d  endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
-                                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' too busy to accept calls.\n", ea_endpoint->ep_serial, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
+                                       trace_header("INTERFACE (too busy)", DIRECTION_NONE);
+                                       add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
+                                       end_trace();
                                }
                        }
-                       if (!port)
-                       {
+                       if (!port) {
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
                                goto check_anycall_intern;
                        }
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
                        memset(&dialinginfo, 0, sizeof(dialinginfo));
-                       SCPY(dialinginfo.number, cfp);
-                       dialinginfo.itype = INFO_ITYPE_EXTERN;
+                       SCPY(dialinginfo.id, cfp);
+                       dialinginfo.itype = INFO_ITYPE_ISDN;
                        dialinginfo.ntype = e_dialinginfo.ntype;
                        portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
-                       if (!portlist)
-                       {
+                       if (!portlist) {
                                PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
                                delete port;
                                goto check_anycall_intern;
                        }
-//printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
+//printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
                        memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
                        memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
                        memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
                        /* if clip is hidden */
-                       if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
-                       {
+                       if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
                                SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
-                               SCPY(message->param.setup.callerinfo.intern, e_ext.number);
+                               SCPY(message->param.setup.callerinfo.extension, e_ext.number);
                                message->param.setup.callerinfo.ntype = e_ext.callerid_type;
                                message->param.setup.callerinfo.present = e_ext.callerid_present;
+                               message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
                        }
                        memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
 //terminal                     SCPY(message->param.setup.from_terminal, e_ext.number);
-//terminal                     if (e_dialinginfo.number)
-//terminal                             SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
+//terminal                     if (e_dialinginfo.id)
+//terminal                             SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
                                /* handle restricted caller ids */
-                       apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
-                       apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
+                       apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+                       apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+                       apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
                        /* display callerid if desired for extension */
-                       SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
+                       SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                        anycall = 1;
                }
 
                check_anycall_intern:
                /* now we have all ports created */
-               if (!anycall)
-               {
-                       printlog("%3d  endpoint INTERFACE No port or no parallel forwarding defined. Nothing to call to.\n", ea_endpoint->ep_serial);
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port or no cfp defined for extension, nothing to dial.\n", ea_endpoint->ep_serial);
-                       if (!ea_endpoint->ep_call_id)
+               if (!anycall) {
+                       trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
+                       end_trace();
+                       if (!ea_endpoint->ep_join_id)
                                break;
-                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
                break;
 
                /* *********************** external call */
                default:
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
                /* call to extenal interfaces */
-               p = e_dialinginfo.number;
-               do
-               {
+               p = e_dialinginfo.id;
+               do {
                        number[0] = '\0';
                        while(*p!=',' && *p!='\0')
                                SCCAT(number, *p++);
@@ -1284,105 +1114,67 @@ void EndpointAppPBX::out_setup(void)
                        /* found number */
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
                        /* hunt for mISDNport and create Port */
-                       mISDNport = mISDNport_first;
-                       port = NULL;
-                       while(mISDNport)
-                       {
-                               /* check for external or given interface */
-                               if ((!e_dialinginfo.interfaces[0]&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
-                               {
-                                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                       cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
-                                       /* if PTP, skip all down links */
-                                       if (mISDNport->ptp && !mISDNport->l2link)
-                                       {
-                                               printlog("%3d  endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
-                                               mISDNport = mISDNport->next;
-                                               continue;
-                                       }
-                                       /* if no channel is available */
-                                       if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
-                                       {
-                                               use = 0;
-                                               i = 0;
-                                               ii = mISDNport->b_num;
-                                               while(i < ii)
-                                               {
-                                                       if (mISDNport->b_state[i])
-                                                               use++;
-                                                       i++;
-                                               }
-                                               if (use >= mISDNport->b_num)
-                                               {
-                                                       printlog("%3d  endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is not single link port_list NT-modem OR no channel available.\n", ea_endpoint->ep_serial);
-                                                       mISDNport = mISDNport->next;
-                                                       continue;
-                                               }
-                                       }
-                                       /* found interface */
-                                       printlog("%3d  endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
-                                       break;
-                               }
-                               mISDNport = mISDNport->next;
-                       }
-                       if (!mISDNport)
-                       {
-                               printlog("%3d  endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
-                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' too busy to accept calls.\n", ea_endpoint->ep_serial, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
+                       /* hunt for mISDNport and create Port */
+                       mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
+                       if (!mISDNport) {
+                               trace_header("INTERFACE (too busy)", DIRECTION_NONE);
+                               add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
+                               end_trace();
                                goto check_anycall_extern;
                        }
                        /* creating EXTERNAL port*/
-                       SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
-                       port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
-                       if (!port)      
-                       {
-                               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no external port available\n", ea_endpoint->ep_serial);
-                               goto check_anycall_extern;
-                       }
+                       SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+                       if (!mISDNport->gsm)
+                               port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+                       else
+#ifdef WITH_GSM
+                               port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+#else
+                               port = NULL;
+#endif
+                       if (!port)
+                               FATAL("No memory for Port instance\n");
+                       earlyb = mISDNport->earlyb;
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
                        memset(&dialinginfo, 0, sizeof(dialinginfo));
-                       SCPY(dialinginfo.number, number);
-                       dialinginfo.itype = INFO_ITYPE_EXTERN;
+                       SCPY(dialinginfo.id, number);
+                       dialinginfo.itype = INFO_ITYPE_ISDN;
                        dialinginfo.ntype = e_dialinginfo.ntype;
-                       portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
-                       if (!portlist)
-                       {
+                       portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
+                       if (!portlist) {
                                PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
                                delete port;
                                goto check_anycall_extern;
                        }
-//                     dss1 = (class Pdss1 *)port;
-//printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
+//printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
                        memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
-                       SCPY(message->param.setup.dialinginfo.number, number);
+                       SCPY(message->param.setup.dialinginfo.id, number);
                        memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
                        memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
                        memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
 //terminal                     SCPY(message->param.setup.from_terminal, e_ext.number);
-//terminal                     if (e_dialinginfo.number)
-//terminal                             SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
+//terminal                     if (e_dialinginfo.id)
+//terminal                             SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
                                /* handle restricted caller ids */
-                       apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
-                       apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
+                       apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+                       apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+                       apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
                        /* display callerid if desired for extension */
-                       SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
+                       SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                        anycall = 1;
                } while(*p);
 
                check_anycall_extern:
                /* now we have all ports created */
-               if (!anycall)
-               {
-                       printlog("%3d  endpoint INTERFACE No free port found for making any call.\n", ea_endpoint->ep_serial);
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found which is idle for at least one number\n", ea_endpoint->ep_serial);
-                       if (!ea_endpoint->ep_call_id)
+               if (!anycall) {
+                       trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
+                       end_trace();
+                       if (!ea_endpoint->ep_join_id)
                                break;
-                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
                break;
@@ -1397,29 +1189,25 @@ void EndpointAppPBX::out_setup(void)
 extern int quit;
 int EndpointAppPBX::handler(void)
 {
-       if (e_crypt_state!=CM_ST_NULL)
-       {
+       if (e_crypt_state!=CM_ST_NULL) {
                cryptman_handler();
        }
 
        /* process answering machine (play) handling */
-       if (e_action)
-       {
+       if (e_action) {
                if (e_action->index == ACTION_VBOX_PLAY)
                        vbox_handler();
 
                /* process action timeout */
                if (e_action_timeout)
-               if (now_d >= e_action_timeout)
-               {
-                       if (e_state!=EPOINT_STATE_CONNECT)
-                       {
+               if (now_d >= e_action_timeout) {
+                       if (e_state!=EPOINT_STATE_CONNECT) {
                                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_call_pattern = 0;
+                               e_join_pattern = 0;
                                process_dialing();
                                return(1); /* we must exit, because our endpoint might be gone */
                        } else
@@ -1428,8 +1216,7 @@ int EndpointAppPBX::handler(void)
        } else {
                /* process action timeout */
                if (e_match_timeout)
-               if (now_d >= e_match_timeout)
-               {
+               if (now_d >= e_match_timeout) {
                        e_redial = 0;
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
                        process_dialing();
@@ -1439,10 +1226,8 @@ int EndpointAppPBX::handler(void)
 
 
        /* process redialing (epoint redials to port) */
-       if (e_redial)
-       {
-               if (now_d >= e_redial)
-               {
+       if (e_redial) {
+               if (now_d >= e_redial) {
                        e_redial = 0;
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
 
@@ -1455,10 +1240,8 @@ int EndpointAppPBX::handler(void)
        }
 
        /* process powerdialing (epoint redials to epoint) */
-       if (e_powerdialing > 0)
-       {
-               if (now_d >= e_powerdialing)
-               {
+       if (e_powerdialing > 0) {
+               if (now_d >= e_powerdialing) {
                        e_powerdialing = -1; /* leave power dialing on */
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
 
@@ -1474,41 +1257,36 @@ int EndpointAppPBX::handler(void)
        }
 
        /* process call forward no response */
-       if (e_cfnr_release)
-       {
+       if (e_cfnr_release) {
                struct port_list *portlist;
-               struct message *message;
+               struct lcr_msg *message;
 
-               if (now >= e_cfnr_release)
-               {
+               if (now >= e_cfnr_release) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
                        e_cfnr_release = 0;
 
                        /* release all ports */
-                       while((portlist = ea_endpoint->ep_portlist))
-                       {
+                       while((portlist = ea_endpoint->ep_portlist)) {
                                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
                                message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
                                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                                message_put(message);
-                               logmessage(message);
+                               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                                ea_endpoint->free_portlist(portlist);
                        }
                        /* put on hold */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                        message_put(message);
                        /* indicate no patterns */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
                        message_put(message);
-                       /* set setup state, since we have no response from the new call */
+                       /* set setup state, since we have no response from the new join */
                        new_state(EPOINT_STATE_OUT_SETUP);
                }
        } else
-       if (e_cfnr_call)
-       {
-               if (now >= e_cfnr_call)
-               {
+       if (e_cfnr_call) {
+               if (now >= e_cfnr_call) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
                        out_setup();
                        e_cfnr_call = 0;
@@ -1516,12 +1294,10 @@ int EndpointAppPBX::handler(void)
        }
 
        /* handle connection to user */
-       if (e_state == EPOINT_STATE_IDLE)
-       {
+       if (e_state == EPOINT_STATE_IDLE) {
                /* epoint is idle, check callback */
                if (e_callback)
-               if (now_d >= e_callback)
-               {
+               if (now_d >= e_callback) {
                        e_callback = 0; /* done with callback */
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
                        new_state(EPOINT_STATE_OUT_SETUP);
@@ -1532,24 +1308,22 @@ int EndpointAppPBX::handler(void)
 
        /* check for password timeout */
        if (e_action)
-       if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
-       {
+       if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE) {
                struct port_list *portlist;
 
-               if (now >= e_password_timeout)
-               {
+               if (now >= e_password_timeout) {
                        e_ruleset = ruleset_main;
                        if (e_ruleset)
                                e_rule = e_ruleset->rule_first;
                        e_action = NULL;
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
-                       printlog("%3d  endpoint PASSWORD timeout\n", ea_endpoint->ep_serial);
+                       trace_header("PASSWORD timeout", DIRECTION_NONE);
+                       end_trace();
                        e_connectedmode = 0;
                        e_dtmf = 0;
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        portlist = ea_endpoint->ep_portlist;
-                       if (portlist)
-                       {
+                       if (portlist) {
                                message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
                                set_tone(portlist, "cause_10");
                        }
@@ -1570,25 +1344,22 @@ void EndpointAppPBX::hookflash(void)
        notify_active();
        e_tx_state = NOTIFY_STATE_ACTIVE;
 
-       printlog("%3d  endpoint HOOKFLASH\n", ea_endpoint->ep_serial);
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf hookflash detected.\n", ea_endpoint->ep_serial);
-       if (ea_endpoint->ep_use > 1)
-       {
+       trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
+       end_trace();
+       if (ea_endpoint->ep_use > 1) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
                return;
        }
        /* dialtone after pressing the hash key */
-       process_hangup(e_call_cause, e_call_location);
-       e_multipoint_cause = CAUSE_NOUSER;
-       e_multipoint_location = LOCATION_PRIVATE_LOCAL;
+       process_hangup(e_join_cause, e_join_location);
+       e_multipoint_cause = 0;
+       e_multipoint_location = 0;
        port = find_port_id(ea_endpoint->ep_portlist->port_id);
-       if (port)
-       {
+       if (port) {
                port->set_echotest(0);
        }
-       if (ea_endpoint->ep_call_id)
-       {
-               release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
+       if (ea_endpoint->ep_join_id) {
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
        }
        e_ruleset = ruleset_main;
        if (e_ruleset)
@@ -1596,15 +1367,13 @@ void EndpointAppPBX::hookflash(void)
        e_action = NULL;
        new_state(EPOINT_STATE_IN_OVERLAP);
        e_connectedmode = 1;
-       SCPY(e_dialinginfo.number, e_ext.prefix);
-        e_extdialing = e_dialinginfo.number;
-       e_call_pattern = 0;
-       if (e_dialinginfo.number[0])
-       {
+       SCPY(e_dialinginfo.id, e_ext.prefix);
+        e_extdialing = e_dialinginfo.id;
+       e_join_pattern = 0;
+       if (e_dialinginfo.id[0]) {
                set_tone(ea_endpoint->ep_portlist, "dialing");
                process_dialing();
-       } else
-       {
+       } else {
                set_tone(ea_endpoint->ep_portlist, "dialpbx");
        }
        e_dtmf_time = now;
@@ -1617,62 +1386,53 @@ void EndpointAppPBX::hookflash(void)
 /* port MESSAGE_SETUP */
 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message          *message;
+       struct lcr_msg          *message;
        char                    buffer[256];
-       char                    extension[32];
-       char                    extension1[32];
-       char                    *p;
        int                     writeext;               /* flags need to write extension after modification */
        class Port              *port;
+       struct interface        *interface;
 
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+       
        portlist->port_type = param->setup.port_type;
        memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
        memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
        memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
        memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
-       e_dtmf = param->setup.dtmf;
-
-       /* screen by interface */
-       if (e_callerinfo.interface[0])
-       {
-               /* screen incoming caller id */
-               screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
+//     e_dtmf = param->setup.dtmf;
+       /* screen incoming caller id */
+       interface = interface_first;
+       while(interface) {
+               if (!strcmp(e_callerinfo.interface, interface->name)) {
+                       break;
+               }
+               interface = interface->next;
+       }
+       if (interface) {
+               do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
+               do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
        }
-colp, outclip, outcolp
 
        /* process extension */
-       if (e_callerinfo.itype == INFO_ITYPE_INTERN)
-       {
+       if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
                /* port makes call from extension */
-               SCPY(e_callerinfo.intern, e_callerinfo.id);
-               SCPY(e_ext.number, e_callerinfo.intern);
+               SCPY(e_callerinfo.extension, e_callerinfo.id);
+               SCPY(e_ext.number, e_callerinfo.extension);
                SCPY(e_extension_interface, e_callerinfo.interface);
-       } else
-       {
+       } else {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
        }
-       printlog("%3d  incoming %s='%s'%s%s%s%s dialing='%s'\n",
-               ea_endpoint->ep_serial,
-               (e_callerinfo.intern[0])?"SETUP from extension":"SETUP from extern",
-               (e_callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
-               (e_callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
-               (e_redirinfo.id[0])?"redirected='":"",
-               e_redirinfo.id,
-               (e_redirinfo.id[0])?"'":"",
-               e_dialinginfo.number
-               );
-
-       if (e_callerinfo.itype == INFO_ITYPE_INTERN)
-       {
+
+       if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
 
                /* get extension's info about caller */
-               if (!read_extension(&e_ext, e_ext.number))
-               {
+               if (!read_extension(&e_ext, e_ext.number)) {
                        /* extension doesn't exist */
-                       printlog("%3d  endpoint EXTENSION '%s' doesn't exist, please check or create.\n", ea_endpoint->ep_serial, e_callerinfo.id);
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting call from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
+                       trace_header("EXTENSION (not created)", DIRECTION_IN);
+                       add_trace("extension", NULL, "%s", e_ext.number);
+                       end_trace();
                        message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
                        new_state(EPOINT_STATE_OUT_DISCONNECT);
                        set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
@@ -1681,26 +1441,23 @@ colp, outclip, outcolp
                }
                writeext = 0;
 
-               /* put prefix (next) in front of e_dialinginfo.number */
-               if (e_ext.next[0])
-               {
-                       SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.number);
-                       SCPY(e_dialinginfo.number, buffer);
+               /* put prefix (next) in front of e_dialinginfo.id */
+               if (e_ext.next[0]) {
+                       SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
+                       SCPY(e_dialinginfo.id, buffer);
                        e_ext.next[0] = '\0';
                        writeext = 1;
-               } else if (e_ext.prefix[0])
-               {
-                       SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.number);
-                       SCPY(e_dialinginfo.number, buffer);
+               } else if (e_ext.prefix[0]) {
+                       SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
+                       SCPY(e_dialinginfo.id, buffer);
                }
 
-               /* screen caller id */
+               /* screen caller id by extension's config */
                e_callerinfo.screen = INFO_SCREEN_NETWORK;
                if (e_ext.name[0])
                        SCPY(e_callerinfo.name, e_ext.name);
                /* use caller id (or if exist: id_next_call) for this call */
-               if (e_ext.id_next_call_present >= 0)
-               {
+               if (e_ext.id_next_call_present >= 0) {
                        SCPY(e_callerinfo.id, e_ext.id_next_call);
                        /* if we restrict the pesentation */
                        if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
@@ -1709,8 +1466,7 @@ colp, outclip, outcolp
                        e_callerinfo.ntype = e_ext.id_next_call_type;
                        e_ext.id_next_call_present = -1;
                        writeext = 1;
-               } else
-               {
+               } else {
                        SCPY(e_callerinfo.id, e_ext.callerid);
                        /* if we restrict the pesentation */
                        if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
@@ -1718,37 +1474,34 @@ colp, outclip, outcolp
                        else    e_callerinfo.present = e_ext.callerid_present;
                        e_callerinfo.ntype = e_ext.callerid_type;
                }
+               e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
 
                /* extension is written */
                if (writeext)
                        write_extension(&e_ext, e_ext.number);
 
                /* set volume of rx and tx */
-               if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
-               if (e_ext.txvol!=256 || e_ext.rxvol!=256)
-               {
+               if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
+               if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
                        message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
-                       message->param.mISDNsignal.rxvol = e_ext.txvol;
-                       message->param.mISDNsignal.txvol = e_ext.rxvol;
+                       message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
+                       message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
                        message_put(message);
                }
 
                /* start recording if enabled */
-               if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
-               {
+               if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
                        /* check if we are a terminal */
                        if (e_ext.number[0] == '\0')
                                PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
-                       else
-                       {
+                       else {
                                port = find_port_id(portlist->port_id);
                                if (port)
                                        port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
                        }
                }
-       } else
-       {
+       } else {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
                /* no terminal identification */
                e_ext.number[0] = '\0';
@@ -1762,130 +1515,131 @@ colp, outclip, outcolp
        if (e_ruleset)
                        e_rule = e_ruleset->rule_first;
        e_action = NULL;
-        e_extdialing = e_dialinginfo.number;
+        e_extdialing = e_dialinginfo.id;
        new_state(EPOINT_STATE_IN_SETUP);
-       if (e_dialinginfo.number[0])
-       {
+       if (e_dialinginfo.id[0]) {
                set_tone(portlist, "dialing");
-       } else
-       {
+       } else {
                if (e_ext.number[0])
                        set_tone(portlist, "dialpbx");
                else
                        set_tone(portlist, "dialtone");
        }
        process_dialing();
-       if (e_state == EPOINT_STATE_IN_SETUP)
-       {
+       if (e_state == EPOINT_STATE_IN_SETUP) {
                /* request MORE info, if not already at higher state */
                new_state(EPOINT_STATE_IN_OVERLAP);
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        }
 }
 
 /* port MESSAGE_INFORMATION */
 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
 {
-       printlog("%3d  incoming INFORMATION information='%s'\n",
-               ea_endpoint->ep_serial,
-               param->information.number
-               );
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+       /* ignore information message without digit information */
+       if (!param->information.id[0])
+               return;
+
        e_overlap = 1;
 
        /* 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.number, e_ext.number, e_callerinfo.id);
+       if (e_dtmf) {
+               trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
+               end_trace();
                e_dtmf = 0;
        }
 
        /* if vbox_play is done, the information are just used as they come */
        if (e_action)
-       if (e_action->index == ACTION_VBOX_PLAY)
-       {
+       if (e_action->index == ACTION_VBOX_PLAY) {
                /* concat dialing string */
-               SCAT(e_dialinginfo.number, param->information.number);
+               SCAT(e_dialinginfo.id, param->information.id);
                process_dialing();
                return;
        }
 
        /* keypad when disconnect but in connected mode */
-       if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.number);
+       if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
                /* processing keypad function */
-               if (param->information.number[0] == '0')
-               {
+               if (param->information.id[0] == '0') {
                        hookflash();
                }
                return;
        }
 
        /* keypad when connected */
-       if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.number);
-               /* processing keypad function */
-               if (param->information.number[0] == '0')
-               {
-                       hookflash();
+       if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
+               if (e_ext.keypad || e_enablekeypad) {
+                       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 {
+                       if (e_ext.number[0])
+                               trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
+                       else
+                               trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
+                       end_trace();
                }
-               if (param->information.number[0])
-                       keypad_function(param->information.number[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);
+       if (e_state != EPOINT_STATE_IN_OVERLAP) {
+               if (e_ext.number[0])
+                       trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
+               else
+                       trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
+               end_trace();
                return;
        }
-       if (!param->information.number[0])
+       if (!param->information.id[0])
                return;
-       if (e_dialinginfo.number[0]=='\0' && !e_action)
-       {
+       if (e_dialinginfo.id[0]=='\0' && !e_action) {
                set_tone(portlist, "dialing");
        }
        if (e_action)
        if (e_action->index==ACTION_OUTDIAL
-        || e_action->index==ACTION_EXTERNAL)
-       {
+        || e_action->index==ACTION_EXTERNAL
+        || e_action->index==ACTION_REMOTE) {
                if (!e_extdialing)
                        set_tone(portlist, "dialing");
                else if (!e_extdialing[0])
                        set_tone(portlist, "dialing");
        }
        /* concat dialing string */
-       SCAT(e_dialinginfo.number, param->information.number);
+       SCAT(e_dialinginfo.id, param->information.id);
        process_dialing();
 }
 
 /* port MESSAGE_DTMF */
 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
 {
-       printlog("%3d  incoming DTMF digit='%c'\n",
-               ea_endpoint->ep_serial,
-               param->dtmf
-               );
        /* only if dtmf detection is enabled */
-       if (!e_dtmf)
-       {
-               PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
+       if (!e_dtmf) {
+               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
        /* if vbox_play is done, the dtmf digits are just used as they come */
        if (e_action)
-       if (e_action->index == ACTION_VBOX_PLAY)
-       {
+       if (e_action->index == ACTION_VBOX_PLAY) {
                /* concat dialing string */
-               if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
-               {
-                       e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
-                       e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
+               if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
+                       e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
+                       e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
                        process_dialing();
                }
                /* continue to process *X# sequences */
@@ -1893,34 +1647,27 @@ NOTE: vbox is now handled due to overlap state
 #endif
 
        /* check for *X# sequence */
-       if (e_state == EPOINT_STATE_CONNECT)
-       {
-               if (e_dtmf_time+3 < now)
-               {
+       if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
+               if (e_dtmf_time+3 < now) {
                        /* the last digit was too far in the past to be a sequence */
                        if (param->dtmf == '*')
                                /* only start is allowed in the sequence */
                                e_dtmf_last = '*';
                        else
                                e_dtmf_last = '\0';
-               } else
-               {
+               } else {
                        /* we have a sequence of digits, see what we got */
                        if (param->dtmf == '*')
                                e_dtmf_last = '*';
-                       else if (param->dtmf>='0' && param->dtmf<='9')
-                       {
+                       else if (param->dtmf>='0' && param->dtmf<='9') {
                                /* we need to have a star before we receive the digit of the sequence */
                                if (e_dtmf_last == '*')
                                        e_dtmf_last = param->dtmf;
-                       } else if (param->dtmf == '#')
-                       {
+                       } else if (param->dtmf == '#') {
                                /* the hash key */
-                               if (e_dtmf_last>='0' && e_dtmf_last<='9')
-                               {
+                               if (e_dtmf_last>='0' && e_dtmf_last<='9') {
                                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
-                                       if (e_dtmf_last == '0')
-                                       {
+                                       if (e_dtmf_last == '0') {
                                                hookflash();
                                                return;
                                        }
@@ -1942,20 +1689,16 @@ NOTE: vbox is now handled due to overlap state
        if (e_action->index==ACTION_PASSWORD
         || e_action->index==ACTION_PASSWORD_WRITE)
                goto password;
-       if (param->dtmf=='#') /* current digit is '#' */
-       {
+       if (param->dtmf=='#') { /* current digit is '#' */
                if (e_state==EPOINT_STATE_IN_DISCONNECT
-                || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
-               {
+                || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
                        hookflash();
                        return;
-               } else
-               {
+               } else {
                        e_dtmf_time = now;
                        e_dtmf_last = '#';
                }
-       } else
-       {
+       } else {
                password:
                e_dtmf_time = now;
                e_dtmf_last = '\0';
@@ -1963,17 +1706,14 @@ NOTE: vbox is now handled due to overlap state
        
 
        /* dialing using dtmf digit */
-       if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
-       {
-               if (e_dialinginfo.number[0]=='\0' && !e_action)
-               {
+       if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
+               if (e_dialinginfo.id[0]=='\0' && !e_action) {
                        set_tone(portlist, "dialing");
                }
                /* concat dialing string */
-               if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
-               {
-                       e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
-                       e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
+               if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
+                       e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
+                       e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
                        process_dialing();
                }
        }
@@ -1992,52 +1732,47 @@ void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, un
 /* port MESSAGE_OVERLAP */
 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
+
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
        /* signal to call tool */
        admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
 
-       printlog("%3d  incoming SETUP ACKNOWLEDGE\n",
-               ea_endpoint->ep_serial
-               );
-       if (e_dialing_queue[0] && portlist)
-       {
+       if (e_dialing_queue[0] && portlist) {
                /* send what we have not dialed yet, because we had no setup complete */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
-               SCPY(message->param.information.number, e_dialing_queue);
+               SCPY(message->param.information.id, e_dialing_queue);
                message->param.information.ntype = INFO_NTYPE_UNKNOWN;
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
                e_dialing_queue[0] = '\0';
        }
        /* check if pattern is available */
-       if (!ea_endpoint->ep_portlist->next && portlist->earlyb) /* one port_list relation and tones available */
-       {
+       if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
                /* indicate patterns */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
+               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_call_id, EPOINT_TO_CALL, 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 = 1;
                message_put(message);
-       } else
-       {
+       } else {
                /* indicate no patterns */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
                message_put(message);
 
                /* disconnect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                message_put(message);
        }
        new_state(EPOINT_STATE_OUT_OVERLAP);
-       /* if we are in a call */
-       if (ea_endpoint->ep_call_id)
-       { 
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
+       /* if we are in a join */
+       if (ea_endpoint->ep_join_id) { 
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
                memcpy(&message->param, param, sizeof(union parameter));
                message_put(message);
        }
@@ -2046,41 +1781,37 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type,
 /* port MESSAGE_PROCEEDING */
 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
+
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
        /* signal to call tool */
        admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
 
-       printlog("%3d  incoming PROCEEDING\n",
-               ea_endpoint->ep_serial
-               );
        e_state = EPOINT_STATE_OUT_PROCEEDING;
        /* check if pattern is availatle */
-       if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
-       {
+       if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
                /* indicate patterns */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
+               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_call_id, EPOINT_TO_CALL, 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 = 1;
                message_put(message);
-       } else
-       {
+       } else {
                /* indicate no patterns */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
                message_put(message);
 
                /* disconnect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                message_put(message);
        }
        /* if we are in a call */
-       if (ea_endpoint->ep_call_id)
-       { 
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
+       if (ea_endpoint->ep_join_id) { 
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
                memcpy(&message->param, param, sizeof(union parameter));
                message_put(message);
        }
@@ -2089,41 +1820,40 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ
 /* port MESSAGE_ALERTING */
 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
+
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
        /* signal to call tool */
        admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
+//#warning hack!!
+//     if (e_adminid)
+//             set_tone(portlist, "hold");
 
-       printlog("%3d  incoming ALERTING\n",
-               ea_endpoint->ep_serial
-               );
        new_state(EPOINT_STATE_OUT_ALERTING);
        /* check if pattern is available */
-       if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
-       {
+       if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
                /* indicate patterns */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
+               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_call_id, EPOINT_TO_CALL, 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 = 1;
                message_put(message);
-       } else
-       {
+       } else {
                /* indicate no patterns */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
                message_put(message);
 
                /* disconnect audio, if not already */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                message_put(message);
        }
        /* if we are in a call */
-       if (ea_endpoint->ep_call_id)
-       { 
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
+       if (ea_endpoint->ep_join_id) { 
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
                memcpy(&message->param, param, sizeof(union parameter));
                message_put(message);
        }
@@ -2132,71 +1862,67 @@ void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type,
 /* port MESSAGE_CONNECT */
 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
        char buffer[256];
-       unsigned long port_id = portlist->port_id;
+       unsigned int port_id = portlist->port_id;
        struct port_list *tportlist;
        class Port *port;
+       struct interface        *interface;
+
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
        /* signal to call tool */
-       admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
+       admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
 
        memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_connectinfo));
-       printlog("%3d  incoming CONNECT id='%s'%s\n",
-               ea_endpoint->ep_serial,
-               (e_connectinfo.intern[0])?e_connectinfo.intern:e_connectinfo.id,
-               (e_connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
-               );
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
-       while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
-       {
+       while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
                tportlist = ea_endpoint->ep_portlist;
                if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
                        tportlist = tportlist->next;
                if (tportlist->port_id == port_id)
-               {
-                       PERROR("EPOINT(%d) software error: this should not happen since the portlist list must not have two links to the same port - exitting.\n");
-                       exit(-1);
-               }
+                       FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
                message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = 26; /* non selected user clearing */
+               message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
                ea_endpoint->free_portlist(tportlist);
        }
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
 
        e_start = now;
 
-       /* screen by interface */
-       if (e_callerinfo.interface[0])
-       {
-               /* screen incoming caller id */
-               screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
+       /* screen incoming connected id */
+       interface = interface_first;
+       while(interface) {
+               if (!strcmp(e_connectinfo.interface, interface->name)) {
+                       break;
+               }
+               interface = interface->next;
        }
+       if (interface)
+               do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
 
        /* screen connected name */
        if (e_ext.name[0])
                SCPY(e_connectinfo.name, e_ext.name);
 
        /* add internal id to colp */
-       SCPY(e_connectinfo.intern, e_ext.number);
+       SCPY(e_connectinfo.extension, e_ext.number);
 
        /* we store the connected port number */
-       SCPY(e_extension_interface, e_connectinfo.interfaces);
+       SCPY(e_extension_interface, e_connectinfo.interface);
 
        /* for internal and am calls, we get the extension's id */
-       if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
-       {
+       if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
                SCPY(e_connectinfo.id, e_ext.callerid);
-               SCPY(e_connectinfo.intern, e_ext.number);
-               e_connectinfo.itype = INFO_ITYPE_INTERN;
+               SCPY(e_connectinfo.extension, e_ext.number);
+               e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
                e_connectinfo.ntype = e_ext.callerid_type;
                e_connectinfo.present = e_ext.callerid_present;
        }
-       if (portlist->port_type==PORT_TYPE_VBOX_OUT)
-       {
+       if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
                e_connectinfo.itype = INFO_ITYPE_VBOX;
                e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
        }
@@ -2204,46 +1930,41 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        new_state(EPOINT_STATE_CONNECT);
 
        /* set volume of rx and tx */
-       if (e_ext.txvol!=256 || e_ext.rxvol!=256)
-       {
+       if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
                message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
-               message->param.mISDNsignal.rxvol = e_ext.txvol;
-               message->param.mISDNsignal.txvol = e_ext.rxvol;
+               message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
+               message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
                message_put(message);
        }
 
        e_cfnr_call = e_cfnr_release = 0;
        if (e_ext.number[0])
                e_dtmf = 1; /* allow dtmf */
-//             if (call_countrelations(ea_endpoint->ep_call_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)
-               {
-                       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)
-                               {
-                                       SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.number, &e_connectinfo.ntype));
-                                       e_connectinfo.present = INFO_PRESENT_ALLOWED;
-                               }
+
+       /* 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.ntype = INFO_NTYPE_NOTPRESENT;
+               if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT || portlist->port_type==PORT_TYPE_GSM_OUT) { /* external extension answered */
+                       port = find_port_id(portlist->port_id);
+                       if (port) {
+                               SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
+                               e_connectinfo.present = INFO_PRESENT_ALLOWED;
                        }
                }
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
+       }
+
+       /* 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_type);
                memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
                message_put(message);
-       }
-       if (ea_endpoint->ep_call_id)
-       {
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 1;
                message_put(message);
-       } else if (!e_adminid)
-       {
+       } else if (!e_adminid) {
                /* callback */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
                SCPY(e_ext.number, e_cbcaller);
@@ -2251,8 +1972,7 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
 
                /* get extension's info about terminal */
-               if (!read_extension(&e_ext, e_ext.number))
-               {
+               if (!read_extension(&e_ext, e_ext.number)) {
                        /* extension doesn't exist */
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
                        message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
@@ -2263,73 +1983,65 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
 
                /* put prefix in front of e_cbdialing */
                SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
-               SCPY(e_dialinginfo.number, buffer);
-               e_dialinginfo.itype = INFO_ITYPE_EXTERN;
+               SCPY(e_dialinginfo.id, buffer);
+               e_dialinginfo.itype = INFO_ITYPE_ISDN;
                e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
 
                /* use caller id (or if exist: id_next_call) for this call */
                e_callerinfo.screen = INFO_SCREEN_NETWORK;
-               SCPY(e_callerinfo.intern, e_ext.number);
-               if (e_ext.id_next_call_present >= 0)
-               {
+               SCPY(e_callerinfo.extension, e_ext.number);
+               if (e_ext.id_next_call_present >= 0) {
                        SCPY(e_callerinfo.id, e_ext.id_next_call);
                        e_callerinfo.present = e_ext.id_next_call_present;
                        e_callerinfo.ntype = e_ext.id_next_call_type;
                        e_ext.id_next_call_present = -1;
                        /* extension is written */
                        write_extension(&e_ext, e_ext.number);
-               } else
-               {
+               } else {
                        SCPY(e_callerinfo.id, e_ext.callerid);
                        e_callerinfo.present = e_ext.callerid_present;
                        e_callerinfo.ntype = e_ext.callerid_type;
                }
+               e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
 
                e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
                e_dtmf = 1;
 
                /* check if caller id is NOT authenticated */
-               if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
-               {
+               if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
                        /* make call state to enter password */
                        new_state(EPOINT_STATE_IN_OVERLAP);
                        e_action = &action_password_write;
                        e_match_timeout = 0;
                        e_match_to_action = NULL;
-                       e_dialinginfo.number[0] = '\0';
-                       e_extdialing = strchr(e_dialinginfo.number, '\0');
+                       e_dialinginfo.id[0] = '\0';
+                       e_extdialing = strchr(e_dialinginfo.id, '\0');
                        e_password_timeout = now+20;
                        process_dialing();
-               } else
-               {
+               } else {
                        /* incoming call (callback) */
                        e_ruleset = ruleset_main;
                        if (e_ruleset)
                                e_rule = e_ruleset->rule_first;
                        e_action = NULL;
-                       e_extdialing = e_dialinginfo.number;
-                       if (e_dialinginfo.number[0])
-                       {
+                       e_extdialing = e_dialinginfo.id;
+                       if (e_dialinginfo.id[0]) {
                                set_tone(portlist, "dialing");
                                process_dialing();
-                       } else
-                       {
+                       } else {
                                set_tone(portlist, "dialpbx");
                        }
                }
-       } else /* testcall */
-       {
+       } else { /* testcall */
                set_tone(portlist, "hold");
        }
 
        /* start recording if enabled, not when answering machine answers */
-       if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
-       {
+       if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
                /* check if we are a terminal */
                if (e_ext.number[0] == '\0')
                        PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
-               else
-               {
+               else {
                        port = find_port_id(portlist->port_id);
                        if (port)
                                port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
@@ -2340,132 +2052,99 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message  *message;
+       struct lcr_msg  *message;
        char            buffer[256];
-       unsigned long   port_id = portlist->port_id;
+       unsigned int    port_id = portlist->port_id;
        int             cause,
                        location;
 
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
        /* signal to call tool */
        admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
 
-       printlog("%3d  incoming %s cause='%d' (%s) location='%d' (%s)\n",
-               ea_endpoint->ep_serial,
-               (message_type==MESSAGE_DISCONNECT)?"DISCONNECT":"RELEASE",
-               param->disconnectinfo.cause,
-               (param->disconnectinfo.cause>0 && param->disconnectinfo.cause<128)?isdn_cause[param->disconnectinfo.cause].english:"-",
-               param->disconnectinfo.location,
-               (param->disconnectinfo.location>=0 && param->disconnectinfo.location<16)?isdn_location[param->disconnectinfo.location].english:"-"
-               );
-
 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
-       if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
-       {
+       if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
                return;
        }
 
        /* collect cause */
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current multipoint cause %d location %d, received cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
-       if (param->disconnectinfo.cause == CAUSE_REJECTED) /* call rejected */
-       {
-               e_multipoint_cause = CAUSE_REJECTED;
-               e_multipoint_location = param->disconnectinfo.location;
-       } else
-       if (param->disconnectinfo.cause==CAUSE_NORMAL && e_multipoint_cause!=CAUSE_REJECTED) /* reject via hangup */
-       {
-               e_multipoint_cause = CAUSE_NORMAL;
-               e_multipoint_location = param->disconnectinfo.location;
-       } else
-       if (param->disconnectinfo.cause==CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* busy */
-       {
-               e_multipoint_cause = CAUSE_BUSY;
-               e_multipoint_location = param->disconnectinfo.location;
-       } else
-       if (param->disconnectinfo.cause==CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* no L1 */
-       {
-               e_multipoint_cause = CAUSE_OUTOFORDER;
-               e_multipoint_location = param->disconnectinfo.location;
-       } else
-       if (param->disconnectinfo.cause!=CAUSE_NOUSER && e_multipoint_cause!=CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* anything but not 18 */
-       {
-               e_multipoint_cause = param->disconnectinfo.cause;
-               e_multipoint_location = param->disconnectinfo.location;
-       }
+       collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
 
        /* check if we have more than one portlist relation and we just ignore the disconnect */
-       if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
-       {
+       if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
                portlist = ea_endpoint->ep_portlist;
-               while(portlist)
-               {
+               while(portlist) {
                        if (portlist->port_id == port_id)
                                break;
                        portlist = portlist->next;
                }
                if (!portlist)
-               {
-                       PERROR("EPOINT(%d) software error: no portlist related to the calling port.\n", ea_endpoint->ep_serial);
-                       exit(-1);
-               }
-               if (message_type != MESSAGE_RELEASE)
-               {
+                       FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
+               if (message_type != MESSAGE_RELEASE) {
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
                        message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
                        message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                }
                ea_endpoint->free_portlist(portlist);
                return; /* one relation removed */ 
        }
-       if (e_multipoint_cause)
-       {
-               cause = e_multipoint_cause;
-               location = e_multipoint_location;
-       } else
-       {
+       if (e_state == EPOINT_STATE_CONNECT) {
+               /* use cause from port after connect */
                cause = param->disconnectinfo.cause;
                location = param->disconnectinfo.location;
+       } else {
+               /* use multipoint cause if no connect yet */
+               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;
 
        /* process hangup */
-       process_hangup(e_call_cause, e_call_location);
+       process_hangup(e_join_cause, e_join_location);
        e_multipoint_cause = 0;
-       e_multipoint_location = LOCATION_PRIVATE_LOCAL;
+       e_multipoint_location = 0;
 
-       /* tone to disconnected end */
-       SPRINT(buffer, "cause_%02x", cause);
-       if (ea_endpoint->ep_portlist)
-               set_tone(ea_endpoint->ep_portlist, buffer);
+       if (message_type == MESSAGE_DISCONNECT) {
+               /* tone to disconnected end */
+               SPRINT(buffer, "cause_%02x", cause);
+               if (ea_endpoint->ep_portlist)
+                       set_tone(ea_endpoint->ep_portlist, buffer);
 
-       new_state(EPOINT_STATE_IN_DISCONNECT);
-       if (ea_endpoint->ep_call_id)
-       {
+               new_state(EPOINT_STATE_IN_DISCONNECT);
+       }
+
+       if (ea_endpoint->ep_join_id) {
                int haspatterns = 0;
                /* check if pattern is available */
                if (ea_endpoint->ep_portlist)
-               if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->earlyb)
-#warning wie ist das bei einem asterisk, gibts auch tones?
-               if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: 
+               if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
+               if (joinpbx_countrelations(ea_endpoint->ep_join_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: asterisk always counts two, since it is a point to point call 
                 && message_type != MESSAGE_RELEASE) // if we release, we are done
                        haspatterns = 1;
-               if (haspatterns)
-               {
+               if (haspatterns) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
                        /* indicate patterns */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
+                       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_call_id, EPOINT_TO_CALL, 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 = 1;
                        message_put(message);
                        /* send disconnect */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
                        memcpy(&message->param, param, sizeof(union parameter));
                        message_put(message);
                        /* disable encryption if disconnected */
@@ -2473,11 +2152,12 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
                        if (e_crypt_state)
                                cryptman_message(CI_DISCONNECT_IND, NULL, 0);
                        return;
-               } else
-               {
+               } else {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
                }
        }
+       if (message_type == MESSAGE_RELEASE)
+               ea_endpoint->free_portlist(portlist);
        release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
        return; /* must exit here */
 }
@@ -2487,48 +2167,64 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
 {
        char cause[16];
 
-       printlog("%3d  incoming TIMEOUT\n",
-               ea_endpoint->ep_serial
-               );
+       trace_header("TIMEOUT", DIRECTION_IN);
        message_type = MESSAGE_DISCONNECT;
-       switch (param->state)
-       {
+       switch (param->state) {
                case PORT_STATE_OUT_SETUP:
                case PORT_STATE_OUT_OVERLAP:
+               add_trace("state", NULL, "outgoing setup/dialing");
+               end_trace();
                /* no user responding */
                release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
                return; /* must exit here */
 
                case PORT_STATE_IN_SETUP:
                case PORT_STATE_IN_OVERLAP:
+               add_trace("state", NULL, "incoming setup/dialing");
                param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                break;
 
                case PORT_STATE_OUT_PROCEEDING:
+               add_trace("state", NULL, "outgoing proceeding");
+               end_trace();
                param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
                return; /* must exit here */
 
                case PORT_STATE_IN_PROCEEDING:
+               add_trace("state", NULL, "incoming proceeding");
                param->disconnectinfo.cause = CAUSE_NOUSER;
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
                break;
 
                case PORT_STATE_OUT_ALERTING:
+               add_trace("state", NULL, "outgoing alerting");
+               end_trace();
                param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
                return; /* must exit here */
 
+               case PORT_STATE_CONNECT:
+               add_trace("state", NULL, "connect");
+               end_trace();
+               param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
+               param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+               return; /* must exit here */
+
                case PORT_STATE_IN_ALERTING:
+               add_trace("state", NULL, "incoming alerting");
                param->disconnectinfo.cause = CAUSE_NOANSWER;
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                break;
 
                case PORT_STATE_IN_DISCONNECT:
                case PORT_STATE_OUT_DISCONNECT:
+               add_trace("state", NULL, "disconnect");
+               end_trace();
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
                release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
                return; /* must exit here */
@@ -2537,44 +2233,43 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                param->disconnectinfo.cause = 31; /* normal unspecified */
                param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
        }
+       end_trace();
        /* release call, disconnect isdn */
-       e_call_pattern = 0;
+       e_join_pattern = 0;
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
        SCPY(e_tone, cause);
-       while(portlist)
-       {
+       while(portlist) {
                set_tone(portlist, cause);
                message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
                portlist = portlist->next;
        }
-       release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
+       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
 }
 
 /* port MESSAGE_NOTIFY */
 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
-       char *logtext = "";
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+       struct lcr_msg *message;
+       const char *logtext = "";
        char buffer[64];
 
        /* signal to call tool */
-       admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
-       if (param->notifyinfo.notify)
-       {
+       admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype, options.national, options.international), 0, 0, param->notifyinfo.notify);
+       if (param->notifyinfo.notify) {
                e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
        }
 
        /* if we get notification from stack, local shows if we disabled/enabled audio stream */
-       if (param->notifyinfo.local) switch(param->notifyinfo.notify)
-       {
+       if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
                case INFO_NOTIFY_REMOTE_HOLD:
                case INFO_NOTIFY_USER_SUSPENDED:
                /* tell call about it */
-               if (ea_endpoint->ep_call_id)
-               {
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_HOLD;
+               if (ea_endpoint->ep_join_id) {
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = 0;
                        message_put(message);
                }
                break;
@@ -2582,32 +2277,29 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
                case INFO_NOTIFY_REMOTE_RETRIEVAL:
                case INFO_NOTIFY_USER_RESUMED:
                /* set volume of rx and tx */
-               if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
-               if (e_ext.txvol!=256 || e_ext.rxvol!=256)
-               if (portlist)
-               {
+               if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
+               if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
+               if (portlist) {
                        message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
                        message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
-                       message->param.mISDNsignal.rxvol = e_ext.txvol;
-                       message->param.mISDNsignal.txvol = e_ext.rxvol;
+                       message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
+                       message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
                        message_put(message);
                }
                /* set current tone */
                if (portlist)
                        set_tone(portlist, e_tone);
                /* tell call about it */
-               if (ea_endpoint->ep_call_id)
-               {
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+               if (ea_endpoint->ep_join_id) {
+                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+                       message->param.audiopath = 1;
                        message_put(message);
                }
                break;
        }
 
        /* get name of notify */
-       switch(param->notifyinfo.notify)
-       {
+       switch(param->notifyinfo.notify) {
                case 0x00:
                logtext = "NULL";
                break;
@@ -2681,21 +2373,14 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
                logtext = "CALL_IS_DIVERTING";
                break;
                default:
-               SPRINT(buffer, "indicator=%d", param->notifyinfo.notify - 0x80);
+               SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
                logtext = buffer;
 
        }
-       printlog("%3d  incoming NOTIFY notify='%s' id='%s'%s\n",
-               ea_endpoint->ep_serial,
-               logtext,
-               param->notifyinfo.id,
-               (param->notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
-       );
 
        /* notify call if available */
-       if (ea_endpoint->ep_call_id)
-       {
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOTIFY);
+       if (ea_endpoint->ep_join_id) {
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
                memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
                message_put(message);
        }
@@ -2705,14 +2390,11 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
 /* port MESSAGE_FACILITY */
 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
-       printlog("%3d  incoming FACILITY len='%d'\n",
-               ea_endpoint->ep_serial,
-               param->facilityinfo.len
-               );
+       struct lcr_msg *message;
 
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_FACILITY);
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
        memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
        message_put(message);
 }
@@ -2721,9 +2403,8 @@ void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type,
 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
 {
-       printlog("%3d  incoming SUSPEND\n",
-               ea_endpoint->ep_serial
-               );
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
        /* epoint is now parked */
        ea_endpoint->ep_park = 1;
        memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
@@ -2737,9 +2418,8 @@ void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type,
 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
 {
-       printlog("%3d  incoming RESUME\n",
-               ea_endpoint->ep_serial
-               );
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
        /* epoint is now resumed */
        ea_endpoint->ep_park = 0;
 
@@ -2748,58 +2428,41 @@ void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, u
 
 /* port sends message to the endpoint
  */
-void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
+void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
 {
        struct port_list *portlist;
-       struct message *message;
-       class Port *port;
 
        portlist = ea_endpoint->ep_portlist;
-       while(portlist)
-       {
+       while(portlist) {
                if (port_id == portlist->port_id)
                        break;
                portlist = portlist->next;
        }
-       if (!portlist)
-       {
+       if (!portlist) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) warning: port is not related to this endpoint. This may happen, if port has been released after the message was created.\n", ea_endpoint->ep_serial);
                return;
        }
 
 //     PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
-       switch(message_type)
-       {
+       switch(message_type) {
                case MESSAGE_DATA: /* data from port */
-               /* send back to source for recording */
-               if (port_id)
-               {
-                       message = message_create(ea_endpoint->ep_serial, port_id, EPOINT_TO_PORT, message_type);
-                       memcpy(&message->param, param, sizeof(union parameter));
-                       message_put(message);
-               }
-
                /* check if there is a call */
-               if (!ea_endpoint->ep_call_id)
+               if (!ea_endpoint->ep_join_id)
                        break;
                /* continue if only one portlist */
                if (ea_endpoint->ep_portlist->next != NULL)
                        break;
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
-               memcpy(&message->param, param, sizeof(union parameter));
-               message_put(message);
+               /* forward message */
+               message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);  
                break;
 
                case MESSAGE_TONE_EOF: /* tone is end of file */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
-               if (e_action)
-               {
-                       if (e_action->index == ACTION_VBOX_PLAY)
-                       {
+               if (e_action) {
+                       if (e_action->index == ACTION_VBOX_PLAY) {
                                vbox_message_eof();
                        }
-                       if (e_action->index == ACTION_EFI)
-                       {
+                       if (e_action->index == ACTION_EFI) {
                                efi_message_eof();
                        }
                }
@@ -2808,8 +2471,7 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                case MESSAGE_TONE_COUNTER: /* counter info received */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received counter information: %d / %d seconds after start of tone.\n", ea_endpoint->ep_serial, param->counter.current, param->counter.max);
                if (e_action)
-               if (e_action->index == ACTION_VBOX_PLAY)
-               {
+               if (e_action->index == ACTION_VBOX_PLAY) {
                        e_vbox_counter = param->counter.current;
                        if (param->counter.max >= 0)
                                e_vbox_counter_max = param->counter.max;
@@ -2818,9 +2480,8 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
 
                /* PORT sends SETUP message */
                case MESSAGE_SETUP:
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.number);
-               if (e_state!=EPOINT_STATE_IDLE)
-               {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
+               if (e_state!=EPOINT_STATE_IDLE) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
                        break;
                }
@@ -2829,7 +2490,7 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
 
                /* PORT sends INFORMATION message */
                case MESSAGE_INFORMATION: /* additional digits received */
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.number, e_ext.number, e_callerinfo.id);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
                port_information(portlist, message_type, param);
                break;
 
@@ -2854,8 +2515,7 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                /* PORT sends MORE message */
                case MESSAGE_OVERLAP:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
-               if (e_state != EPOINT_STATE_OUT_SETUP)
-               {
+               if (e_state != EPOINT_STATE_OUT_SETUP) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
                        break;
                }
@@ -2866,8 +2526,7 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                case MESSAGE_PROCEEDING: /* port is proceeding */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_OUT_SETUP
-                && e_state!=EPOINT_STATE_OUT_OVERLAP)
-               {
+                && e_state!=EPOINT_STATE_OUT_OVERLAP) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
                        break;
                }
@@ -2879,8 +2538,7 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_OUT_SETUP
                 && e_state!=EPOINT_STATE_OUT_OVERLAP
-                && e_state!=EPOINT_STATE_OUT_PROCEEDING)
-               {
+                && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
                        break;
                }
@@ -2893,8 +2551,7 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                if (e_state!=EPOINT_STATE_OUT_SETUP
                 && e_state!=EPOINT_STATE_OUT_OVERLAP
                 && e_state!=EPOINT_STATE_OUT_PROCEEDING
-                && e_state!=EPOINT_STATE_OUT_ALERTING)
-               {
+                && e_state!=EPOINT_STATE_OUT_ALERTING) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
                        break;
                }
@@ -2938,21 +2595,32 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                port_resume(portlist, message_type, param);
                break;
 
+#if 0
+               kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
+               /* 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);
+               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_type);
        }
 
        /* Note: this endpoint may be destroyed, so we MUST return */
 }
 
 
-/* messages from port
+/* messages from join
  */
-/* call MESSAGE_CRYPT */
-void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_CRYPT */
+void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
 {
-       switch(param->crypt.type)
-       {
+       switch(param->crypt.type) {
                /* message from remote port to "crypt manager" */
                case CU_ACTK_REQ:           /* activate key-exchange */
                case CU_ACTS_REQ:            /* activate shared key */
@@ -2977,123 +2645,120 @@ void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, un
        }
 }
 
-/* call MESSAGE_INFORMATION */
-void EndpointAppPBX::call_information(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_INFORMATION */
+void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
        e_overlap = 1;
 
-       while(portlist)
-       {
+       while(portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
                memcpy(&message->param.information, &param->information, sizeof(struct dialing_info));
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                portlist = portlist->next;
        }
 }
 
-/* call MESSAGE_FACILITY */
-void EndpointAppPBX::call_facility(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_FACILITY */
+void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
-       if (!e_ext.facility)
-       {
+       if (!e_ext.facility && e_ext.number[0]) {
                return;
        }
 
-       while(portlist)
-       {
+       while(portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
                memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                portlist = portlist->next;
        }
 }
 
-/* call MESSAGE_MORE */
-void EndpointAppPBX::call_overlap(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_MORE */
+void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
        new_state(EPOINT_STATE_IN_OVERLAP);
        
        /* own dialtone */
-       if (e_call_pattern && e_ext.own_setup)
-       {
+       if (e_join_pattern && e_ext.own_setup) {
                /* disconnect audio */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                message_put(message);
        }
-       if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
-       {
-                       set_tone(portlist, "dialtone");
+       if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
+                       if (e_dialinginfo.id[0])
+                               set_tone(portlist, "dialing");
+                       else
+                               set_tone(portlist, "dialtone");
                        return;
        }
-       if (e_ext.number[0])
-               set_tone(portlist, "dialpbx");
-       else
-               set_tone(portlist, "dialtone");
+       if (e_dialinginfo.id[0]) {
+               set_tone(portlist, "dialing");
+       } else {
+               if (e_ext.number[0])
+                       set_tone(portlist, "dialpbx");
+               else
+                       set_tone(portlist, "dialtone");
+       }
 }
 
-/* call MESSAGE_PROCEEDING */
-void EndpointAppPBX::call_proceeding(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_PROCEEDING */
+void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
        new_state(EPOINT_STATE_IN_PROCEEDING);
 
        /* own proceeding tone */
-       if (e_call_pattern)
-       {
+       if (e_join_pattern) {
                /* connect / disconnect audio */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                else
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+                       message->param.audiopath = 1;
                message_put(message);
        }
-//                     UCPY(e_call_tone, "proceeding");
-       if (portlist)
-       {
+//                     UCPY(e_join_tone, "proceeding");
+       if (portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        }
        set_tone(portlist, "proceeding");
 }
 
-/* call MESSAGE_ALERTING */
-void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_ALERTING */
+void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
        new_state(EPOINT_STATE_IN_ALERTING);
 
        /* own alerting tone */
-       if (e_call_pattern)
-       {
+       if (e_join_pattern) {
                /* connect / disconnect audio */
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                else
-                       message->param.channel = CHANNEL_STATE_CONNECT;
+                       message->param.audiopath = 1;
                message_put(message);
        }
-       if (portlist)
-       {
+       if (portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        }
-       if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
-       {
+       if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
                set_tone(portlist, "ringing");
                return;
        }
@@ -3101,72 +2766,68 @@ void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type,
                set_tone(portlist, "ringpbx");
        else
                set_tone(portlist, "ringing");
+
+       if (e_ext.number[0])
+               e_dtmf = 1; /* allow dtmf */
 }
 
-/* call MESSAGE_CONNECT */
-void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_CONNECT */
+void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
        new_state(EPOINT_STATE_CONNECT);
-//                     UCPY(e_call_tone, "");
+//                     UCPY(e_join_tone, "");
+//                     
        if (e_ext.number[0])
                e_dtmf = 1; /* allow dtmf */
+
        e_powerdialing = 0;
        memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_callerinfo));
-       if(portlist)
-       {
+       if(portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
                memcpy(&message->param, param, sizeof(union parameter));
-               /* screen by interface */
-               if (e_connectinfo.interface[0])
-               {
-                       /* screen incoming caller id */
-                       screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
-               }
-               memcpy(&message->param.connnectinfo, e_connectinfo);
 
                /* screen clip if prefix is required */
-               if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
-               {
+               if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
                        SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
-                       SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
+                       SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
                        message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
                }
 
                /* use internal caller id */
-               if (e_ext.number[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
-               {
-                       SCPY(message->param.connectinfo.id, e_connectinfo.intern);
+               if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
+                       SCPY(message->param.connectinfo.id, e_connectinfo.extension);
                        message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
                }
 
                /* handle restricted caller ids */
-               apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name);
+               apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
                /* display callerid if desired for extension */
-               SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name));
+               SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
 
                /* use conp, if enabld */
-               if (!e_ext.centrex)
-                       message->param.connectinfo.name[0] = '\0';
+//             if (!e_ext.centrex)
+//                     message->param.connectinfo.name[0] = '\0';
 
                /* send connect */
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
        }
        set_tone(portlist, NULL);
-       e_call_pattern = 0;
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
-       message->param.channel = CHANNEL_STATE_CONNECT;
+       e_join_pattern = 0;
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+       message->param.audiopath = 1;
        message_put(message);
        e_start = now;
 }
 
-/* call MESSAGE_DISCONNECT MESSAGE_RELEASE */
-void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
+void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
 {
        char cause[16];
-       struct message *message;
+       struct lcr_msg *message;
+       struct port_list *portlist = NULL;
 
 
        /* be sure that we are active */
@@ -3174,46 +2835,41 @@ void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int mes
        e_tx_state = NOTIFY_STATE_ACTIVE;
 
        /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
-       if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
-       {
-               release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
+       if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
 
                /* set time for power dialing */
                e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
                e_powercount++;
 
                /* set redial tone */
-               if (ea_endpoint->ep_portlist)
-               {
-                       e_call_pattern = 0;
+               if (ea_endpoint->ep_portlist) {
+                       e_join_pattern = 0;
                }
                set_tone(ea_endpoint->ep_portlist, "redial");
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (int)e_powerdelay);
                /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
-               if (e_state==EPOINT_STATE_IN_OVERLAP)
-               {
+               if (e_state==EPOINT_STATE_IN_OVERLAP) {
                        new_state(EPOINT_STATE_IN_PROCEEDING);
-                       if (portlist)
-                       {
-                               message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
+                       if (ea_endpoint->ep_portlist) {
+                               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
                                message_put(message);
-                               logmessage(message);
+                               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"); */
                }
                /* send display of powerdialing */
-               if (e_ext.display_dialing)
-               {
-                       while (portlist)
-                       {
+               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);
                                if (e_powerlimit)
                                        SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
                                else
                                        SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
                                message_put(message);
-                               logmessage(message);
+                               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                                portlist = portlist->next;
                        }
                }
@@ -3228,80 +2884,73 @@ void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int mes
          && e_state!=EPOINT_STATE_IN_OVERLAP
          && e_state!=EPOINT_STATE_IN_PROCEEDING
          && e_state!=EPOINT_STATE_IN_ALERTING)
-        || !ea_endpoint->ep_portlist) /* or no port */
-       {
+        || !ea_endpoint->ep_portlist) { /* or no port */
                process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
-               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, call, port */
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
                return; /* must exit here */
        }
        /* save cause */
-       if (!e_call_cause)
-       {
-               e_call_cause = param->disconnectinfo.cause;
-               e_call_location = param->disconnectinfo.location;
+       if (!e_join_cause) {
+               e_join_cause = param->disconnectinfo.cause;
+               e_join_location = param->disconnectinfo.location;
        }
 
        /* on release we need the audio again! */
-       if (message_type == MESSAGE_RELEASE)
-       {
-               e_call_pattern = 0;
-               ea_endpoint->ep_call_id = 0;
+       if (message_type == MESSAGE_RELEASE) {
+               e_join_pattern = 0;
+               ea_endpoint->ep_join_id = 0;
        }
        /* disconnect and select tone */
        new_state(EPOINT_STATE_OUT_DISCONNECT);
        SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
-       /* if own_cause, we must release the call */
+       /* if own_cause, we must release the join */
        if (e_ext.own_cause /* own cause */
-        || !e_call_pattern) /* no patterns */
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_call_pattern);
+        || !e_join_pattern) { /* no patterns */
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_join_pattern);
                if (message_type != MESSAGE_RELEASE)
-                       release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
-               e_call_pattern = 0;
-       } else /* else we enable audio */
-       {
-               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
-               message->param.channel = CHANNEL_STATE_CONNECT;
+                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+               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_AUDIOPATH);
+               message->param.audiopath = 1;
                message_put(message);
        }
        /* send disconnect message */
        SCPY(e_tone, cause);
-       while(portlist)
-       {
+       portlist = ea_endpoint->ep_portlist;
+       while(portlist) {
                set_tone(portlist, cause);
                message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
                portlist = portlist->next;
        }
 }
 
-/* call MESSAGE_SETUP */
-void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_SETUP */
+void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
+//     struct interface        *interface;
 
        /* if we already in setup state, we just update the dialing with new digits */
        if (e_state == EPOINT_STATE_OUT_SETUP
-        || e_state == EPOINT_STATE_OUT_OVERLAP)
-       {
+        || e_state == EPOINT_STATE_OUT_OVERLAP) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
                /* if digits changed, what we have already dialed */
-               if (!!strncmp(e_dialinginfo.number,param->setup.dialinginfo.number,strlen(e_dialinginfo.number)))
-               {
+               if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have dialed digits which have been changed or we have a new multidial, so we must redial.\n", ea_endpoint->ep_serial);
                        /* release all ports */
-                       while((portlist = ea_endpoint->ep_portlist))
-                       {
+                       while((portlist = ea_endpoint->ep_portlist)) {
                                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
                                message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
                                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                                message_put(message);
-                               logmessage(message);
+                               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                                ea_endpoint->free_portlist(portlist);
                        }
 
                        /* disconnect audio */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                        message_put(message);
 
                        /* get dialing info */
@@ -3316,54 +2965,46 @@ void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, un
                        return;
                }
                /* if we have a pending redial, so we just adjust the dialing number */
-               if (e_redial)
-               {
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.number);
+               if (e_redial) {
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
                        memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
                        return;
                }
-               if (!ea_endpoint->ep_portlist)
-               {
+               if (!ea_endpoint->ep_portlist) {
                        PERROR("ERROR: overlap dialing to a NULL port relation\n");
                }
-               if (ea_endpoint->ep_portlist->next)
-               {
+               if (ea_endpoint->ep_portlist->next) {
                        PERROR("ERROR: overlap dialing to a port_list port relation\n");
                }
-               if (e_state == EPOINT_STATE_OUT_SETUP)
-               {
+               if (e_state == EPOINT_STATE_OUT_SETUP) {
                        /* queue digits */
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) digits '%s' are queued because we didn't receive a setup acknowledge.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.number);
-                       SCAT(e_dialing_queue, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) digits '%s' are queued because we didn't receive a setup acknowledge.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
+                       SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
                        
-               } else
-               {
+               } else {
                        /* get what we have not dialed yet */
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.number, param->setup.dialinginfo.number, param->setup.dialinginfo.number+strlen(e_dialinginfo.number));
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.id+strlen(e_dialinginfo.id));
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
-                       SCPY(message->param.information.number, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
+                       SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
                        message->param.information.ntype = INFO_NTYPE_UNKNOWN;
                        message_put(message);
-                       logmessage(message);
+                       logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
                }
                /* always store what we have dialed or queued */
                memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
                
                return;
        }
-       if (e_state != EPOINT_STATE_IDLE)
-       {
+       if (e_state != EPOINT_STATE_IDLE) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
                return;
        }
        /* if an internal extension is dialed, copy that number */
-       if (param->setup.dialinginfo.itype==INFO_ITYPE_INTERN || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
-               SCPY(e_ext.number, param->setup.dialinginfo.number);
+       if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
+               SCPY(e_ext.number, param->setup.dialinginfo.id);
        /* if an internal extension is dialed, get extension's info about caller */
-       if (e_ext.number[0]) 
-       {
-               if (!read_extension(&e_ext, e_ext.number))
-               {
+       if (e_ext.number[0]) {
+               if (!read_extension(&e_ext, e_ext.number)) {
                        e_ext.number[0] = '\0';
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
                }
@@ -3374,16 +3015,8 @@ void EndpointAppPBX::call_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));
 
-       /* screen by interface */
-       if (e_callerinfo.interface[0])
-       {
-               /* screen incoming caller id */
-               screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
-       }
-
        /* process (voice over) data calls */
-       if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
-       {
+       if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
                memset(&e_capainfo, 0, sizeof(e_capainfo));
                e_capainfo.bearer_capa = INFO_BC_AUDIO;
@@ -3396,13 +3029,12 @@ void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, un
        out_setup();
 }
 
-/* call MESSAGE_mISDNSIGNAL */
-void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_mISDNSIGNAL */
+void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
-       while(portlist)
-       {
+       while(portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
                memcpy(&message->param, param, sizeof(union parameter));
                message_put(message);
@@ -3410,38 +3042,34 @@ void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_ty
        }
 }
 
-/* call MESSAGE_NOTIFY */
-void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, union parameter *param)
+/* join MESSAGE_NOTIFY */
+void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
        int new_state;
 
-       if (param->notifyinfo.notify)
-       {
+       if (param->notifyinfo.notify) {
                new_state = track_notify(e_tx_state, param->notifyinfo.notify);
 //             /* if notification was generated locally, we turn hold music on/off */ 
 //             if (param->notifyinfo.local)
 // NOTE: we always assume that we send hold music on suspension of call, because we don't track if audio is available or not (we assume that we always have no audio, to make it easier)
                {
-                       if (e_hold)
-                       {
+                       if (e_hold) {
                                /* unhold if */
-                               if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
-                               {
-                                       while(portlist)
-                                       {
-                                               set_tone(portlist, "");
-                                               portlist = portlist->next;
+                               if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
+                                       if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
+                                               while(portlist) {
+                                                       set_tone(portlist, "");
+                                                       portlist = portlist->next;
+                                               }
                                        }
                                        portlist = ea_endpoint->ep_portlist;
                                        e_hold = 0;
                                }
                        } else {
                                /* hold if */
-                               if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
-                               {
-                                       while(portlist)
-                                       {
+                               if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
+                                       while(portlist) {
                                                set_tone(portlist, "hold");
                                                portlist = portlist->next;
                                        }
@@ -3455,205 +3083,218 @@ void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, u
        }
 
        /* notify port(s) about it */
-       while(portlist)
-       {
+       while(portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
                memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
                /* handle restricted caller ids */
-               apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, NULL, message->param.notifyinfo.voip, message->param.notifyinfo.intern, 0);
+               apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
                /* display callerid if desired for extension */
-               SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.voip, message->param.notifyinfo.intern, NULL));
+               SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL));
                message_put(message);
-               logmessage(message);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                portlist = portlist->next;
        }
 }
 
-/* call sends messages to the endpoint
+/* JOIN sends messages to the endpoint
  */
-void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, union parameter *param)
+void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
 {
        struct port_list *portlist;
-       struct message *message;
+       struct lcr_msg *message;
 
-       if (!call_id)
-       {
-               PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
+       if (!join_id) {
+               PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
                return;
        }
 
        portlist = ea_endpoint->ep_portlist;
 
        /* send MESSAGE_DATA to port */
-       if (call_id == ea_endpoint->ep_call_id)
-       {
-               if (message_type == MESSAGE_DATA)
-               {
+       if (message_type == MESSAGE_DATA) {
+               if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
                        /* skip if no port relation */
                        if (!portlist)
                                return;
                        /* skip if more than one port relation */
                        if (portlist->next)
                                return;
-                       /* send audio data to port */
-                       message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DATA);
-                       memcpy(&message->param, param, sizeof(union parameter));
-                       message_put(message);
+                       /* forward audio data to port */
+                       message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
                        return;
                }
        }
 
-//     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);
-       switch(message_type)
-       {
-               /* CALL SENDS CRYPT message */
+//     PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
+       switch(message_type) {
+               /* JOIN SENDS TONE message */
+               case MESSAGE_TONE:
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received tone message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->tone.name);
+               set_tone(portlist, param->tone.name);
+               break;
+
+               /* 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);
-               call_crypt(portlist, message_type, param);
+               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.number);
-               call_information(portlist, message_type, param);
+               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);
-               call_facility(portlist, message_type, param);
+               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);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info required'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_SETUP
-                && e_state!=EPOINT_STATE_IN_OVERLAP)
-               {
+                && e_state!=EPOINT_STATE_IN_OVERLAP) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
                        break;
                }
-               call_overlap(portlist, message_type, param);
+               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)
-               {
+               if(e_state!=EPOINT_STATE_IN_OVERLAP) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
                        break;
                }
-               call_proceeding(portlist, message_type, param);
+               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
-                && e_state!=EPOINT_STATE_IN_PROCEEDING)
-               {
+                && e_state!=EPOINT_STATE_IN_PROCEEDING) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
                        break;
                }
-               call_alerting(portlist, message_type, param);
+               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
                 && e_state!=EPOINT_STATE_IN_PROCEEDING
-                && e_state!=EPOINT_STATE_IN_ALERTING)
-               {
+                && e_state!=EPOINT_STATE_IN_ALERTING) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
                        break;
                }
-               call_connect(portlist, message_type, param);
+               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);
-               call_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.intern, param->setup.callerinfo.id, param->setup.dialinginfo.number, param->setup.dialinginfo.itype);
-               call_setup(portlist, message_type, param);
-               return;
+               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);
                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);
-               call_mISDNsignal(portlist, message_type, param);
+               join_mISDNsignal(portlist, message_type, param);
                break;
 
-               /* CALL has pattern available */
+#if 0
+               kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
+               /* JOIN requests bchannel */
+               case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
+               /* only one port is expected to be connected to bchannel */
+               if (!portlist)
+                       break;
+               if (portlist->next)
+                       break;
+               e_join_pattern = 1;
+               SCPY(e_tone, "");
+               set_tone(portlist, NULL);
+               message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
+               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+               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_call_pattern)
-               {
+               if (!e_join_pattern) {
                        PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
-                       e_call_pattern = 1;
+                       e_join_pattern = 1;
                        SCPY(e_tone, "");
-                       while(portlist)
-                       {
+                       while(portlist) {
                                set_tone(portlist, NULL);
                                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_call_id, EPOINT_TO_CALL, 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 = 1;
                        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_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO);
-//                     message->param.channel = 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_call_pattern)
-               {
+               if (e_join_pattern) {
                        PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
-                       e_call_pattern = 0;
+                       e_join_pattern = 0;
                        /* disconnect our audio tx and rx */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 0;
                        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_call_id, EPOINT_TO_CALL, 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);
-               call_notify(portlist, message_type, param);
+               join_notify(portlist, message_type, param);
+               break;
+
+               /* JOIN wants keypad / dtmf */
+               case MESSAGE_ENABLEKEYPAD:
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received keypad enable request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               e_enablekeypad = 1;
+               e_dtmf = 1;
+               trace_header("ENABLE KEYPAD", DIRECTION_NONE);
+               end_trace();
                break;
 
                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);
+               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_type);
        }
 }
 
 
-/* pick_call will connect the first incoming call found. the endpoint
+/* pick_join will connect the first incoming call found. the endpoint
  * will receivce a MESSAGE_CONNECT.
  */
 int match_list(char *list, char *item)
@@ -3664,13 +3305,11 @@ int match_list(char *list, char *item)
        if (!list)
                return(1);
 
-       while(42)
-       {
+       while(42) {
                /* eliminate white spaces */
                while (*list <= ' ')
                        list++;
-               if (*list == ',')
-               {
+               if (*list == ',') {
                        list++;
                        continue;
                }
@@ -3691,43 +3330,36 @@ int match_list(char *list, char *item)
        }
 }
 
-void EndpointAppPBX::pick_call(char *extensions)
+void EndpointAppPBX::pick_join(char *extensions)
 {
-       struct message *message;
+       struct lcr_msg *message;
        struct port_list *portlist;
        class Port *port;
        class EndpointAppPBX *eapp, *found;
-       class Call *call;
-       class CallPBX *callpbx;
-       struct call_relation *relation;
+       class Join *join;
+       class JoinPBX *joinpbx;
+       struct join_relation *relation;
        int vbox;
 
        /* find an endpoint that is ringing internally or vbox with higher priority */
        vbox = 0;
        found = NULL;
        eapp = apppbx_first;
-       while(eapp)
-       {
-               if (eapp!=this && ea_endpoint->ep_portlist)
-               {
+       while(eapp) {
+               if (eapp!=this && ea_endpoint->ep_portlist) {
                        portlist = eapp->ea_endpoint->ep_portlist;
-                       while(portlist)
-                       {
-                               if ((port = find_port_id(portlist->port_id)))
-                               {
-                                       if (port->p_type == PORT_TYPE_VBOX_OUT)
-                                       {
-                                               if (match_list(extensions, eapp->e_ext.number))
-                                               {
+                       while(portlist) {
+                               if ((port = find_port_id(portlist->port_id))) {
+                                       if (port->p_type == PORT_TYPE_VBOX_OUT) {
+                                               if (match_list(extensions, eapp->e_ext.number)) {
                                                        found = eapp;
                                                        vbox = 1;
                                                        break;
                                                }
                                        }
-                                       if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
+                                       if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT || port->p_type==PORT_TYPE_GSM_OUT)
                                         && port->p_state==PORT_STATE_OUT_ALERTING)
-                                               if (match_list(extensions, eapp->e_ext.number))
-                                               {
+                                               if (match_list(extensions, eapp->e_ext.number)) {
                                                        found = eapp;
                                                }
                                }
@@ -3740,8 +3372,7 @@ void EndpointAppPBX::pick_call(char *extensions)
        }
 
        /* if no endpoint found */
-       if (!found)
-       {
+       if (!found) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
 reject:
                set_tone(ea_endpoint->ep_portlist, "cause_10");
@@ -3751,92 +3382,82 @@ reject:
        }
        eapp = found;
 
-       if (ea_endpoint->ep_call_id)
-       {
-               PERROR("EPOINT(%d) we already have a call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
+       if (ea_endpoint->ep_join_id) {
+               PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
                goto reject;
        }
-       if (!eapp->ea_endpoint->ep_call_id)
-       {
-               PERROR("EPOINT(%d) ringing endpoint has no call.\n", ea_endpoint->ep_serial);
+       if (!eapp->ea_endpoint->ep_join_id) {
+               PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
                goto reject;
        }
-       call = find_call_id(eapp->ea_endpoint->ep_call_id);
-       if (!call)
-       {
-               PERROR("EPOINT(%d) ringing endpoint's call not found.\n", ea_endpoint->ep_serial);
+       join = find_join_id(eapp->ea_endpoint->ep_join_id);
+       if (!join) {
+               PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
                goto reject;
        }
-       if (callpbx->c_type != CALL_TYPE_PBX)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's call is not a PBX call, so we must reject.\n", ea_endpoint->ep_serial);
+       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;
        }
-       callpbx = (class CallPBX *)call;
-       relation = callpbx->c_relation;
-       if (!relation)
-       {
-               PERROR("EPOINT(%d) ringing endpoint's call has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
+       joinpbx = (class JoinPBX *)join;
+       relation = joinpbx->j_relation;
+       if (!relation) {
+               PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
                goto reject;
        }
-       while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
-       {
+       while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
                relation = relation->next;
-               if (!relation)
-               {
-                       PERROR("EPOINT(%d) ringing endpoint's call has no relation to that call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
+               if (!relation) {
+                       PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
                        goto reject;
                }
        }
 
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
 
-       if (options.deb & DEBUG_EPOINT)
-       {
-               class Call *debug_c = call_first;
+       if (options.deb & DEBUG_EPOINT) {
+               class Join *debug_c = join_first;
                class Endpoint *debug_e = epoint_first;
                class Port *debug_p = port_first;
 
-               callpbx_debug(callpbx, "EndpointAppPBX::pick_call(before)");
+               joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
 
-               PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
-               while(debug_c)
-               {
-                       PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
+               PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
+               while(debug_c) {
+                       PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
                        debug_c = debug_c->next;
                }
                PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
-               while(debug_e)
-               {
-                       PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
+               while(debug_e) {
+                       PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
                        debug_e = debug_e->next;
                }
                PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
-               while(debug_p)
-               {
+               while(debug_p) {
                        PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
                        debug_p = debug_p->next;
                }
        }
 
-       /* relink call */
-       ea_endpoint->ep_call_id = eapp->ea_endpoint->ep_call_id; /* we get the call */
-       relation->epoint_id = ea_endpoint->ep_serial; /* the call gets us */
-       eapp->ea_endpoint->ep_call_id = 0; /* the ringing endpoint will get disconnected */
+       /* relink join */
+       ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
+       relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
+       eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
 
        /* connnecting our endpoint */
        new_state(EPOINT_STATE_CONNECT);
-       e_dtmf = 1;
+       if (e_ext.number[0])
+               e_dtmf = 1;
        set_tone(ea_endpoint->ep_portlist, NULL);
 
        /* now we send a release to the ringing endpoint */
-       message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
-       message->param.disconnectinfo.cause = 26; /* non selected user clearing */
+       message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
+       message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
        message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
        message_put(message);
 
-       /* we send a connect to the call with our caller id */
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CONNECT);
+       /* we send a connect to the join with our caller id */
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
        SCPY(message->param.connectinfo.id, e_callerinfo.id);
        message->param.connectinfo.present = e_callerinfo.present;
        message->param.connectinfo.screen = e_callerinfo.screen;
@@ -3852,42 +3473,38 @@ reject:
        message->param.connectinfo.itype = eapp->e_callerinfo.itype;
        message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
        /* handle restricted caller ids */
-       apply_callerid_restriction(e_ext.anon_ignore, ea_endpoint->ep_portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name);
+       apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
        /* display callerid if desired for extension */
-       SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype,  message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name));
+       SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype,  message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
        message_put(message);
 
        /* we send a connect to the audio path (not for vbox) */
-       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, 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 = 1;
        message_put(message);
 
        /* beeing paranoid, we make call update */
-       callpbx->c_mixer = 1;
+       joinpbx->j_updatebridge = 1;
 
-       if (options.deb & DEBUG_EPOINT)
-       {
-               class Call *debug_c = call_first;
+       if (options.deb & DEBUG_EPOINT) {
+               class Join *debug_c = join_first;
                class Endpoint *debug_e = epoint_first;
                class Port *debug_p = port_first;
 
-               callpbx_debug(callpbx, "EndpointAppPBX::pick_call(after)");
+               joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
 
-               PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
-               while(debug_c)
-               {
-                       PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
+               PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
+               while(debug_c) {
+                       PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
                        debug_c = debug_c->next;
                }
                PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
-               while(debug_e)
-               {
-                       PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
+               while(debug_e) {
+                       PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
                        debug_e = debug_e->next;
                }
                PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
-               while(debug_p)
-               {
+               while(debug_p) {
                        PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
                        debug_p = debug_p->next;
                }
@@ -3895,50 +3512,44 @@ reject:
 }
 
 
-/* join calls (look for a call that is on hold (same isdn interface/terminal))
+/* join calls (look for a join that is on hold (same isdn interface/terminal))
  */
-void EndpointAppPBX::join_call(void)
+void EndpointAppPBX::join_join(void)
 {
-       struct message *message;
-       struct call_relation *our_relation, *other_relation;
-       struct call_relation **our_relation_pointer, **other_relation_pointer;
-       class Call *our_call, *other_call;
-       class CallPBX *our_callpbx, *other_callpbx;
+       struct lcr_msg *message;
+       struct join_relation *our_relation, *other_relation;
+       struct join_relation **our_relation_pointer, **other_relation_pointer;
+       class Join *our_join, *other_join;
+       class JoinPBX *our_joinpbx, *other_joinpbx;
        class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
        class Port *our_port, *other_port;
        class Pdss1 *our_pdss1, *other_pdss1;
 
-       /* are we a candidate to join a call */
-       our_call = find_call_id(ea_endpoint->ep_call_id);
-       if (!our_call)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our call doesn't exist anymore.\n", ea_endpoint->ep_serial);
+       /* are we a candidate to join a join? */
+       our_join = find_join_id(ea_endpoint->ep_join_id);
+       if (!our_join) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
                return;
        }
-       if (our_call->c_type != CALL_TYPE_PBX)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: call is not a pbx call.\n", ea_endpoint->ep_serial);
+       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;
        }
-       our_callpbx = (class CallPBX *)our_call;
-       if (!ea_endpoint->ep_portlist)
-       {
+       our_joinpbx = (class JoinPBX *)our_join;
+       if (!ea_endpoint->ep_portlist) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
                return;
        }
-       if (!e_ext.number[0])
-       {
+       if (!e_ext.number[0]) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
                return;
        }
        our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
-       if (!our_port)
-       {
+       if (!our_port) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
                return;
        }
-       if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
-       {
+       if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
                return;
        }
@@ -3946,199 +3557,173 @@ void EndpointAppPBX::join_call(void)
 
        /* find an endpoint that is on hold and has the same mISDNport that we are on */
        other_eapp = apppbx_first;
-       while(other_eapp)
-       {
-               if (other_eapp == this)
-               {
+       while(other_eapp) {
+               if (other_eapp == this) {
                        other_eapp = other_eapp->next;
                        continue;
                }
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s call=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_call_id);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s join=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_join_id);
                if (other_eapp->e_ext.number[0] /* has terminal */
                 && other_eapp->ea_endpoint->ep_portlist /* has port */
-                && other_eapp->ea_endpoint->ep_call_id) /* has call */
-               {
+                && other_eapp->ea_endpoint->ep_join_id) { /* has join */
                        other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
-                       if (other_port) /* port still exists */
-                       {
+                       if (other_port) { /* port still exists */
                                if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
-                                || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
-                               {
+                                || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
                                        other_pdss1 = (class Pdss1 *)other_port;
                                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
                                        if (other_pdss1->p_m_hold /* port is on hold */
                                         && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
                                         && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
                                                break;
-                               } else
-                               {
+                               } else {
                                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
                                }
-                       } else
-                       {
+                       } else {
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
                        }
                }
                other_eapp = other_eapp->next;
        }
-       if (!other_eapp)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
+       if (!other_eapp) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
                return;
        }
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
 
-       /* if we have the same call */
-       if (other_eapp->ea_endpoint->ep_call_id == ea_endpoint->ep_call_id)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same call.\n", ea_endpoint->ep_serial);
+       /* if we have the same join */
+       if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
                return;
        }
-       other_call = find_call_id(other_eapp->ea_endpoint->ep_call_id);
-       if (!other_call)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call doesn't exist anymore.\n", ea_endpoint->ep_serial);
+       other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
+       if (!other_join) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
                return;
        }
-       if (other_call->c_type != CALL_TYPE_PBX)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call is not a pbx call.\n", ea_endpoint->ep_serial);
+       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_callpbx = (class CallPBX *)other_call;
-       if (our_callpbx->c_partyline && other_callpbx->c_partyline)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both calls are partylines.\n", ea_endpoint->ep_serial);
+       other_joinpbx = (class JoinPBX *)other_join;
+       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 call on hold */
-       other_relation = other_callpbx->c_relation;
-       other_relation_pointer = &other_callpbx->c_relation;
-       while(other_relation)
-       {
-               if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
-               {
-               /* detach other endpoint on hold */
+       /* remove relation to endpoint for join on hold */
+       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) {
+                       /* detach other endpoint on hold */
                        *other_relation_pointer = other_relation->next;
-                       memset(other_relation, 0, sizeof(struct call_relation));
-                       free(other_relation);
+                       FREE(other_relation, sizeof(struct join_relation));
                        cmemuse--;
                        other_relation = *other_relation_pointer;
-                       other_eapp->ea_endpoint->ep_call_id = NULL;
+                       other_eapp->ea_endpoint->ep_join_id = 0;
                        continue;
                }
 
-               /* change call/hold pointer of endpoint to the new call */
+               /* change join/hold pointer of endpoint to the new join */
                temp_epoint = find_epoint_id(other_relation->epoint_id);
-               if (temp_epoint)
-               {
-                       if (temp_epoint->ep_call_id == other_call->c_serial)
-                               temp_epoint->ep_call_id = our_call->c_serial;
+               if (temp_epoint) {
+                       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;
                other_relation = other_relation->next;
        }
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on call relinked (to our call).\n", ea_endpoint->ep_serial);
+       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_callpbx->c_relation;
-       our_relation_pointer = &our_callpbx->c_relation;
-       while(our_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_callpbx->c_relation;
-       other_callpbx->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_callpbx->c_serial, other_eapp->ea_endpoint->ep_serial, CALL_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 call */
-       our_callpbx->c_partyline += other_callpbx->c_partyline; 
+       /* if we are not a partyline, we get partyline state from other join */
+       our_joinpbx->j_partyline += other_joinpbx->j_partyline; 
 
-       /* remove empty call */
-       delete other_call;
-       PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-call completely removed!\n");
+       /* remove empty join */
+       delete other_join;
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
 
        /* mixer must update */
-       our_callpbx->c_mixer = 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 call and send it to the endpoints is changes
+       // mixer will update the hold-state of the join and send it to the endpoints is changes
 }
 
 
 /* check if we have an external call
  * this is used to check for encryption ability
  */
-int EndpointAppPBX::check_external(char **errstr, class Port **port)
+int EndpointAppPBX::check_external(const char **errstr, class Port **port)
 {
-       struct call_relation *relation;
-       class Call *call;
-       class CallPBX *callpbx;
+       struct join_relation *relation;
+       class Join *join;
+       class JoinPBX *joinpbx;
        class Endpoint *epoint;
 
        /* some paranoia check */
-       if (!ea_endpoint->ep_portlist)
-       {
+       if (!ea_endpoint->ep_portlist) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
-       if (!e_ext.number[0])
-       {
+       if (!e_ext.number[0]) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
 
-       /* check if we have a call with 2 parties */
-       call = find_call_id(ea_endpoint->ep_call_id);
-       if (!call)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no call.\n", ea_endpoint->ep_serial);
+       /* check if we have a join with 2 parties */
+       join = find_join_id(ea_endpoint->ep_join_id);
+       if (!join) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
-       if (call->c_type != CALL_TYPE_PBX)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call is nto a pbx call.\n", ea_endpoint->ep_serial);
+       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);
        }
-       callpbx = (class CallPBX *)call;
-       relation = callpbx->c_relation;
-       if (!relation)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no relation.\n", ea_endpoint->ep_serial);
+       joinpbx = (class JoinPBX *)join;
+       relation = joinpbx->j_relation;
+       if (!relation) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
-       if (!relation->next)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd relation.\n", ea_endpoint->ep_serial);
+       if (!relation->next) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
-       if (relation->next->next)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has more than two relations.\n", ea_endpoint->ep_serial);
+       if (relation->next->next) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
                *errstr = "Err: Conference";
                return(1);
        }
-       if (relation->epoint_id == ea_endpoint->ep_serial)
-       {
+       if (relation->epoint_id == ea_endpoint->ep_serial) {
                relation = relation->next;
-               if (relation->epoint_id == ea_endpoint->ep_serial)
-               {
-                       PERROR("EPOINT(%d) SOFTWARE ERROR: both call relations are related to our endpoint.\n", ea_endpoint->ep_serial);
+               if (relation->epoint_id == ea_endpoint->ep_serial) {
+                       PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
                        *errstr = "Software Error";
                        return(1);
                }
@@ -4146,33 +3731,28 @@ int EndpointAppPBX::check_external(char **errstr, class Port **port)
 
        /* check remote port for external call */
        epoint = find_epoint_id(relation->epoint_id);
-       if (!epoint)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd endpoint.\n", ea_endpoint->ep_serial);
+       if (!epoint) {
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
-       if (!epoint->ep_portlist)
-       {
+       if (!epoint->ep_portlist) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
        *port = find_port_id(epoint->ep_portlist->port_id);
-       if (!(*port))
-       {
+       if (!(*port)) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
-       if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
-       {
+       if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) { /* port is not external isdn */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
                *errstr = "No Ext Call";
                return(1);
        }
-       if ((*port)->p_state != PORT_STATE_CONNECT)
-       {
+       if ((*port)->p_state != PORT_STATE_CONNECT) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
                *errstr = "No Ext Connect";
                return(1);
@@ -4180,120 +3760,163 @@ int EndpointAppPBX::check_external(char **errstr, class Port **port)
        return(0);
 }
 
-void EndpointAppPBX::logmessage(struct message *message)
+void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
 {
-       class Port *port;
-       class Pdss1 *pdss1;
-       char *logtext = "unknown";
+       const char *logtext = "unknown";
        char buffer[64];
 
-       if (message->flow != EPOINT_TO_PORT)
-       {
-               PERROR("EPOINT(%d) message not of correct flow type-\n", ea_endpoint->ep_serial);
-               return;
-       }
-
-       switch(message->type)
-       {
+       switch(message_type) {
                case MESSAGE_SETUP:
-               port = find_port_id(message->id_to);
-               if (!port)
-                       return;
-               if (port->p_type == PORT_TYPE_DSS1_NT_OUT)
-               {
-                       pdss1 = (class Pdss1 *)port;
-                       printlog("%3d  outgoing SETUP from %s='%s'%s%s%s%s to intern='%s' port='%d' (NT)\n",
-                               ea_endpoint->ep_serial,
-                               (message->param.setup.callerinfo.intern[0])?"intern":"extern",
-                               (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
-                               (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
-                               (message->param.setup.redirinfo.id[0])?"redirected='":"",
-                               message->param.setup.redirinfo.id,
-                               (message->param.setup.redirinfo.id[0])?"'":"",
-                               message->param.setup.dialinginfo.number,
-                               pdss1->p_m_mISDNport->portnum
-                               );
+               trace_header("SETUP", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               if (param->setup.callerinfo.extension[0])
+                       add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
+               add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
+               switch(param->setup.callerinfo.present) {
+                       case INFO_PRESENT_RESTRICTED:
+                       add_trace("caller id", "present", "restricted");
+                       break;
+                       case INFO_PRESENT_ALLOWED:
+                       add_trace("caller id", "present", "allowed");
+                       break;
+                       default:
+                       add_trace("caller id", "present", "not available");
                }
-               if (port->p_type == PORT_TYPE_DSS1_TE_OUT)
-               {
-                       pdss1 = (class Pdss1 *)port;
-                       printlog("%3d  outgoing SETUP from %s='%s'%s%s%s%s to extern='%s' port='%d' (TE)\n",
-                               ea_endpoint->ep_serial,
-                               (message->param.setup.callerinfo.intern[0])?"intern":"extern",
-                               (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
-                               (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
-                               (message->param.setup.redirinfo.id[0])?"redirected='":"",
-                               message->param.setup.redirinfo.id,
-                               (message->param.setup.redirinfo.id[0])?"'":"",
-                               message->param.setup.dialinginfo.number,
-                               pdss1->p_m_mISDNport->portnum
-                               );
+               if (param->setup.callerinfo.ntype2) {
+                       add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
+                       switch(param->setup.callerinfo.present) {
+                               case INFO_PRESENT_RESTRICTED:
+                               add_trace("caller id2", "present", "restricted");
+                               break;
+                               case INFO_PRESENT_ALLOWED:
+                               add_trace("caller id2", "present", "allowed");
+                               break;
+                               default:
+                               add_trace("caller id2", "present", "not available");
+                       }
                }
-               if (port->p_type == PORT_TYPE_VBOX_OUT)
-               {
-                       printlog("%3d  outgoing SETUP from %s='%s'%s%s%s%s to vbox='%s'\n",
-                               ea_endpoint->ep_serial,
-                               (message->param.setup.callerinfo.intern[0])?"intern":"extern",
-                               (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
-                               (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
-                               (message->param.setup.redirinfo.id[0])?"redirected='":"",
-                               message->param.setup.redirinfo.id,
-                               (message->param.setup.redirinfo.id[0])?"'":"",
-                               message->param.setup.dialinginfo.number
-                               );
+               if (param->setup.redirinfo.id[0]) {
+                       add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
+                       switch(param->setup.redirinfo.present) {
+                               case INFO_PRESENT_RESTRICTED:
+                               add_trace("redir'ing", "present", "restricted");
+                               break;
+                               case INFO_PRESENT_ALLOWED:
+                               add_trace("redir'ing", "present", "allowed");
+                               break;
+                               default:
+                               add_trace("redir'ing", "present", "not available");
+                       }
                }
+               if (param->setup.dialinginfo.id[0])
+                       add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
+               if (param->setup.dialinginfo.display[0])
+                       add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
+               if (param->setup.dialinginfo.sending_complete)
+                       add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
+               end_trace();
                break;
 
                case MESSAGE_OVERLAP:
-               printlog("%3d  outgoing SETUP ACKNOWLEDGE\n",
-                       ea_endpoint->ep_serial
-                       );
+               trace_header("SETUP ACKNOWLEDGE", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               end_trace();
                break;
 
                case MESSAGE_PROCEEDING:
-               printlog("%3d  outgoing PROCEEDING\n",
-                       ea_endpoint->ep_serial
-                       );
+               trace_header("PROCEEDING", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               end_trace();
                break;
 
                case MESSAGE_ALERTING:
-               printlog("%3d  outgoing ALERTING\n",
-                       ea_endpoint->ep_serial
-                       );
+               trace_header("ALERTING", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               end_trace();
                break;
 
                case MESSAGE_CONNECT:
-               printlog("%3d  outgoing CONNECT id='%s'%s\n",
-                       ea_endpoint->ep_serial,
-                       message->param.connectinfo.id,
-                       (message->param.connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
-               );
+               trace_header("CONNECT", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               if (param->connectinfo.extension[0])
+                       add_trace("extension", NULL, "%s", param->connectinfo.extension);
+               add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
+               switch(param->connectinfo.present) {
+                       case INFO_PRESENT_RESTRICTED:
+                       add_trace("connect id", "present", "restricted");
+                       break;
+                       case INFO_PRESENT_ALLOWED:
+                       add_trace("connect id", "present", "allowed");
+                       break;
+                       default:
+                       add_trace("connect id", "present", "not available");
+               }
+               if (param->connectinfo.display[0])
+                       add_trace("display", NULL, "%s", param->connectinfo.display);
+               end_trace();
                break;
 
                case MESSAGE_DISCONNECT:
-               printlog("%3d  outgoing DISCONNECT cause='%d' (%s) location='%d' (%s) display='%s'\n",
-                       ea_endpoint->ep_serial,
-                       message->param.disconnectinfo.cause,
-                       (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
-                       message->param.disconnectinfo.location,
-                       (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-",
-                       message->param.disconnectinfo.display
-                       );
-               break;
-
                case MESSAGE_RELEASE:
-               printlog("%3d  outgoing RELEASE cause='%d' (%s) location='%d' (%s)\n",
-                       ea_endpoint->ep_serial,
-                       message->param.disconnectinfo.cause,
-                       (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
-                       message->param.disconnectinfo.location,
-                       (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-"
-                       );
+               if (message_type == MESSAGE_DISCONNECT)
+                       trace_header("DISCONNECT", dir);
+               else
+                       trace_header("RELEASE", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               add_trace("cause", "value", "%d", param->disconnectinfo.cause);
+               switch(param->disconnectinfo.location) {
+                       case LOCATION_USER:
+                       add_trace("cause", "location", "0-User");
+                       break;
+                       case LOCATION_PRIVATE_LOCAL:
+                       add_trace("cause", "location", "1-Local-PBX");
+                       break;
+                       case LOCATION_PUBLIC_LOCAL:
+                       add_trace("cause", "location", "2-Local-Exchange");
+                       break;
+                       case LOCATION_TRANSIT:
+                       add_trace("cause", "location", "3-Transit");
+                       break;
+                       case LOCATION_PUBLIC_REMOTE:
+                       add_trace("cause", "location", "4-Remote-Exchange");
+                       break;
+                       case LOCATION_PRIVATE_REMOTE:
+                       add_trace("cause", "location", "5-Remote-PBX");
+                       break;
+                       case LOCATION_INTERNATIONAL:
+                       add_trace("cause", "location", "7-International-Exchange");
+                       break;
+                       case LOCATION_BEYOND:
+                       add_trace("cause", "location", "10-Beyond-Interworking");
+                       break;
+                       default:
+                       add_trace("cause", "location", "%d", param->disconnectinfo.location);
+               }
+               if (param->disconnectinfo.display[0])
+                       add_trace("display", NULL, "%s", param->disconnectinfo.display);
+               end_trace();
                break;
 
                case MESSAGE_NOTIFY:
-               switch(message->param.notifyinfo.notify)
-               {
+               switch(param->notifyinfo.notify) {
                        case 0x00:
                        logtext = "NULL";
                        break;
@@ -4367,57 +3990,129 @@ void EndpointAppPBX::logmessage(struct message *message)
                        logtext = "CALL_IS_DIVERTING";
                        break;
                        default:
-                       SPRINT(buffer, "indicator=%d", message->param.notifyinfo.notify - 0x80);
+                       SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
                        logtext = buffer;
 
                }
-               printlog("%3d  outgoing NOTIFY notify='%s' id='%s'%s display='%s'\n",
-                       ea_endpoint->ep_serial,
-                       logtext,
-                       message->param.notifyinfo.id,
-                       (message->param.notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
-                       message->param.notifyinfo.display
-                       );
+               trace_header("NOTIFY", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               if (param->notifyinfo.notify)
+                       add_trace("indicator", NULL, "%s", logtext);
+               if (param->notifyinfo.id[0]) {
+                       add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
+                       switch(param->notifyinfo.present) {
+                               case INFO_PRESENT_RESTRICTED:
+                               add_trace("redir'on", "present", "restricted");
+                               break;
+                               case INFO_PRESENT_ALLOWED:
+                               add_trace("redir'on", "present", "allowed");
+                               break;
+                               default:
+                               add_trace("redir'on", "present", "not available");
+                       }
+               }
+               if (param->notifyinfo.display[0])
+                       add_trace("display", NULL, "%s", param->notifyinfo.display);
+               end_trace();
                break;
 
                case MESSAGE_INFORMATION:
-               printlog("%3d  outgoing INFORMATION information='%s'\n",
-                       ea_endpoint->ep_serial,
-                       message->param.information.number
-                       );
+               trace_header("INFORMATION", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               if (param->information.id[0])
+                       add_trace("dialing", NULL, "%s", param->information.id);
+               if (param->information.display[0])
+                       add_trace("display", NULL, "%s", param->information.display);
+               if (param->information.sending_complete)
+                       add_trace("complete", NULL, "true", param->information.sending_complete);
+               end_trace();
                break;
 
                case MESSAGE_FACILITY:
-               printlog("%3d  outgoing FACILITY len='%d'\n",
-                       ea_endpoint->ep_serial,
-                       message->param.facilityinfo.len
-                       );
+               trace_header("FACILITY", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               end_trace();
                break;
 
                case MESSAGE_TONE:
-               printlog("%3d  outgoing TONE dir='%s' name='%s'\n",
-                       ea_endpoint->ep_serial,
-                       message->param.tone.dir,
-                       message->param.tone.name
-                       );
+               trace_header("TONE", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               if (param->tone.name[0]) {
+                       add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
+                       add_trace("name", NULL, "%s", param->tone.name);
+               } else
+                       add_trace("off", NULL, NULL);
+               end_trace();
+               break;
+
+               case MESSAGE_SUSPEND:
+               case MESSAGE_RESUME:
+               if (message_type == MESSAGE_SUSPEND)
+                       trace_header("SUSPEND", dir);
+               else
+                       trace_header("RESUME", dir);
+               if (dir == DIRECTION_OUT)
+                       add_trace("to", NULL, "CH(%lu)", port_id);
+               if (dir == DIRECTION_IN)
+                       add_trace("from", NULL, "CH(%lu)", port_id);
+               if (param->parkinfo.len)
+                       add_trace("length", NULL, "%d", param->parkinfo.len);
+               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);
+               PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
        }
 }
 
-void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
+void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
 {
-       struct message *message;
+       struct lcr_msg *message;
 
        if (!portlist)
                return;
        if (!portlist->port_id)
                return;
 
-       if (!e_connectedmode)
-       {
+       if (!e_connectedmode) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
                message->param.disconnectinfo.cause = cause;
                message->param.disconnectinfo.location = location;
@@ -4425,8 +4120,7 @@ void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cau
                        SCPY(message->param.disconnectinfo.display, display);
                else
                        SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
-       } else
-       {
+       } else {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
                if (display[0])
                        SCPY(message->param.notifyinfo.display, display);
@@ -4434,5 +4128,6 @@ void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cau
                        SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
        }
        message_put(message);
-       logmessage(message);
+       logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
 }
+