Data-Over-Voice
[lcr.git] / port.cpp
index 98a644f..32184a8 100644 (file)
--- a/port.cpp
+++ b/port.cpp
@@ -148,7 +148,7 @@ struct epoint_list *Port::epointlist_new(unsigned int epoint_id)
 /*
  * port constructor
  */
-Port::Port(int type, const char *portname, struct port_settings *settings)
+Port::Port(int type, const char *portname, struct port_settings *settings, struct interface *interface)
 {
        class Port *temp, **tempp;
 
@@ -159,6 +159,8 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
                memset(&p_settings, 0, sizeof(p_settings));
        }
        SCPY(p_name, portname);
+       if (interface)
+               SCPY(p_interface_name, interface->name);
        p_tone_dir[0] = '\0';
        p_type = type;
        p_serial = port_serial++;
@@ -177,6 +179,7 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
 
        /* call recording */
        p_record = NULL;
+       p_tap = 0;
        p_record_type = 0;
        p_record_length = 0;
        p_record_skip = 0;
@@ -185,6 +188,13 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
        p_record_buffer_writep = 0;
        p_record_buffer_dir = 0;
 
+       /* VoOTP */
+#ifdef WITH_VOOTP
+       p_vootp = NULL;
+#endif
+       /* D-O-V */
+       dov_init();
+
        /* append port to chain */
        next = NULL;
        temp = port_first;
@@ -197,7 +207,7 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
 
        classuse++;
 
-       PDEBUG(DEBUG_PORT, "new port (%d) of type 0x%x, name '%s'\n", p_serial, type, portname);
+       PDEBUG(DEBUG_PORT, "new port (%d) of type 0x%x, name '%s' interface '%s'\n", p_serial, type, portname, p_interface_name);
 }
 
 
@@ -209,7 +219,14 @@ Port::~Port(void)
        class Port *temp, **tempp;
        struct lcr_msg *message;
 
-       PDEBUG(DEBUG_PORT, "removing port (%d) of type 0x%x, name '%s'\n", p_serial, p_type, p_name);
+       PDEBUG(DEBUG_PORT, "removing port (%d) of type 0x%x, name '%s' interface '%s'\n", p_serial, p_type, p_name, p_interface_name);
+
+#ifdef WITH_VOOTP
+       if (p_vootp) {
+               vootp_destroy(p_vootp);
+               p_vootp = NULL;
+       }
+#endif
 
        if (p_bridge) {
                PDEBUG(DEBUG_PORT, "Removing us from bridge %u\n", p_bridge->bridge_id);
@@ -219,6 +236,8 @@ Port::~Port(void)
        if (p_record)
                close_record(0, 0);
 
+       dov_exit();
+
        classuse--;
 
        /* disconnect port from endpoint */
@@ -374,6 +393,10 @@ void Port::set_tone(const char *dir, const char *name)
 }
 
 
+void Port::set_display(const char *text)
+{
+}
+
 /*
  * set the file in the tone directory for vbox playback
  * also set the play_eof-flag
@@ -634,6 +657,23 @@ int Port::message_epoint(unsigned int epoint_id, int message_id, union parameter
                PDEBUG(DEBUG_PORT, "PORT(%s) bridging to id %d\n", p_name, param->bridge_id);
                bridge(param->bridge_id);
                return 1;
+
+#ifdef WITH_VOOTP
+       case MESSAGE_VOOTP: /* enable / disable VoOTP */
+               PDEBUG(DEBUG_PORT, "PORT(%s) VoOTP enabled: %d\n", p_name, param->vootp.enable);
+               set_vootp(&param->vootp);
+               return 1;
+#endif
+
+       case MESSAGE_DOV_REQUEST: /* Data-Over-Voice message */
+               PDEBUG(DEBUG_PORT, "PORT(%s) sending data over voice message (len=%d)\n", p_name, param->dov.length);
+               dov_sendmsg(param->dov.data, param->dov.length, (enum dov_type)param->dov.type, param->dov.level);
+               return 1;
+
+       case MESSAGE_DOV_LISTEN: /* Data-Over-Voice listen order */
+               PDEBUG(DEBUG_PORT, "PORT(%s) sending data over voice listen order\n", p_name);
+               dov_listen((enum dov_type)param->dov.type);
+               return 1;
        }
 
        return 0;
@@ -663,7 +703,7 @@ int Port::open_record(int type, int vbox, int skip, char *extension, int anon_ig
        char filename[256];
        time_t now;
        struct tm *now_tm;
-       int ret;
+       int __attribute__((__unused__)) ret;
 
        if (!extension) {
                PERROR("Port(%d) not an extension\n", p_serial);
@@ -756,7 +796,7 @@ void Port::close_record(int beep, int mute)
        char *p;
        struct caller_info callerinfo;
        const char *valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-!$%&/()=+*;~";
-       int ret;
+       int __attribute__((__unused__)) ret;
 
        if (!p_record)
                return;
@@ -957,7 +997,7 @@ void Port::record(unsigned char *data, int length, int dir_fromup)
        signed short *s;
        int free, i, ii;
        signed int sample;
-       int ret;
+       int __attribute__((__unused__)) ret;
 
        /* no recording */
        if (!p_record || !length)
@@ -1162,6 +1202,10 @@ different_again:
 
 }
 
+void Port::tap(unsigned char *data, int length, int dir_fromup)
+{
+}
+
 void Port::update_rxoff(void)
 {
 }
@@ -1305,6 +1349,11 @@ int Port::bridge_tx(unsigned char *data, int len)
        signed long *sum;
        unsigned char *buf;
 
+#ifdef WITH_VOOTP
+       if (p_vootp)
+               vootp_encrypt_stream(p_vootp, data, len);
+#endif
+
        /* less than two ports, so drop */
        if (!p_bridge || !p_bridge->first || !p_bridge->first->next)
                return -EIO;
@@ -1420,9 +1469,47 @@ int bridge_timeout(struct lcr_timer *timer, void *instance, int index)
 }
 
 
-/* receive data from remote Port (dummy, needs to be inherited) */
+/* receive data from remote Port */
 int Port::bridge_rx(unsigned char *data, int len)
 {
-       return 0; /* datenklo */
+
+#ifdef WITH_VOOTP
+       if (p_vootp)
+               vootp_decrypt_stream(p_vootp, data, len);
+#endif
+
+       return 0;
+}
+
+#ifdef WITH_VOOTP
+static void vootp_info(void *priv, const char *text)
+{
+       class Port *port = (class Port *)priv;
+       char display[strlen(text) + 1];
+
+       SCPY(display, text);
+       if (display[0])
+               display[strlen(display) - 1] = '\0';
+
+       port->set_display(display);
 }
 
+void Port::set_vootp(struct param_vootp *vootp)
+{
+       if (p_vootp) {
+               vootp_destroy(p_vootp);
+               p_vootp = NULL;
+       }
+       if (vootp->enable) {
+               p_vootp = vootp_create(this, (options.law=='a'), options.otp_dir, NULL, NULL, vootp->id, vootp_info);
+//             vootp_loglevel(VOOTP_LOGL_DEBUG);
+               if (!p_vootp) {
+                       struct lcr_msg *message;
+
+                       message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_VOOTP);
+                       message->param.vootp.failed = 1;
+                       message_put(message);
+               }
+       }
+}
+#endif