Adds screening of redirecting number
[lcr.git] / apppbx.cpp
index 3788c85..6cf2c92 100644 (file)
 \*****************************************************************************/ 
 
 
-#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;
 
+int action_timeout(struct lcr_timer *timer, void *instance, int index);
+int match_timeout(struct lcr_timer *timer, void *instance, int index);
+int redial_timeout(struct lcr_timer *timer, void *instance, int index);
+int powerdial_timeout(struct lcr_timer *timer, void *instance, int index);
+int cfnr_timeout(struct lcr_timer *timer, void *instance, int index);
+int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index);
+int password_timeout(struct lcr_timer *timer, void *instance, int index);
+int callback_timeout(struct lcr_timer *timer, void *instance, int index);
+
 /*
  * EndpointAppPBX constructor
  */
-EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
+EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin, EAPP_TYPE_PBX)
 {
        class EndpointAppPBX **apppointer;
 
+#ifdef WITH_CRYPT
+       memset(&e_crypt_handler, 0, sizeof(e_crypt_handler));
+       add_timer(&e_crypt_handler, crypt_handler, this, 0);
+#endif
+       memset(&e_vbox_refresh, 0, sizeof(e_vbox_refresh));
+       add_timer(&e_vbox_refresh, vbox_refresh, this, 0);
+       memset(&e_action_timeout, 0, sizeof(e_action_timeout));
+       add_timer(&e_action_timeout, action_timeout, this, 0);
+       memset(&e_match_timeout, 0, sizeof(e_match_timeout));
+       add_timer(&e_match_timeout, match_timeout, this, 0);
+       memset(&e_redial_timeout, 0, sizeof(e_redial_timeout));
+       add_timer(&e_redial_timeout, redial_timeout, this, 0);
+       memset(&e_powerdial_timeout, 0, sizeof(e_powerdial_timeout));
+       add_timer(&e_powerdial_timeout, powerdial_timeout, this, 0);
+       memset(&e_cfnr_timeout, 0, sizeof(e_cfnr_timeout));
+       add_timer(&e_cfnr_timeout, cfnr_timeout, this, 0);
+       memset(&e_cfnr_call_timeout, 0, sizeof(e_cfnr_call_timeout));
+       add_timer(&e_cfnr_call_timeout, cfnr_call_timeout, this, 0);
+       memset(&e_callback_timeout, 0, sizeof(e_callback_timeout));
+       add_timer(&e_callback_timeout, callback_timeout, this, 0);
+       memset(&e_password_timeout, 0, sizeof(e_password_timeout));
+       add_timer(&e_password_timeout, password_timeout, this, 0);
+       e_powerdial_on = 0;
+
        /* add application to chain */
        next = NULL;
        apppointer = &apppbx_first;
@@ -49,6 +74,7 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp
         memset(&e_connectinfo, 0, sizeof(struct connect_info));
         memset(&e_redirinfo, 0, sizeof(struct redir_info));
         memset(&e_capainfo, 0, sizeof(struct capa_info));
+        memset(&e_rtpinfo, 0, sizeof(struct rtp_info));
         e_start = e_stop = 0;
        e_origin = origin;
        e_ruleset = ruleset_main;
@@ -56,8 +82,6 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp
                e_rule = e_ruleset->rule_first;
        e_rule_nesting = 0;
         e_action = NULL;
-       e_action_timeout = 0;
-       e_match_timeout = 0;
        e_match_to_action = NULL;
         e_select = 0;
         e_extdialing = e_dialinginfo.id;
@@ -66,13 +90,10 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp
        e_hold = 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
-        e_powerdialing = 0;
         e_powerdelay = 0;
         e_powerlimit = 0;
-        e_callback = 0;
         e_cbdialing[0] = '\0';
         e_cbcaller[0] = '\0';
        e_cbto[0] = '\0';
@@ -81,16 +102,16 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp
         e_dtmf = 0;
         e_dtmf_time = 0;
         e_dtmf_last = 0;
-       e_cfnr_release = 0;
-       e_cfnr_call = 0;
-       e_password_timeout = 0;
+       e_enablekeypad = 0;
        e_multipoint_cause = 0;
        e_multipoint_location = 0;
        e_dialing_queue[0] = '\0';
+#ifdef WITH_CRYPT
        e_crypt = CRYPT_OFF;
        e_crypt_state = CM_ST_NULL;
        e_crypt_keyengine_busy = 0;
-       e_crypt_info[0] = '\0'; 
+       e_crypt_info[0] = '\0';
+#endif
        e_overlap = 0;
        e_vbox[0] = '\0';
        e_tx_state = NOTIFY_STATE_ACTIVE;
@@ -114,11 +135,23 @@ EndpointAppPBX::~EndpointAppPBX(void)
 {
        class EndpointAppPBX *temp, **tempp;
 
+#ifdef WITH_CRYPT
+       del_timer(&e_crypt_handler);
+#endif
+       del_timer(&e_vbox_refresh);
+       del_timer(&e_action_timeout);
+       del_timer(&e_match_timeout);
+       del_timer(&e_redial_timeout);
+       del_timer(&e_powerdial_timeout);
+       del_timer(&e_cfnr_timeout);
+       del_timer(&e_cfnr_call_timeout);
+       del_timer(&e_callback_timeout);
+       del_timer(&e_password_timeout);
+
        /* detach */
        temp =apppbx_first;
        tempp = &apppbx_first;
-       while(temp)
-       {
+       while(temp) {
                if (temp == this)
                        break;
 
@@ -135,7 +168,7 @@ EndpointAppPBX::~EndpointAppPBX(void)
 /*
  * trace header for application
  */
-void EndpointAppPBX::trace_header(char *name, int direction)
+void EndpointAppPBX::trace_header(const char *name, int direction)
 {
        struct trace _trace;
 
@@ -144,9 +177,9 @@ void EndpointAppPBX::trace_header(char *name, int direction)
        SCPY(msgtext, name);
 
        /* init trace with given values */
-       start_trace(0,
+       start_trace(-1,
                    NULL,
-                   numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
+                   numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
                    e_dialinginfo.id,
                    direction,
                    CATEGORY_EP,
@@ -162,8 +195,7 @@ EPOINT_STATE_NAMES
 void EndpointAppPBX::new_state(int state)
 {
 #if 0
-       if (e_state != state)
-       {
+       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]);
@@ -176,21 +208,19 @@ void EndpointAppPBX::new_state(int state)
 
 /* release join and port (as specified)
  */
-void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
+void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
 {
        struct port_list *portlist;
-       struct message *message;
+       struct lcr_msg *message;
        char cause[16];
 
        /* message to test call */
        admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
 
        /* if a release is pending */
-       if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
-       {
+       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)
-               {
+               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;
@@ -199,26 +229,23 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                }
                e_join_pattern = 0;
 #if 0
-               if (release != RELEASE_PORT_JOINONLY)
-               {
+               if (release != RELEASE_PORT_JOINONLY) {
                        if (e_hold_id)
                                join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
                        e_hold_id = 0;
                }
 #endif
        }
-       if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
-       {
+       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->param.disconnectinfo.force = force; // set, if port should release imediately
                                message_put(message);
                                logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                        }
@@ -226,8 +253,7 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                }
 
                /* if callback is enabled, call back with the given caller id */
-               if (e_callback)
-               {
+               if (e_callback_timeout.active) {
                        /* reset some stuff */
                        new_state(EPOINT_STATE_IDLE);
                        memset(&e_connectinfo, 0, sizeof(struct connect_info));
@@ -237,8 +263,10 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                        if (e_ruleset)
                                e_rule = e_ruleset->rule_first;
                        e_action = NULL;
-                       e_action_timeout = 0;
-                       e_match_timeout = 0;
+                       unsched_timer(&e_action_timeout);
+                       unsched_timer(&e_match_timeout);
+                       unsched_timer(&e_cfnr_timeout);
+                       unsched_timer(&e_cfnr_call_timeout);
                        e_match_to_action = NULL;
                        //e_select = 0;
                        e_extdialing = e_dialinginfo.id;
@@ -246,15 +274,16 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                        e_dtmf = 0;
                        e_dtmf_time = 0;
                        e_dtmf_last = 0;
-                       e_cfnr_release = 0;
-                       e_cfnr_call = 0;
+                       e_enablekeypad = 0;
                        e_multipoint_cause = 0;
                        e_multipoint_location = 0;
                        e_dialing_queue[0] = '\0';
+#ifdef WITH_CRYPT
                        e_crypt = 0;
                        e_crypt_state = CM_ST_NULL;
                        e_crypt_keyengine_busy = 0;
                        e_crypt_info[0] = '\0'; 
+#endif
                        e_tone[0] = '\0';
                        e_overlap = 0;
                        e_vbox[0] = '\0';
@@ -266,23 +295,19 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                        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.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])
-                               {
+                       } else {
+                               if (e_cbto[0]) {
                                        SCPY(e_dialinginfo.id, e_cbto);
-                               } else
-                               {
+                               } else {
                                        /* numberrize caller id and use it to dial to the callback */
-                                       SCPY(e_dialinginfo.id, 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;
@@ -292,7 +317,8 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                }
 
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
-               ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
+               if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
+                       trigger_work(&ea_endpoint->ep_delete);
                return;
        }
 }
@@ -333,12 +359,12 @@ void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int
 }
 
 /* used display message to display callerid as available */
-char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, 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 extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
 
@@ -352,8 +378,7 @@ char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int
        /* 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 (extension[0] && e_ext.display_int)
-       {
+       if (extension[0] && e_ext.display_int) {
                if (!display[0])
                        SCAT(display, extension);
                if (display[0])
@@ -365,12 +390,9 @@ char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int
        }
 
        /* external caller id */
-       if (!extension[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
@@ -382,8 +404,7 @@ 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_anon && present==INFO_PRESENT_RESTRICTED)
-       {
+       if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
                if (!cid[0])
                        SCAT(display, "unknown");
                else 
@@ -392,12 +413,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
@@ -410,8 +428,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])
@@ -428,19 +445,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;
                }
@@ -449,8 +464,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;
                }
@@ -459,8 +473,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;
                }
@@ -472,8 +485,7 @@ 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);
@@ -490,18 +502,15 @@ 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_join_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;
                }
@@ -509,6 +518,7 @@ void EndpointAppPBX::keypad_function(char digit)
                join_join();
                break;
 
+#ifdef WITH_CRYPT
                /* crypt shared */
                case '7':
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
@@ -526,6 +536,7 @@ void EndpointAppPBX::keypad_function(char digit)
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
                encrypt_off();
                break;
+#endif
 
                default:        
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
@@ -534,9 +545,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 = "";
@@ -556,286 +567,42 @@ 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->type, &message->param, portlist->port_id, DIRECTION_OUT);
-       } else
-       {
+       } else {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
                return;
        }
 }
 
 
-/*
- * hunts an mISDNport that is available for an outgoing call
- * if no ifname was given, any interface that is not an extension
- * will be searched.
- */
-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;
-
-       interface = interface_first;
-
-       /* first find the given interface or, if not given, one with no extension */
-       checknext:
-       if (!interface)
-               return(NULL);
-
-       /* check for given interface */
-       if (ifname)
-       {
-               if (!strcasecmp(interface->name, ifname))
-               {
-                       /* found explicit interface */
-                       trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
-                       add_trace("interface", NULL, "%s", ifname);
-                       end_trace();
-                       goto foundif;
-               }
-
-       } else
-       {
-               if (!interface->extension)
-               {
-                       /* found non extension */
-                       trace_header("CHANNEL SELECTION (found non extension 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)
-       {
-               /* no ports */
-               trace_header("CHANNEL SELECTION (interface has no 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->ifport;
-       index = 0;
-       if (interface->hunt == HUNT_ROUNDROBIN)
-       {
-               while(ifport_start->next && index<interface->hunt_next)
-               {
-                       ifport_start = ifport_start->next;
-                       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 */
-       ifport = ifport_start;
-       nextport:
-
-       /* see if port is available */
-       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;
-
-       /* see if port is administratively blocked */
-       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 on PTP*/
-       if (mISDNport->l2hold && !mISDNport->l2link)
-       {
-               trace_header("CHANNEL SELECTION (port holds layer 2, but 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->out_channel;
-       while(selchannel)
-       {
-               switch(selchannel->channel)
-               {
-                       case CHANNEL_FREE: /* free channel */
-                       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)
-                               {
-                                       *channel = i+1+(i>=15);
-                                       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_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 */
-                       }
-                       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 */
-                       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)
-                       {
-                               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)
-                       {
-                               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)
-                       {
-                               *channel = selchannel->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;
-               }
-               if (*channel)
-                       break; /* found channel */
-               selchannel = selchannel->next;
-       }
-
-       /* if channel was found, return mISDNport and channel */
-       if (*channel)
-       {
-               /* setting next port to start next time */
-               if (interface->hunt == HUNT_ROUNDROBIN)
-               {
-                       index++;
-                       if (!ifport->next)
-                               index = 0;
-                       interface->hunt_next = index;
-               }
-               
-               return(mISDNport);
-       }
-
-       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)
-       {
-               index = 0;
-               ifport = interface->ifport;
-       }
-       if (ifport != ifport_start)
-               goto nextport;
-
-       return(NULL); /* no port found */
-}
-
 /* outgoing setup to port(s)
  * ports will be created and a setup is sent if everything is ok. otherwhise
  * the endpoint is destroyed.
  */
-void EndpointAppPBX::out_setup(void)
+void EndpointAppPBX::out_setup(int cfnr)
 {
        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 interface        *interface;
+#ifdef WITH_MISDN
        struct mISDNport        *mISDNport;
+#endif
        char                    portname[32];
        char                    *dirname;
        class EndpointAppPBX    *atemp;
@@ -844,8 +611,15 @@ void EndpointAppPBX::out_setup(void)
        char                    ifname[sizeof(e_ext.interfaces)],
                                number[256];
        struct port_settings    port_settings;
+#ifdef WITH_MISDN
        int                     channel = 0;
+       struct admin_list       *admin;
+#endif
        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));
@@ -858,25 +632,21 @@ void EndpointAppPBX::out_setup(void)
        /* 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_ join, port */
+                               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
                                return; /* must exit here */
                        }
                }
@@ -887,15 +657,14 @@ void EndpointAppPBX::out_setup(void)
 //             if (strchr(exten, ','))
 //                     *strchr(exten, ',') = '\0';
 //             if (!read_extension(&e_ext, exten))
-               if (!read_extension(&e_ext, e_dialinginfo.id))
-               {
+               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 */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
+               e_dialinginfo.sending_complete = 1;
 
-               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;
@@ -903,11 +672,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))
@@ -916,18 +683,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))
@@ -940,22 +702,18 @@ 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 (cfnr) {
                                /* 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))
-                       {
-                               e_cfnr_release = now + e_ext.cfnr_delay;
-                               e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
+                       if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
+                               schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
+                               schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* 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);
                        }
                }
@@ -963,46 +721,102 @@ void EndpointAppPBX::out_setup(void)
                /* call to all internal interfaces */
                p = e_ext.interfaces;
                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)
-               {
+               while(*p) {
+                       earlyb = 0;
                        ifname[0] = '\0';
                        while(*p!=',' && *p!='\0')
                                if (*p > ' ')
                                        SCCAT(ifname, *p++);
                        if (*p == ',')
                                p++;
-                       /* found interface */
-                       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)
-                       {
-                               trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
+                       /* search interface */
+                       interface = hunt_interface(ifname);
+                       if (!interface) {
+                               trace_header("INTERFACE (not found)", DIRECTION_NONE);
                                add_trace("interface", NULL, "%s", ifname);
                                end_trace();
                                continue;
                        }
-                       /* creating INTERNAL port */
-                       SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
-                       port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
+                       /* found interface */
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
+#ifdef WITH_GSM_BS
+                       if (interface->gsm_bs) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
+                               earlyb = (interface->is_earlyb == IS_YES);
+                       } else
+#endif
+#ifdef WITH_GSM_MS
+                       if (interface->gsm_ms) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
+                               earlyb = (interface->is_earlyb == IS_YES);
+                       } else
+#endif
+#ifdef WITH_SIP
+                       if (interface->sip) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+                               earlyb = (interface->is_earlyb == IS_YES);
+                       } else
+#endif
+                       {
+#ifdef WITH_MISDN
+                               /* hunt for mISDNport and create Port */
+                               mISDNport = hunt_port(ifname, &channel);
+                               if (!mISDNport) {
+                                       trace_header("INTERFACE (busy)", DIRECTION_NONE);
+                                       add_trace("interface", NULL, "%s", ifname);
+                                       end_trace();
+                                       continue;
+                               }
+
+                               SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+#ifdef WITH_SS5
+                               if (mISDNport->ss5)
+                                       port = ss5_hunt_line(mISDNport);
+                               else
+#endif
+                               if (mISDNport->ifport->remote) {
+                                       admin = admin_first;
+                                       while(admin) {
+                                               if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+                                                       break;
+                                               admin = admin->next;
+                                       }
+                                       if (!admin) {
+                                               trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+                                               add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+                                               end_trace();
+                                               continue;
+                                       }
+                                       port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+                               } else
+                                       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);
+                               earlyb = mISDNport->earlyb;
+#else
+                       trace_header("INTERFACE (has no function)", DIRECTION_NONE);
+                       add_trace("interface", NULL, "%s", ifname);
+                       end_trace();
+                       continue;
+#endif
+                       }
                        if (!port)
-                               FATAL("No memory for DSS1 Port instance\n");
+                               FATAL("Failed to create Port instance\n");
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
                        memset(&dialinginfo, 0, sizeof(dialinginfo));
                        SCPY(dialinginfo.id, e_dialinginfo.id);
                        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->earlyb);
-                       if (!portlist)
-                       {
+                       portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 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.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);
@@ -1015,11 +829,13 @@ void EndpointAppPBX::out_setup(void)
                        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));
+                       memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
 //terminal                     SCPY(message->param.setup.from_terminal, e_ext.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, 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.extension, message->param.setup.callerinfo.name));
@@ -1028,17 +844,21 @@ void EndpointAppPBX::out_setup(void)
        //              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.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
-                       {
+                       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->type, &message->param, portlist->port_id, DIRECTION_OUT);
@@ -1047,11 +867,10 @@ void EndpointAppPBX::out_setup(void)
 
                /* 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;
                        }
                }
 
@@ -1061,12 +880,10 @@ void EndpointAppPBX::out_setup(void)
                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.id, p);
 //             i=0;
-               while(*p)
-               {
+               while(*p) {
                        earlyb = 0;
                        /* only if vbox should be dialed, and terminal is given */
-                       if (!strcmp(p, "vbox") && e_ext.number[0])
-                       {
+                       if (!strcmp(p, "vbox") && e_ext.number[0]) {
                                /* go to the end of p */
                                p += strlen(p);
 
@@ -1077,8 +894,7 @@ void EndpointAppPBX::out_setup(void)
                                        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++);
@@ -1086,16 +902,23 @@ void EndpointAppPBX::out_setup(void)
                                        p++;
                                /* external call */
                                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
+#ifdef WITH_MISDN
                                /* hunt for mISDNport and create Port */
                                mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
-                               if (mISDNport)
-                               {
+                               if (mISDNport) {
                                        /* creating EXTERNAL port*/
                                        SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
-                                       if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
-                                               FATAL("No memory for DSS1 Port instance\n");
+#ifdef WITH_SS5
+                                       if (mISDNport->ss5)
+                                               port = ss5_hunt_line(mISDNport);
+                                       else
+#endif
+                                               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
+#endif
                                {
                                        port = NULL;
                                        trace_header("INTERFACE (too busy)", DIRECTION_NONE);
@@ -1103,8 +926,7 @@ void EndpointAppPBX::out_setup(void)
                                        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;
                        }
@@ -1114,8 +936,7 @@ void EndpointAppPBX::out_setup(void)
                        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;
@@ -1126,12 +947,12 @@ void EndpointAppPBX::out_setup(void)
                        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.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);
@@ -1139,6 +960,7 @@ void EndpointAppPBX::out_setup(void)
 //terminal                             SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
                                /* handle restricted caller ids */
                        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.extension, message->param.setup.callerinfo.name));
@@ -1149,24 +971,26 @@ void EndpointAppPBX::out_setup(void)
 
                check_anycall_intern:
                /* now we have all ports created */
-               if (!anycall)
-               {
+               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, join, port */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* 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.id);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
                /* call to extenal interfaces */
-               p = e_dialinginfo.id;
-               do
-               {
+               if (e_dialinginfo.keypad[0])
+                       p = e_dialinginfo.keypad;
+               else
+                       p = e_dialinginfo.id;
+               do {
+                       earlyb = 0;
                        number[0] = '\0';
                        while(*p!=',' && *p!='\0')
                                SCCAT(number, *p++);
@@ -1174,46 +998,107 @@ void EndpointAppPBX::out_setup(void)
                                p++;
                        /* 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 */
-                       /* 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");
+                       /* search interface */
+                       interface = hunt_interface(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL);
+                       if (!interface) {
+                               trace_header("INTERFACE (not found)", DIRECTION_NONE);
+                               add_trace("interface", NULL, "%s", ifname);
                                end_trace();
                                goto check_anycall_extern;
                        }
-                       /* creating EXTERNAL port*/
-                       SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
-                       if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
-                               FATAL("No memory for DSS1 Port instance\n");
-                       earlyb = mISDNport->earlyb;
+                       /* found interface */
+#ifdef WITH_GSM_BS
+                       if (interface->gsm_bs) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
+                               earlyb = (interface->is_earlyb == IS_YES);
+                       } else
+#endif
+#ifdef WITH_GSM_MS
+                       if (interface->gsm_ms) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
+                               earlyb = (interface->is_earlyb == IS_YES);
+                       } else
+#endif
+#ifdef WITH_SIP
+                       if (interface->sip) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+                               earlyb = (interface->is_earlyb == IS_YES);
+                       } else
+#endif
+                       {
+#ifdef WITH_MISDN
+                               /* 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->ifport->interface->name, mISDNport->portnum);
+#ifdef WITH_SS5
+                               if (mISDNport->ss5)
+                                       port = ss5_hunt_line(mISDNport);
+                               else
+#endif
+                               if (mISDNport->ifport->remote) {
+                                       admin = admin_first;
+                                       while(admin) {
+                                               if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+                                                       break;
+                                               admin = admin->next;
+                                       }
+                                       if (!admin) {
+                                               trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+                                               add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+                                               end_trace();
+                                               continue;
+                                       }
+                                       port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+                               } else
+                                       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);
+                               earlyb = mISDNport->earlyb;
+#else
+                               trace_header("INTERFACE (has no function)", DIRECTION_NONE);
+                               add_trace("interface", NULL, "%s", ifname);
+                               end_trace();
+                               continue;
+#endif
+                       }
+                       if (!port)
+                               FATAL("No memory for Port instance\n");
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
                        memset(&dialinginfo, 0, sizeof(dialinginfo));
-                       SCPY(dialinginfo.id, number);
+                       if (e_dialinginfo.keypad[0])
+                               SCPY(dialinginfo.keypad, number);
+                       else
+                               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->earlyb);
-                       if (!portlist)
-                       {
+                       dialinginfo.sending_complete = e_dialinginfo.sending_complete;
+                       portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 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.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.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));
+                       memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
 //terminal                     SCPY(message->param.setup.from_terminal, e_ext.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, 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.extension, message->param.setup.callerinfo.name));
@@ -1224,13 +1109,12 @@ void EndpointAppPBX::out_setup(void)
 
                check_anycall_extern:
                /* now we have all ports created */
-               if (!anycall)
-               {
+               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, join, port */
+                       release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                        return; /* must exit here */
                }
                break;
@@ -1238,182 +1122,157 @@ void EndpointAppPBX::out_setup(void)
 
 }
 
+int action_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
 
-/* handler for endpoint
- */
+       if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
+               return 0;
+
+       unsched_timer(&ea->e_redial_timeout);
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
+       ea->e_multipoint_cause = 0;
+       ea->e_multipoint_location = 0;
+       ea->new_state(EPOINT_STATE_IN_OVERLAP);
+       ea->e_join_pattern = 0;
+       ea->process_dialing(1);
+       /* we must exit, because our endpoint might be gone */
 
-extern int quit;
-int EndpointAppPBX::handler(void)
+       return 0;
+}
+
+int match_timeout(struct lcr_timer *timer, void *instance, int index)
 {
-       if (e_crypt_state!=CM_ST_NULL)
-       {
-               cryptman_handler();
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+       if (!ea->e_action) {
+               unsched_timer(&ea->e_redial_timeout);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
+               ea->process_dialing(0);
+               /* we must exit, because our endpoint might be gone */
        }
 
-       /* process answering machine (play) handling */
-       if (e_action)
-       {
-               if (e_action->index == ACTION_VBOX_PLAY)
-                       vbox_handler();
+       return 0;
+}
 
-               /* process action timeout */
-               if (e_action_timeout)
-               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 = 0;
-                               e_multipoint_location = 0;
-                               new_state(EPOINT_STATE_IN_OVERLAP);
-                               e_join_pattern = 0;
-                               process_dialing();
-                               return(1); /* we must exit, because our endpoint might be gone */
-                       } else
-                               e_action_timeout = 0;
-               }
-       } else {
-               /* process action timeout */
-               if (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();
-                       return(1); /* we must exit, because our endpoint might be gone */
-               }
-       }
+int redial_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
 
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
 
-       /* process redialing (epoint redials to port) */
-       if (e_redial)
-       {
-               if (now_d >= e_redial)
-               {
-                       e_redial = 0;
-                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
+       ea->new_state(EPOINT_STATE_OUT_SETUP);
+       /* call special setup routine */
+       ea->out_setup(0);
 
-                       new_state(EPOINT_STATE_OUT_SETUP);
-                       /* call special setup routine */
-                       out_setup();
+       return 0;
+}
 
-                       return(1);
-               }
-       }
+int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
 
-       /* process powerdialing (epoint redials to epoint) */
-       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);
+       /* leave power dialing on */
+       ea->e_powerdial_on = 1;
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
 
-                       /* redial */
-                       e_ruleset = ruleset_main;
-                       if (e_ruleset)
-                               e_rule = e_ruleset->rule_first;
-                       e_action = NULL;
-                       new_state(EPOINT_STATE_IN_OVERLAP);
-                       process_dialing();
-                       return(1);
-               }
-       }
+       /* redial */
+       ea->e_ruleset = ruleset_main;
+       if (ea->e_ruleset)
+                       ea->e_rule = ea->e_ruleset->rule_first;
+       ea->e_action = NULL;
+       ea->new_state(EPOINT_STATE_IN_OVERLAP);
+       ea->process_dialing(0);
 
-       /* process call forward no response */
-       if (e_cfnr_release)
-       {
-               struct port_list *portlist;
-               struct message *message;
+       return 0;
+}
 
-               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;
+int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+       struct port_list *portlist;
+       struct lcr_msg *message;
 
-                       /* release all ports */
-                       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->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_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-                       message->param.audiopath = CHANNEL_STATE_HOLD;
-                       message_put(message);
-                       /* indicate no patterns */
-                       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
-                       message_put(message);
-                       /* 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)
-               {
-                       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;
-               }
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
+
+       /* release all ports */
+       while((portlist = ea->ea_endpoint->ep_portlist)) {
+               message = message_create(ea->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);
+               ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+               ea->ea_endpoint->free_portlist(portlist);
        }
+       /* put on hold */
+       message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+       message->param.audiopath = 0;
+       message_put(message);
+       /* indicate no patterns */
+       message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
+       message_put(message);
+       /* set setup state, since we have no response from the new join */
+       ea->new_state(EPOINT_STATE_OUT_SETUP);
 
-       /* handle connection to user */
-       if (e_state == EPOINT_STATE_IDLE)
-       {
+       return 0;
+}
+
+int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea->ea_endpoint->ep_serial, ea->e_ext.cfnr);
+       ea->out_setup(1);
+
+       return 0;
+}
+
+int callback_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+       if (ea->e_state == EPOINT_STATE_IDLE) {
                /* epoint is idle, check callback */
-               if (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);
-                       out_setup();
-                       return(1);
-               }
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
+               ea->new_state(EPOINT_STATE_OUT_SETUP);
+               ea->out_setup(0);
        }
 
-       /* check for password timeout */
-       if (e_action)
-       if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
-       {
+       return 0;
+}
+
+int password_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+       class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+       if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
                struct port_list *portlist;
 
-               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);
-                       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)
-                       {
-                               message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
-                               set_tone(portlist, "cause_10");
-                       }
-                       return(1);
+               ea->e_ruleset = ruleset_main;
+               if (ea->e_ruleset)
+                       ea->e_rule = ea->e_ruleset->rule_first;
+               ea->e_action = NULL;
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
+               ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
+               end_trace();
+               ea->e_connectedmode = 0;
+               ea->e_dtmf = 0;
+               ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
+               portlist = ea->ea_endpoint->ep_portlist;
+               if (portlist) {
+                       ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+                       ea->set_tone(portlist, "cause_10");
                }
        }
-       return(0);
-}
 
+       return 0;
+}
 
 /* doing a hookflash */
 void EndpointAppPBX::hookflash(void)
 {
        class Port *port;
+       time_t now;
 
        /* be sure that we are active */
        notify_active();
@@ -1421,8 +1280,7 @@ void EndpointAppPBX::hookflash(void)
 
        trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
        end_trace();
-       if (ea_endpoint->ep_use > 1)
-       {
+       if (ea_endpoint->ep_use > 1) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
                return;
        }
@@ -1431,13 +1289,11 @@ void EndpointAppPBX::hookflash(void)
        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_join_id)
-       {
-               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+       if (ea_endpoint->ep_join_id) {
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
        }
        e_ruleset = ruleset_main;
        if (e_ruleset)
@@ -1448,14 +1304,13 @@ void EndpointAppPBX::hookflash(void)
        SCPY(e_dialinginfo.id, e_ext.prefix);
         e_extdialing = e_dialinginfo.id;
        e_join_pattern = 0;
-       if (e_dialinginfo.id[0])
-       {
+       if (e_dialinginfo.id[0]) {
                set_tone(ea_endpoint->ep_portlist, "dialing");
-               process_dialing();
-       } else
-       {
+               process_dialing(0);
+       } else {
                set_tone(ea_endpoint->ep_portlist, "dialpbx");
        }
+       time(&now);
        e_dtmf_time = now;
        e_dtmf_last = '\0';
 }
@@ -1466,11 +1321,10 @@ 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];
        int                     writeext;               /* flags need to write extension after modification */
        class Port              *port;
-       struct interface        *interface;
 
        logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
        
@@ -1479,40 +1333,36 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
        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;
+       memcpy(&e_rtpinfo, &param->setup.rtpinfo, sizeof(e_rtpinfo));
+
+       /* convert (inter-)national number type */
+       SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
+       e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
+
+//     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 (e_callerinfo.interface[0]) {
+               do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, e_callerinfo.interface);
+               do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, e_callerinfo.interface);
+               do_screen(0, e_redirinfo.id, sizeof(e_redirinfo.id), &e_redirinfo.ntype, &e_redirinfo.present, e_callerinfo.interface);
        }
-       if (interface)
-               do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
 
        /* process extension */
-       if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
-       {
+       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.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);
        }
 
-       if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
-       {
+       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 */
                        trace_header("EXTENSION (not created)", DIRECTION_IN);
                        add_trace("extension", NULL, "%s", e_ext.number);
@@ -1526,14 +1376,12 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
                writeext = 0;
 
                /* put prefix (next) in front of e_dialinginfo.id */
-               if (e_ext.next[0])
-               {
+               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])
-               {
+               } else if (e_ext.prefix[0]) {
                        SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
                        SCPY(e_dialinginfo.id, buffer);
                }
@@ -1543,8 +1391,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
                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)
@@ -1553,8 +1400,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
                        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)
@@ -1562,6 +1408,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
                        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)
@@ -1569,8 +1416,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
 
                /* set volume of rx and tx */
                if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
-               if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
-               {
+               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.rx_gain = e_ext.tx_gain;
@@ -1579,20 +1425,17 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
                }
 
                /* 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';
@@ -1608,19 +1451,16 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
        e_action = NULL;
         e_extdialing = e_dialinginfo.id;
        new_state(EPOINT_STATE_IN_SETUP);
-       if (e_dialinginfo.id[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)
-       {
+       process_dialing(0);
+       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);
@@ -1632,13 +1472,18 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
 /* port MESSAGE_INFORMATION */
 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
 {
+       struct lcr_msg          *message;
+
        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)
-       {
+       if (e_dtmf) {
                trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
                end_trace();
                e_dtmf = 0;
@@ -1646,41 +1491,40 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
 
        /* 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.id, param->information.id);
-               process_dialing();
+               process_dialing(0);
                return;
        }
 
        /* keypad when disconnect but in connected mode */
-       if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
-       {
+       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.id[0] == '0')
-               {
+               if (param->information.id[0] == '0') {
                        hookflash();
                }
                return;
        }
 
        /* keypad when connected */
-       if (e_state == EPOINT_STATE_CONNECT)
-       {
-               if (e_ext.keypad)
-               {
+       if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
+               if (e_enablekeypad) {
+                       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);
+                       return;
+               }
+               if (e_ext.keypad) {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
                        /* processing keypad function */
-                       if (param->information.id[0] == '0')
-                       {
+                       if (param->information.id[0] == '0') {
                                hookflash();
                        }
                        if (param->information.id[0])
                                keypad_function(param->information.id[0]);
-               } else
-               {
+               } else {
                        if (e_ext.number[0])
                                trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
                        else
@@ -1689,8 +1533,7 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
                }
                return;
        }
-       if (e_state != EPOINT_STATE_IN_OVERLAP)
-       {
+       if (e_state != EPOINT_STATE_IN_OVERLAP) {
                if (e_ext.number[0])
                        trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
                else
@@ -1700,14 +1543,13 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
        }
        if (!param->information.id[0])
                return;
-       if (e_dialinginfo.id[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])
@@ -1715,15 +1557,19 @@ void EndpointAppPBX::port_information(struct port_list *portlist, int message_ty
        }
        /* concat dialing string */
        SCAT(e_dialinginfo.id, param->information.id);
-       process_dialing();
+       process_dialing(0);
 }
 
 /* port MESSAGE_DTMF */
 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
 {
+       time_t now;
+       struct lcr_msg          *message;
+
+       time(&now);
+
        /* only if dtmf detection is enabled */
-       if (!e_dtmf)
-       {
+       if (!e_dtmf) {
                trace_header("DTMF (disabled)", DIRECTION_IN);
                end_trace();
                return;
@@ -1736,48 +1582,45 @@ void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, uni
 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.id)+1 < sizeof(e_dialinginfo.id))
-               {
+               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();
+                       process_dialing(0);
                }
                /* continue to process *X# sequences */
        }
 #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_enablekeypad) {
+                       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);
+                       return;
+               }
+               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;
                                        }
@@ -1799,20 +1642,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';
@@ -1820,18 +1659,15 @@ 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.id[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.id)+1 < sizeof(e_dialinginfo.id))
-               {
+               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();
+                       process_dialing(0);
                }
        }
 }
@@ -1839,25 +1675,26 @@ NOTE: vbox is now handled due to overlap state
 /* port MESSAGE_CRYPT */
 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
 {
+#ifdef WITH_CRYPT
        /* send crypt response to cryptman */
        if (param->crypt.type == CR_MESSAGE_IND)
                cryptman_msg2man(param->crypt.data, param->crypt.len);
        else
                cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
+#endif
 }
 
 /* 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);
 
-       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);
@@ -1868,31 +1705,28 @@ void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type,
                e_dialing_queue[0] = '\0';
        }
        /* check if pattern is available */
-       if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* 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_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
                message_put(message);
 
                /* connect audio, if not already */
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_CONNECT;
+               message->param.audiopath = 1;
                message_put(message);
-       } else
-       {
+       } else {
                /* indicate no patterns */
                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_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_HOLD;
+               message->param.audiopath = 0;
                message_put(message);
        }
        new_state(EPOINT_STATE_OUT_OVERLAP);
        /* if we are in a join */
-       if (ea_endpoint->ep_join_id)
-       { 
+       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);
@@ -1902,7 +1736,7 @@ 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);
 
@@ -1911,30 +1745,27 @@ void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_typ
 
        e_state = EPOINT_STATE_OUT_PROCEEDING;
        /* check if pattern is availatle */
-       if (!ea_endpoint->ep_portlist->next && (portlist->early_b || 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_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
                message_put(message);
 
                /* connect audio, if not already */
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_CONNECT;
+               message->param.audiopath = 1;
                message_put(message);
-       } else
-       {
+       } else {
                /* indicate no patterns */
                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_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_HOLD;
+               message->param.audiopath = 0;
                message_put(message);
        }
        /* if we are in a call */
-       if (ea_endpoint->ep_join_id)
-       { 
+       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);
@@ -1944,39 +1775,39 @@ 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");
 
        new_state(EPOINT_STATE_OUT_ALERTING);
        /* check if pattern is available */
-       if (!ea_endpoint->ep_portlist->next && (portlist->early_b || 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_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
                message_put(message);
 
                /* connect audio, if not already */
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_CONNECT;
+               message->param.audiopath = 1;
                message_put(message);
-       } else
-       {
+       } else {
                /* indicate no patterns */
                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_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_HOLD;
+               message->param.audiopath = 0;
                message_put(message);
        }
        /* if we are in a call */
-       if (ea_endpoint->ep_join_id)
-       { 
+       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);
@@ -1986,22 +1817,21 @@ 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;
+       time_t now;
 
        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));
        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;
@@ -2016,20 +1846,11 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        }
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
 
+       time(&now);
        e_start = now;
 
-       /* 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);
+       if (e_callerinfo.interface[0])
+               do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, e_connectinfo.interface);
 
        /* screen connected name */
        if (e_ext.name[0])
@@ -2042,16 +1863,14 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        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.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;
        }
@@ -2059,8 +1878,7 @@ 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.tx_gain!=0 || e_ext.rx_gain!=0)
-       {
+       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.rx_gain = e_ext.tx_gain;
@@ -2068,38 +1886,35 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
                message_put(message);
        }
 
-       e_cfnr_call = e_cfnr_release = 0;
+       unsched_timer(&e_cfnr_timeout);
+       unsched_timer(&e_cfnr_call_timeout);
        if (e_ext.number[0])
                e_dtmf = 1; /* allow dtmf */
 
        /* 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 */
-               {
+       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_CLASS_DIR_MASK) == PORT_CLASS_DIR_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));
+                       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;
                        }
                }
        }
 
        /* send connect to join */
-       if (ea_endpoint->ep_join_id)
-       {
+       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);
 
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_CONNECT;
+               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);
@@ -2107,8 +1922,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, "");
@@ -2126,66 +1940,58 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
                /* use caller id (or if exist: id_next_call) for this call */
                e_callerinfo.screen = INFO_SCREEN_NETWORK;
                SCPY(e_callerinfo.extension, e_ext.number);
-               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);
                        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;
+                       unsched_timer(&e_match_timeout);
                        e_match_to_action = NULL;
                        e_dialinginfo.id[0] = '\0';
                        e_extdialing = strchr(e_dialinginfo.id, '\0');
-                       e_password_timeout = now+20;
-                       process_dialing();
-               } else
-               {
+                       schedule_timer(&e_password_timeout, 20, 0);
+                       process_dialing(0);
+               } else {
                        /* incoming call (callback) */
                        e_ruleset = ruleset_main;
                        if (e_ruleset)
                                e_rule = e_ruleset->rule_first;
                        e_action = NULL;
                        e_extdialing = e_dialinginfo.id;
-                       if (e_dialinginfo.id[0])
-                       {
+                       if (e_dialinginfo.id[0]) {
                                set_tone(portlist, "dialing");
-                               process_dialing();
-                       } else
-                       {
+                               process_dialing(0);
+                       } 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);
@@ -2196,9 +2002,9 @@ 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;
 
@@ -2208,8 +2014,7 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
        admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
 
 //#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;
        }
@@ -2220,20 +2025,17 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
        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)
                        FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
-               if (message_type != MESSAGE_RELEASE)
-               {
+               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;
@@ -2243,34 +2045,30 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
                ea_endpoint->free_portlist(portlist);
                return; /* one relation removed */ 
        }
-       if (e_state == EPOINT_STATE_CONNECT)
-       {
+       if (e_state == EPOINT_STATE_CONNECT) {
                /* use cause from port after connect */
                cause = param->disconnectinfo.cause;
                location = param->disconnectinfo.location;
-       } else
-       {
+       } else {
                /* use multipoint cause if no connect yet */
-               if (e_multipoint_cause)
-               {
+               if (e_multipoint_cause) {
                        cause = e_multipoint_cause;
                        location = e_multipoint_location;
-               } else
-               {
+               } else {
                        cause = CAUSE_NOUSER;
                        location = LOCATION_PRIVATE_LOCAL;
                }
        }
 
-       e_cfnr_call = e_cfnr_release = 0;
+       unsched_timer(&e_cfnr_timeout);
+       unsched_timer(&e_cfnr_call_timeout);
 
        /* process hangup */
        process_hangup(e_join_cause, e_join_location);
        e_multipoint_cause = 0;
        e_multipoint_location = 0;
 
-       if (message_type == MESSAGE_DISCONNECT)
-       {
+       if (message_type == MESSAGE_DISCONNECT) {
                /* tone to disconnected end */
                SPRINT(buffer, "cause_%02x", cause);
                if (ea_endpoint->ep_portlist)
@@ -2279,8 +2077,7 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
                new_state(EPOINT_STATE_IN_DISCONNECT);
        }
 
-       if (ea_endpoint->ep_join_id)
-       {
+       if (ea_endpoint->ep_join_id) {
                int haspatterns = 0;
                /* check if pattern is available */
                if (ea_endpoint->ep_portlist)
@@ -2288,15 +2085,14 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
                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_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
                        message_put(message);
                        /* connect audio, if not already */
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-                       message->param.audiopath = CHANNEL_STATE_CONNECT;
+                       message->param.audiopath = 1;
                        message_put(message);
                        /* send disconnect */
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
@@ -2304,17 +2100,18 @@ void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int mes
                        message_put(message);
                        /* disable encryption if disconnected */
 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
+#ifdef WITH_CRYPT
                        if (e_crypt_state)
                                cryptman_message(CI_DISCONNECT_IND, NULL, 0);
+#endif
                        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 */
+       release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
        return; /* must exit here */
 }
 
@@ -2325,14 +2122,13 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
 
        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);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_IN_SETUP:
@@ -2347,7 +2143,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                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);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_IN_PROCEEDING:
@@ -2361,7 +2157,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                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);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_CONNECT:
@@ -2369,7 +2165,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                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);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                case PORT_STATE_IN_ALERTING:
@@ -2383,7 +2179,7 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
                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);
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
                return; /* must exit here */
 
                default:
@@ -2396,13 +2192,12 @@ void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type,
        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_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
 }
 
 /* port MESSAGE_NOTIFY */
@@ -2410,27 +2205,24 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
 {
        logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
-       struct message *message;
-       char *logtext = "";
+       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_join_id)
-               {
+               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 = CHANNEL_STATE_HOLD;
+                       message->param.audiopath = 0;
                        message_put(message);
                }
                break;
@@ -2440,8 +2232,7 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
                /* set volume of rx and tx */
                if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
                if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
-               if (portlist)
-               {
+               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.rx_gain = e_ext.tx_gain;
@@ -2452,18 +2243,16 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
                if (portlist)
                        set_tone(portlist, e_tone);
                /* tell call about it */
-               if (ea_endpoint->ep_join_id)
-               {
+               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 = CHANNEL_STATE_CONNECT;
+                       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;
@@ -2543,8 +2332,7 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
        }
 
        /* notify call if available */
-       if (ea_endpoint->ep_join_id)
-       {
+       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);
@@ -2552,12 +2340,31 @@ void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, u
 
 }
 
+/* port MESSAGE_PROGRESS */
+void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
+{
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+       struct lcr_msg *message;
+
+       /* signal to call tool */
+       admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
+
+       /* send progress to call if available */
+       if (ea_endpoint->ep_join_id) {
+               message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
+               memcpy(&message->param.progressinfo, &param->progressinfo, sizeof(struct progress_info));
+               message_put(message);
+       }
+
+}
+
 /* port MESSAGE_FACILITY */
 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
 {
        logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
 
-       struct message *message;
+       struct lcr_msg *message;
 
        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));
@@ -2590,51 +2397,45 @@ void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, u
 
 }
 
+/* port MESSAGE_ENABLEKEYPAD */
+void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
+{
+       struct lcr_msg *message;
+
+       logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+       message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
+       memcpy(&message->param, param, sizeof(union parameter));
+       message_put(message);
+}
+
 
 /* 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;
 
        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)
-       {
-               case MESSAGE_DATA: /* data from port */
-               /* check if there is a call */
-               if (!ea_endpoint->ep_join_id)
-                       break;
-               /* continue if only one portlist */
-               if (ea_endpoint->ep_portlist->next != NULL)
-                       break;
-               /* forward message */
-               message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);  
-               break;
-
+       switch(message_type) {
                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();
                        }
                }
@@ -2643,8 +2444,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;
@@ -2654,8 +2454,7 @@ 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.id);
-               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);
                        break;
                }
@@ -2689,8 +2488,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;
                }
@@ -2701,8 +2499,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;
                }
@@ -2714,8 +2511,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;
                }
@@ -2728,8 +2524,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;
                }
@@ -2761,6 +2556,12 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                port_notify(portlist, message_type, param);
                break;
 
+               /* PORT sends a PROGRESS message */
+               case MESSAGE_PROGRESS:
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received progress.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               port_progress(portlist, message_type, param);
+               break;
+
                /* PORT sends a SUSPEND message */
                case MESSAGE_SUSPEND:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
@@ -2774,6 +2575,7 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                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);
@@ -2783,9 +2585,15 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                break;
 #endif
 
+               /* PORT requests DTMF */
+               case MESSAGE_ENABLEKEYPAD:
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') requests DTMF/KEYPAD.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               port_enablekeypad(portlist, message_type, param);
+               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);
        }
 
        /* Note: this endpoint may be destroyed, so we MUST return */
@@ -2797,8 +2605,8 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
 /* join MESSAGE_CRYPT */
 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
 {
-       switch(param->crypt.type)
-       {
+#ifdef WITH_CRYPT
+       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 */
@@ -2821,17 +2629,17 @@ void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, un
                default:
                PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
        }
+#endif
 }
 
 /* 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);
@@ -2843,15 +2651,13 @@ void EndpointAppPBX::join_information(struct port_list *portlist, int message_ty
 /* 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 && e_ext.number[0])
-       {
+       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);
@@ -2863,53 +2669,53 @@ void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type,
 /* 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_join_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_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-               message->param.audiopath = CHANNEL_STATE_HOLD;
+               message->param.audiopath = 0;
                message_put(message);
        }
-       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) {
                        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");
+       }
 }
 
 /* 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_join_pattern)
-       {
+       if (e_join_pattern) {
                /* connect / disconnect audio */
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
                if (e_ext.own_proceeding)
-                       message->param.audiopath = CHANNEL_STATE_HOLD;
+                       message->param.audiopath = 0;
                else
-                       message->param.audiopath = CHANNEL_STATE_CONNECT;
+                       message->param.audiopath = 1;
                message_put(message);
        }
 //                     UCPY(e_join_tone, "proceeding");
-       if (portlist)
-       {
+       if (portlist) {
                message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
                message_put(message);
                logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
@@ -2920,29 +2726,26 @@ void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_typ
 /* 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_join_pattern)
-       {
+       if (e_join_pattern) {
                /* connect / disconnect audio */
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
                if (e_ext.own_alerting)
-                       message->param.audiopath = CHANNEL_STATE_HOLD;
+                       message->param.audiopath = 0;
                else
-                       message->param.audiopath = 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->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;
        }
@@ -2950,35 +2753,39 @@ void EndpointAppPBX::join_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 */
 }
 
 /* join MESSAGE_CONNECT */
 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
 {
-       struct message *message;
+       struct lcr_msg *message;
+       time_t now;
 
        new_state(EPOINT_STATE_CONNECT);
 //                     UCPY(e_join_tone, "");
+//                     
        if (e_ext.number[0])
                e_dtmf = 1; /* allow dtmf */
-       e_powerdialing = 0;
+
+       e_powerdial_on = 0;
+       unsched_timer(&e_powerdial_timeout);
        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 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.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
-               {
+               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;
                }
@@ -2999,8 +2806,9 @@ void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type,
        set_tone(portlist, NULL);
        e_join_pattern = 0;
        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-       message->param.audiopath = CHANNEL_STATE_CONNECT;
+       message->param.audiopath = 1;
        message_put(message);
+       time(&now);
        e_start = now;
 }
 
@@ -3008,36 +2816,33 @@ void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type,
 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;
+       time_t now;
 
 
        /* be sure that we are active */
        notify_active();
        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_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+       /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
+       if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
+               release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
 
                /* set time for power dialing */
-               e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
+               schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
                e_powercount++;
 
                /* set redial tone */
-               if (ea_endpoint->ep_portlist)
-               {
+               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 (ea_endpoint->ep_portlist)
-                       {
+                       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->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
@@ -3046,11 +2851,9 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
 /*                                     set_tone(portlist, "proceeding"); */
                }
                /* send display of powerdialing */
-               if (e_ext.display_dialing)
-               {
+               if (e_ext.display_dialing) {
                        portlist = ea_endpoint->ep_portlist;
-                       while (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);
@@ -3065,6 +2868,7 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
        }
 
        /* set stop time */
+       time(&now);
        e_stop = now;
 
        if ((e_state!=EPOINT_STATE_CONNECT
@@ -3072,22 +2876,19 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
          && 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, join, port */
+               release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
                return; /* must exit here */
        }
        /* save cause */
-       if (!e_join_cause)
-       {
+       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)
-       {
+       if (message_type == MESSAGE_RELEASE) {
                e_join_pattern = 0;
                ea_endpoint->ep_join_id = 0;
        }
@@ -3096,23 +2897,20 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
        SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
        /* if own_cause, we must release the join */
        if (e_ext.own_cause /* own cause */
-        || !e_join_pattern) /* no patterns */
-       {
+        || !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_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+                       release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
                e_join_pattern = 0;
-       } else /* else we enable audio */
-       {
+       } 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 = CHANNEL_STATE_CONNECT;
+               message->param.audiopath = 1;
                message_put(message);
        }
        /* send disconnect message */
        SCPY(e_tone, cause);
        portlist = ea_endpoint->ep_portlist;
-       while(portlist)
-       {
+       while(portlist) {
                set_tone(portlist, cause);
                message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
                portlist = portlist->next;
@@ -3122,21 +2920,18 @@ void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *
 /* 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.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
-               {
+               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;
@@ -3147,7 +2942,7 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
 
                        /* disconnect audio */
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-                       message->param.audiopath = CHANNEL_STATE_HOLD;
+                       message->param.audiopath = 0;
                        message_put(message);
 
                        /* get dialing info */
@@ -3158,32 +2953,27 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
                        new_state(EPOINT_STATE_OUT_OVERLAP);
 
                        /* get time */
-                       e_redial = now_d + 1; /* set redial one second in the future */
+                       schedule_timer(&e_redial_timeout, 1, 0);
                        return;
                }
                /* if we have a pending redial, so we just adjust the dialing number */
-               if (e_redial)
-               {
+               if (e_redial_timeout.active) {
                        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.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.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);
@@ -3197,8 +2987,7 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
                
                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;
        }
@@ -3206,10 +2995,8 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
        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);
                }
@@ -3219,10 +3006,10 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
        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));
+       memcpy(&e_rtpinfo, &param->setup.rtpinfo, sizeof(e_rtpinfo));
 
        /* 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;
@@ -3232,16 +3019,15 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
 
        new_state(EPOINT_STATE_OUT_SETUP);
        /* call special setup routine */
-       out_setup();
+       out_setup(0);
 }
 
 /* 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);
@@ -3249,28 +3035,36 @@ void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_ty
        }
 }
 
+/* join MESSAGE_BRIDE */
+void EndpointAppPBX::join_bridge(struct port_list *portlist, int message_type, union parameter *param)
+{
+       struct lcr_msg *message;
+
+       while(portlist) {
+               message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
+               memcpy(&message->param, param, sizeof(union parameter));
+               message_put(message);
+               portlist = portlist->next;
+       }
+}
+
 /* join MESSAGE_NOTIFY */
 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
 {
-       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)
-                               {
-                                       if (!strcmp(e_tone, "hold")) // don't interrupt other tones
-                                       {
-                                               while(portlist)
-                                               {
+                               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;
                                                }
@@ -3280,10 +3074,8 @@ void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, u
                                }
                        } 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;
                                        }
@@ -3297,8 +3089,7 @@ void EndpointAppPBX::join_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 */
@@ -3311,41 +3102,35 @@ void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, u
        }
 }
 
+/* join MESSAGE_DTMF */
+void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, union parameter *param)
+{
+       struct lcr_msg *message;
+
+       while(portlist) {
+               message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DTMF);
+               memcpy(&message->param, param, sizeof(union parameter));
+               message_put(message);
+               portlist = portlist->next;
+       }
+}
+
 /* JOIN sends messages to the endpoint
  */
-void EndpointAppPBX::ea_message_join(unsigned long join_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 (!join_id)
-       {
+       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 (message_type == MESSAGE_DATA)
-       {
-               if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
-               {
-                       /* skip if no port relation */
-                       if (!portlist)
-                               return;
-                       /* skip if more than one port relation */
-                       if (portlist->next)
-                               return;
-                       /* forward audio data to port */
-                       message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
-                       return;
-               }
-       }
-
 //     PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
-       switch(message_type)
-       {
+       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);
@@ -3372,10 +3157,9 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
 
                /* 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;
                }
@@ -3385,8 +3169,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                /* 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;
                }
@@ -3397,8 +3180,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                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;
                }
@@ -3410,8 +3192,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                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;
                }
@@ -3437,58 +3218,39 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_mISDNsignal(portlist, message_type, param);
                break;
 
-#if 0
-               /* JOIN requests bchannel */
-               case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
-               /* only one port is expected to be connected to bchannel */
-               if (!portlist)
-                       break;
-               if (portlist->next)
-                       break;
-               e_join_pattern = 1;
-               SCPY(e_tone, "");
-               set_tone(portlist, NULL);
-               message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
-               logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+               /* JOIN sends bridge message */
+               case MESSAGE_BRIDGE: /* bride message to port */
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bridge message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               join_bridge(portlist, message_type, param);
                break;
-#endif
 
                /* JOIN has pattern available */
                case MESSAGE_PATTERN: /* indicating pattern available */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
-               if (!e_join_pattern)
-               {
+               if (!e_join_pattern) {
                        PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
                        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_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-                       message->param.audiopath = CHANNEL_STATE_CONNECT;
+                       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_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
-//                     message->param.audiopath = CHANNEL_STATE_CONNECT;
-//                     message_put(message);
-// patterns are available, remote already connected audio
                }
                break;
 
                /* JOIN has no pattern available */
                case MESSAGE_NOPATTERN: /* indicating no pattern available */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
-               if (e_join_pattern)
-               {
+               if (e_join_pattern) {
                        PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
                        e_join_pattern = 0;
                        /* disconnect our audio tx and rx */
                        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-                       message->param.audiopath = CHANNEL_STATE_HOLD;
+                       message->param.audiopath = 0;
                        message_put(message);
                }
                break;
@@ -3509,8 +3271,23 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                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;
+
+               /* JOIN sends a DTMF message */
+               case MESSAGE_DTMF:
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received dtmf.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               join_dtmf(portlist, message_type, param);
+               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);
        }
 }
 
@@ -3526,13 +3303,11 @@ int match_list(char *list, char *item)
        if (!list)
                return(1);
 
-       while(42)
-       {
+       while(42) {
                /* eliminate white spaces */
-               while (*list <= ' ')
+               while (*list > '\0' && *list <= ' ')
                        list++;
-               if (*list == ',')
-               {
+               if (*list == ',') {
                        list++;
                        continue;
                }
@@ -3555,7 +3330,7 @@ int match_list(char *list, char *item)
 
 void EndpointAppPBX::pick_join(char *extensions)
 {
-       struct message *message;
+       struct lcr_msg *message;
        struct port_list *portlist;
        class Port *port;
        class EndpointAppPBX *eapp, *found;
@@ -3568,28 +3343,21 @@ void EndpointAppPBX::pick_join(char *extensions)
        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 ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_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;
                                                }
                                }
@@ -3602,8 +3370,7 @@ void EndpointAppPBX::pick_join(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");
@@ -3613,39 +3380,32 @@ reject:
        }
        eapp = found;
 
-       if (ea_endpoint->ep_join_id)
-       {
+       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_join_id)
-       {
+       if (!eapp->ea_endpoint->ep_join_id) {
                PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
                goto reject;
        }
        join = find_join_id(eapp->ea_endpoint->ep_join_id);
-       if (!join)
-       {
+       if (!join) {
                PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
                goto reject;
        }
-       if (join->j_type != JOIN_TYPE_PBX)
-       {
+       if (join->j_type != JOIN_TYPE_PBX) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
                goto reject;
        }
        joinpbx = (class JoinPBX *)join;
        relation = joinpbx->j_relation;
-       if (!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)
-               {
+               if (!relation) {
                        PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
                        goto reject;
                }
@@ -3653,8 +3413,7 @@ 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)
-       {
+       if (options.deb & DEBUG_EPOINT) {
                class Join *debug_c = join_first;
                class Endpoint *debug_e = epoint_first;
                class Port *debug_p = port_first;
@@ -3662,20 +3421,17 @@ reject:
                joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
 
                PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
-               while(debug_c)
-               {
+               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)
-               {
+               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;
                }
@@ -3688,7 +3444,8 @@ reject:
 
        /* 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 */
@@ -3721,14 +3478,13 @@ reject:
 
        /* we send a connect to the audio path (not for vbox) */
        message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
-       message->param.audiopath = CHANNEL_STATE_CONNECT;
+       message->param.audiopath = 1;
        message_put(message);
 
        /* beeing paranoid, we make call update */
-       joinpbx->j_updatebridge = 1;
+       trigger_work(&joinpbx->j_updatebridge);
 
-       if (options.deb & DEBUG_EPOINT)
-       {
+       if (options.deb & DEBUG_EPOINT) {
                class Join *debug_c = join_first;
                class Endpoint *debug_e = epoint_first;
                class Port *debug_p = port_first;
@@ -3736,20 +3492,17 @@ reject:
                joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
 
                PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
-               while(debug_c)
-               {
+               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)
-               {
+               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;
                }
@@ -3761,7 +3514,8 @@ reject:
  */
 void EndpointAppPBX::join_join(void)
 {
-       struct message *message;
+#ifdef WITH_MISDN
+       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;
@@ -3770,37 +3524,31 @@ void EndpointAppPBX::join_join(void)
        class Port *our_port, *other_port;
        class Pdss1 *our_pdss1, *other_pdss1;
 
-       /* are we a candidate to join a join */
+       /* are we a candidate to join a join? */
        our_join = find_join_id(ea_endpoint->ep_join_id);
-       if (!our_join)
-       {
+       if (!our_join) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
                return;
        }
-       if (our_join->j_type != JOIN_TYPE_PBX)
-       {
+       if (our_join->j_type != JOIN_TYPE_PBX) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
                return;
        }
        our_joinpbx = (class JoinPBX *)our_join;
-       if (!ea_endpoint->ep_portlist)
-       {
+       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_DSS1) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
                return;
        }
@@ -3808,68 +3556,56 @@ void EndpointAppPBX::join_join(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 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_join_id) /* has join */
-               {
+                && 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 join */
-       if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
-       {
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
+       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_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
-       if (!other_join)
-       {
+       if (!other_join) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
                return;
        }
-       if (other_join->j_type != JOIN_TYPE_PBX)
-       {
+       if (other_join->j_type != JOIN_TYPE_PBX) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
                return;
        }
        other_joinpbx = (class JoinPBX *)other_join;
-       if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
-       {
+       if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
                return;
        }
@@ -3877,10 +3613,8 @@ void EndpointAppPBX::join_join(void)
        /* 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)
-               {
+       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;
                        FREE(other_relation, sizeof(struct join_relation));
@@ -3892,8 +3626,7 @@ void EndpointAppPBX::join_join(void)
 
                /* 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) {
                        if (temp_epoint->ep_join_id == other_join->j_serial)
                                temp_epoint->ep_join_id = our_join->j_serial;
                }
@@ -3906,8 +3639,7 @@ void EndpointAppPBX::join_join(void)
        /* join call relations */
        our_relation = our_joinpbx->j_relation;
        our_relation_pointer = &our_joinpbx->j_relation;
-       while(our_relation)
-       {
+       while(our_relation) {
                our_relation_pointer = &our_relation->next;
                our_relation = our_relation->next;
        }
@@ -3929,17 +3661,20 @@ void EndpointAppPBX::join_join(void)
        PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
 
        /* mixer must update */
-       our_joinpbx->j_updatebridge = 1; /* update mixer flag */
+       trigger_work(&our_joinpbx->j_updatebridge);
 
        /* we send a retrieve to that endpoint */
        // mixer will update the hold-state of the join and send it to the endpoints is changes
+#else
+       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
+#endif
 }
 
 
 /* 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 join_relation *relation;
        class Join *join;
@@ -3947,14 +3682,12 @@ int EndpointAppPBX::check_external(char **errstr, class Port **port)
        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);
@@ -3962,43 +3695,36 @@ int EndpointAppPBX::check_external(char **errstr, class Port **port)
 
        /* check if we have a join with 2 parties */
        join = find_join_id(ea_endpoint->ep_join_id);
-       if (!join)
-       {
+       if (!join) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
                *errstr = "No Call";
                return(1);
        }
-       if (join->j_type != JOIN_TYPE_PBX)
-       {
+       if (join->j_type != JOIN_TYPE_PBX) {
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
                *errstr = "No PBX Call";
                return(1);
        }
        joinpbx = (class JoinPBX *)join;
        relation = joinpbx->j_relation;
-       if (!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)
-       {
+       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)
-       {
+       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)
-               {
+               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);
@@ -4007,33 +3733,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)
-       {
+       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_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);
@@ -4041,13 +3762,12 @@ int EndpointAppPBX::check_external(char **errstr, class Port **port)
        return(0);
 }
 
-void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
+void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
 {
-       char *logtext = "unknown";
+       const char *logtext = "unknown";
        char buffer[64];
 
-       switch(message_type)
-       {
+       switch(message_type) {
                case MESSAGE_SETUP:
                trace_header("SETUP", dir);
                if (dir == DIRECTION_OUT)
@@ -4056,9 +3776,8 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                        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));
-               switch(param->setup.callerinfo.present)
-               {
+               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;
@@ -4068,11 +3787,22 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                        default:
                        add_trace("caller id", "present", "not available");
                }
-               if (param->setup.redirinfo.id[0])
-               {
-                       add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
-                       switch(param->setup.redirinfo.present)
-                       {
+               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 (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;
@@ -4085,6 +3815,12 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                }
                if (param->setup.dialinginfo.id[0])
                        add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
+               if (param->setup.dialinginfo.keypad[0])
+                       add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
+               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;
 
@@ -4123,9 +3859,8 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                        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));
-               switch(param->connectinfo.present)
-               {
+               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;
@@ -4135,6 +3870,8 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                        default:
                        add_trace("connect id", "present", "not available");
                }
+               if (param->connectinfo.display[0])
+                       add_trace("display", NULL, "%s", param->connectinfo.display);
                end_trace();
                break;
 
@@ -4149,8 +3886,7 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                if (dir == DIRECTION_IN)
                        add_trace("from", NULL, "CH(%lu)", port_id);
                add_trace("cause", "value", "%d", param->disconnectinfo.cause);
-               switch(param->disconnectinfo.location)
-               {
+               switch(param->disconnectinfo.location) {
                        case LOCATION_USER:
                        add_trace("cause", "location", "0-User");
                        break;
@@ -4178,12 +3914,13 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                        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(param->notifyinfo.notify)
-               {
+               switch(param->notifyinfo.notify) {
                        case 0x00:
                        logtext = "NULL";
                        break;
@@ -4268,11 +4005,9 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                        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));
-                       switch(param->notifyinfo.present)
-                       {
+               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;
@@ -4288,13 +4023,77 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                end_trace();
                break;
 
+               case MESSAGE_PROGRESS:
+               switch(param->progressinfo.progress) {
+                       case 0x01:
+                       logtext = "Call is not end to end ISDN";
+                       break;
+                       case 0x02:
+                       logtext = "Destination address is non-ISDN";
+                       break;
+                       case 0x03:
+                       logtext = "Origination address is non-ISDN";
+                       break;
+                       case 0x04:
+                       logtext = "Call has returned to the ISDN";
+                       break;
+                       case 0x08:
+                       logtext = "In-band info or pattern available";
+                       break;
+                       default:
+                       SPRINT(buffer, "%d", param->progressinfo.progress);
+                       logtext = buffer;
+
+               }
+               trace_header("PROGRESS", 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("indicator", NULL, "%s", logtext);
+               switch(param->progressinfo.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->progressinfo.location);
+               }
+               end_trace();
+               break;
+
                case MESSAGE_INFORMATION:
                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);
-               add_trace("dialing", NULL, "%s", param->information.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;
 
@@ -4313,8 +4112,7 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                        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])
-               {
+               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
@@ -4340,8 +4138,7 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
 #if 0
                case MESSAGE_BCHANNEL:
                trace_header("BCHANNEL", dir);
-               switch(param->bchannel.type)
-               {
+               switch(param->bchannel.type) {
                        case BCHANNEL_REQUEST:
                        add_trace("type", NULL, "request");
                        break;
@@ -4369,17 +4166,16 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
        }
 }
 
-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;
@@ -4387,8 +4183,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);
@@ -4399,4 +4194,3 @@ void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cau
        logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
 }
 
-