Fix: Send tones/patterns/announcements for remote connections
[lcr.git] / remote.cpp
index e7b9009..6fcb64b 100644 (file)
@@ -16,24 +16,24 @@ unsigned int new_remote = 1000;
 /*
  * constructor
  */
-Premote::Premote(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, int remote_id) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+Premote::Premote(int type, char *portname, struct port_settings *settings, struct interface *interface, int remote_id) : Port(type, portname, settings, interface)
 {
        union parameter param;
 
-       p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
-       p_m_r_ref = new_remote++;
-       SCPY(p_m_r_remote_app, mISDNport->ifport->remote_app);
-       p_m_r_handle = 0;
+       p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
+       p_r_ref = new_remote++;
+       SCPY(p_r_remote_app, interface->remote_app);
+       p_r_tones = (interface->is_tones == IS_YES);
 
        /* send new ref to remote socket */
        memset(&param, 0, sizeof(union parameter));
        if (type == PORT_TYPE_REMOTE_OUT)
                param.newref.direction = 1; /* new ref from lcr */
-       p_m_r_remote_id = remote_id;
-       if (admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_NEWREF, &param) < 0)
-               FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", mISDNport->ifport->remote_app);
+       p_r_remote_id = remote_id;
+       if (admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_NEWREF, &param) < 0)
+               FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", p_r_remote_app);
 
-       PDEBUG(DEBUG_GSM, "Created new RemotePort(%s).\n", portname);
+       PDEBUG(DEBUG_PORT, "Created new RemotePort(%s).\n", portname);
 
 }
 
@@ -42,17 +42,7 @@ Premote::Premote(int type, struct mISDNport *mISDNport, char *portname, struct p
  */
 Premote::~Premote()
 {
-       /* need to remote (import) external channel from remote application */
-       if (p_m_r_handle) {
-               message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_REMOVE, p_m_r_handle, 0, 0, 0, 0, 0, 0, 1);
-               chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-               add_trace("type", NULL, "remove");
-               add_trace("channel", NULL, "%d.%d", p_m_r_handle>>8, p_m_r_handle&0xff);
-               end_trace();
-       }
-
-       PDEBUG(DEBUG_GSM, "Destroyed Remote process(%s).\n", p_name);
-
+       PDEBUG(DEBUG_PORT, "Destroyed Remote process(%s).\n", p_name);
 }
 
 /*
@@ -60,32 +50,19 @@ Premote::~Premote()
  */
 int Premote::message_epoint(unsigned int epoint_id, int message_type, union parameter *param)
 {
-       struct lcr_msg *message;
-       int channel;
-       int ret;
        struct epoint_list *epointlist;
 
-       if (PmISDN::message_epoint(epoint_id, message_type, param))
+       if (Port::message_epoint(epoint_id, message_type, param))
                return 1;
 
-       if (message_type == MESSAGE_SETUP) {
-               ret = channel = hunt_bchannel();
-               if (ret < 0)
-                       goto no_channel;
-               /* open channel */
-               ret = seize_bchannel(channel, 1);
-               if (ret < 0) {
-                       no_channel:
-                       message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-                       message->param.disconnectinfo.cause = 34;
-                       message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-                       message_put(message);
-                       new_state(PORT_STATE_RELEASE);
-                       delete this;
+       switch (message_type) {
+       case MESSAGE_SETUP:
+               struct interface *interface;
+               interface = getinterfacebyname(p_interface_name);
+               if (!interface) {
+                       PERROR("Cannot find interface %s.\n", p_interface_name);
                        return 0;
                }
-               bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-
                /* attach only if not already */
                epointlist = p_epointlist;
                while(epointlist) {
@@ -97,24 +74,51 @@ int Premote::message_epoint(unsigned int epoint_id, int message_type, union para
                        epointlist_new(epoint_id);
 
                /* set context to pbx */
-               SCPY(param->setup.context, "pbx");
+               if (!param->setup.dialinginfo.context[0]) {
+                       if (interface->remote_context[0])
+                               SCPY(param->setup.dialinginfo.context, interface->remote_context);
+                       else
+                               SCPY(param->setup.dialinginfo.context, "lcr");
+               }
+               /* screen */
+               memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
+               memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
+               do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_interface_name);
+               do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_interface_name);
+               do_screen(1, p_redirinfo.id, sizeof(p_redirinfo.id), &p_redirinfo.ntype, &p_redirinfo.present, p_interface_name);
+               memcpy(&param->setup.callerinfo, &p_callerinfo, sizeof(p_callerinfo));
+               memcpy(&param->setup.redirinfo, &p_redirinfo, sizeof(p_redirinfo));
+
+               new_state(PORT_STATE_OUT_SETUP);
+               break;
+
+       case MESSAGE_PROCEEDING:
+               new_state(PORT_STATE_IN_PROCEEDING);
+               break;
+
+       case MESSAGE_ALERTING:
+               new_state(PORT_STATE_IN_ALERTING);
+               break;
+
+       case MESSAGE_CONNECT:
+               new_state(PORT_STATE_CONNECT);
+               break;
+
+       case MESSAGE_DISCONNECT:
+               new_state(PORT_STATE_OUT_DISCONNECT);
+               break;
+
+       case MESSAGE_RELEASE:
+               new_state(PORT_STATE_RELEASE);
+               break;
        }
 
        /* look for Remote's interface */
-       if (admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, message_type, param)<0) {
-               PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all remote ports.\n", p_m_mISDNport->ifport->remote_app);
+       if (admin_message_from_lcr(p_r_remote_id, p_r_ref, message_type, param)<0) {
+               PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all remote ports.\n", p_r_remote_app);
                return 0;               
        }
 
-       /* enable audio path */
-       if (message_type == MESSAGE_SETUP) {
-               union parameter newparam;
-               memset(&newparam, 0, sizeof(union parameter));
-               admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_PATTERN, &newparam);
-               newparam.audiopath = 1;
-               admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_AUDIOPATH, &newparam);
-       }
-
        if (message_type == MESSAGE_RELEASE) {
                new_state(PORT_STATE_RELEASE);
                delete this;
@@ -128,76 +132,70 @@ void Premote::message_remote(int message_type, union parameter *param)
 {
        class Endpoint *epoint;
        struct lcr_msg *message;
-       int channel;
-       int ret;
+       struct interface *interface;
+
+       switch (message_type) {
+       case MESSAGE_TRAFFIC:
+               bridge_tx(param->traffic.data, param->traffic.len);
+               if (p_tone_name[0]) {
+                       read_audio(param->traffic.data, param->traffic.len);
+                       admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param);
+               }
+               break;
+
+       case MESSAGE_SETUP:
+               interface = getinterfacebyname(p_interface_name);
+               if (!interface) {
+                       PERROR("Cannot find interface %s.\n", p_interface_name);
+                       return;
+               }
 
-       if (message_type == MESSAGE_SETUP) {
                /* enable audio path */
-               union parameter newparam;
-               memset(&newparam, 0, sizeof(union parameter));
-               admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_PATTERN, &newparam);
-               newparam.audiopath = 1;
-               admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_AUDIOPATH, &newparam);
+               if (interface->is_tones == IS_YES) {
+                       union parameter newparam;
+                       memset(&newparam, 0, sizeof(union parameter));
+                       admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_PATTERN, &newparam);
+                       newparam.audiopath = 1;
+                       admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_AUDIOPATH, &newparam);
+               }
 
                /* set source interface */
                param->setup.callerinfo.itype = p_callerinfo.itype;
-               param->setup.callerinfo.isdn_port = p_m_portnum;
-               SCPY(param->setup.callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+               SCPY(param->setup.callerinfo.interface, interface->name);
                
-               ret = channel = hunt_bchannel();
-               if (ret < 0)
-                       goto no_channel;
-
-               /* open channel */
-               ret = seize_bchannel(channel, 1);
-               if (ret < 0) {
-                       no_channel:
-                       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
-                       message->param.disconnectinfo.cause = 34;
-                       message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-                       message_put(message);
-                       new_state(PORT_STATE_RELEASE);
-                       delete this;
-                       return;
-               }
-               bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-
                /* create endpoint */
                if (p_epointlist)
                        FATAL("Incoming call but already got an endpoint.\n");
                if (!(epoint = new Endpoint(p_serial, 0)))
                        FATAL("No memory for Endpoint instance\n");
-               epoint->ep_app = new_endpointapp(epoint, 0, p_m_mISDNport->ifport->interface->app); //incoming
+               epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
 
                epointlist_new(epoint->ep_serial);
-       }
 
-       /* set serial on bchannel message
-        * also ref is given, so we send message with ref */
-       if (message_type == MESSAGE_BCHANNEL) {
-               int i = p_m_b_index;
-               unsigned int portid = (mISDNloop.port<<8) + i+1+(i>=15);
-               switch (param->bchannel.type) {
-               case BCHANNEL_REQUEST:
-                       p_m_r_handle = portid;
-                       message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_ASSIGN, portid, 0, 0, 0, 0, 0, 0, 1);
-                       chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                       add_trace("type", NULL, "assign");
-                       add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                       end_trace();
-                       break;
-               case BCHANNEL_RELEASE:
-                       p_m_r_handle = 0;
-                       message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_REMOVE, portid, 0, 0, 0, 0, 0, 0, 1);
-                       chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
-                       add_trace("type", NULL, "remove");
-                       add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
-                       end_trace();
-                       break;
-               }
-               return;
+               new_state(PORT_STATE_IN_SETUP);
+               break;
+
+       case MESSAGE_PROCEEDING:
+               new_state(PORT_STATE_OUT_PROCEEDING);
+               break;
+
+       case MESSAGE_ALERTING:
+               new_state(PORT_STATE_OUT_ALERTING);
+               break;
+
+       case MESSAGE_CONNECT:
+               new_state(PORT_STATE_CONNECT);
+               break;
+
+       case MESSAGE_DISCONNECT:
+               new_state(PORT_STATE_IN_DISCONNECT);
+               break;
+
+       case MESSAGE_RELEASE:
+               new_state(PORT_STATE_RELEASE);
+               break;
        }
-       
+
        /* cannot just forward, because param is not of container "struct lcr_msg" */
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, message_type);
        memcpy(&message->param, param, sizeof(message->param));
@@ -210,11 +208,32 @@ void Premote::message_remote(int message_type, union parameter *param)
        }
 }
 
-/* select free bchannel from loopback interface */
-int Premote::hunt_bchannel(void)
+/* receive from remote Port instance */
+int Premote::bridge_rx(unsigned char *data, int len)
 {
-       return loop_hunt_bchannel(this, p_m_mISDNport);
-}
+       union parameter newparam;
+       int l;
+
+       /* don't send tones, if not enabled or not connected */
+       if (!p_r_tones
+        && p_state != PORT_STATE_CONNECT)
+               return 0;
+
+       if (p_tone_name[0])
+               return 0;
 
+       memset(&newparam, 0, sizeof(union parameter));
+       /* split, if exeeds data size */
+       while(len) {
+               l = (len > (int)sizeof(newparam.traffic.data)) ? sizeof(newparam.traffic.data) : len;
+               newparam.traffic.len = l;
+               len -= l;
+               memcpy(newparam.traffic.data, data, l);
+               data += l;
+               admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, &newparam);
+       }
+
+       return 0;
+}