Added support of mISDN to direct bridge feature
[lcr.git] / apppbx.cpp
index 1b119b2..bacdba9 100644 (file)
@@ -26,12 +26,14 @@ 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));
@@ -72,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;
@@ -103,10 +106,12 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp
        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;
@@ -130,7 +135,9 @@ 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);
@@ -271,10 +278,12 @@ void EndpointAppPBX::release(int release, int joinlocation, int joincause, int p
                        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';
@@ -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);
@@ -574,257 +585,6 @@ void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
 }
 
 
-/*
- * 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;
-       int there_is_an_external = 0;
-
-       interface = interface_first;
-
-       /* first find the given interface or, if not given, one with no extension */
-       checknext:
-       if (!interface) {
-               if (!there_is_an_external && !(ifname && ifname[0])) {
-                       trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
-                       add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
-                       end_trace();
-               }
-               return(NULL);
-       }
-
-       /* check for given interface */
-       if (ifname && ifname[0]) {
-               if (!strcasecmp(interface->name, ifname)) {
-                       /* found explicit interface */
-                       trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
-                       add_trace("interface", NULL, "%s", ifname);
-                       end_trace();
-                       goto foundif;
-               }
-
-       } else {
-               if (interface->external) {
-                       there_is_an_external = 1;
-                       /* found non extension */
-                       trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
-                       add_trace("interface", NULL, "%s", interface->name);
-                       end_trace();
-                       goto foundif;
-               }
-       }
-
-       interface = interface->next;
-       goto checknext;
-foundif:
-
-       /* see if interface has ports */
-       if (!interface->ifport) {
-               /* no ports */
-               trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
-               add_trace("interface", NULL, "%s", interface->name);
-               end_trace();
-               interface = interface->next;
-               goto checknext;
-       }
-
-       /* select port by algorithm */
-       ifport_start = interface->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<1) {
-               trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
-               add_trace("port", NULL, "%d", ifport->portnum);
-               add_trace("position", NULL, "%d", index);
-               end_trace();
-               goto portbusy;
-       }
-
-       /* check for channel form selection list */
-       *channel = 0;
-#ifdef WITH_SS5
-       if (mISDNport->ss5) {
-               class Pss5 *port;
-               port = ss5_hunt_line(mISDNport);
-               if (port) {
-                       *channel = port->p_m_b_channel;
-                       trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
-                       add_trace("port", NULL, "%d", ifport->portnum);
-                       add_trace("position", NULL, "%d", index);
-                       add_trace("channel", NULL, "%d", *channel);
-                       end_trace();
-               }
-       } else
-#endif
-       {
-               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;
-
-       if (!ifname) {
-               interface = interface->next;
-               goto checknext;
-       }
-
-       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.
@@ -839,7 +599,10 @@ void EndpointAppPBX::out_setup(int cfnr)
        int                     cause = CAUSE_RESSOURCEUNAVAIL;
        const char              *p;
        char                    cfp[64];
+       struct interface        *interface;
+#ifdef WITH_MISDN
        struct mISDNport        *mISDNport;
+#endif
        char                    portname[32];
        char                    *dirname;
        class EndpointAppPBX    *atemp;
@@ -848,10 +611,12 @@ void EndpointAppPBX::out_setup(int cfnr)
        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;
-       struct admin_list       *admin;
 
        /* set bchannel mode */
        mode = e_capainfo.source_mode;
@@ -957,60 +722,85 @@ void EndpointAppPBX::out_setup(int cfnr)
                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) {
+                       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);
-#ifdef WITH_SS5
-                       if (mISDNport->ss5)
-                               port = ss5_hunt_line(mISDNport);
-                       else
-#endif
+                       /* found interface */
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
 #ifdef WITH_GSM_BS
-                       if (mISDNport->gsm_bs)
-                               port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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 (mISDNport->gsm_ms)
-                               port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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 (mISDNport->ifport->interface->sip)
-                               port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
-                       else
+#ifdef WITH_GSM_MS
+                       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
-                       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);
+                       {
+#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;
                                }
-                               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);
+
+                               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("Failed to create Port instance\n");
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
@@ -1019,7 +809,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        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);
+                       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;
@@ -1039,6 +829,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        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);
@@ -1111,6 +902,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                                        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) {
@@ -1125,7 +917,9 @@ void EndpointAppPBX::out_setup(int cfnr)
                                        if (!port)
                                                FATAL("No memory for Port instance\n");
                                        earlyb = mISDNport->earlyb;
-                               } else {
+                               } else
+#endif
+                               {
                                        port = NULL;
                                        trace_header("INTERFACE (too busy)", DIRECTION_NONE);
                                        add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
@@ -1196,6 +990,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                else
                        p = e_dialinginfo.id;
                do {
+                       earlyb = 0;
                        number[0] = '\0';
                        while(*p!=',' && *p!='\0')
                                SCCAT(number, *p++);
@@ -1203,56 +998,79 @@ void EndpointAppPBX::out_setup(int cfnr)
                                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);
-#ifdef WITH_SS5
-                       if (mISDNport->ss5)
-                               port = ss5_hunt_line(mISDNport);
-                       else
-#endif
+                       /* found interface */
 #ifdef WITH_GSM_BS
-                       if (mISDNport->gsm_bs)
-                               port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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 (mISDNport->gsm_ms)
-                               port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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 (mISDNport->ifport->interface->sip)
-                               port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
-                       else
+#ifdef WITH_GSM_MS
+                       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
-                       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);
+                       {
+#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();
-                                       continue;
+                                       goto check_anycall_extern;
                                }
-                               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);
+                               /* 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");
-                       earlyb = mISDNport->earlyb;
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
                        memset(&dialinginfo, 0, sizeof(dialinginfo));
                        if (e_dialinginfo.keypad[0])
@@ -1262,7 +1080,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        dialinginfo.itype = INFO_ITYPE_ISDN;
                        dialinginfo.ntype = e_dialinginfo.ntype;
                        dialinginfo.sending_complete = e_dialinginfo.sending_complete;
-                       portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
+                       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;
@@ -1274,6 +1092,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        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);
@@ -1506,7 +1325,6 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
        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);
        
@@ -1515,6 +1333,7 @@ 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));
+       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));
@@ -1522,16 +1341,9 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
 
 //     e_dtmf = param->setup.dtmf;
        /* screen incoming caller id */
-       interface = interface_first;
-       while(interface) {
-               if (!strcmp(e_callerinfo.interface, interface->name)) {
-                       break;
-               }
-               interface = interface->next;
-       }
-       if (interface) {
-               do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
-               do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
+       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);
        }
 
        /* process extension */
@@ -1862,11 +1674,13 @@ 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 */
@@ -2007,7 +1821,6 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        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);
@@ -2035,16 +1848,8 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        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])
@@ -2294,8 +2099,10 @@ 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 {
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
@@ -2797,6 +2604,7 @@ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, uni
 /* join MESSAGE_CRYPT */
 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
 {
+#ifdef WITH_CRYPT
        switch(param->crypt.type) {
                /* message from remote port to "crypt manager" */
                case CU_ACTK_REQ:           /* activate key-exchange */
@@ -2820,6 +2628,7 @@ 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 */
@@ -3196,6 +3005,7 @@ 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) {
@@ -3703,6 +3513,7 @@ reject:
  */
 void EndpointAppPBX::join_join(void)
 {
+#ifdef WITH_MISDN
        struct lcr_msg *message;
        struct join_relation *our_relation, *other_relation;
        struct join_relation **our_relation_pointer, **other_relation_pointer;
@@ -3853,6 +3664,9 @@ void EndpointAppPBX::join_join(void)
 
        /* 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
 }