added echo cancelling
[spider.git] / src / client.c
index c330536bf3a15e6c52ed21987692a55a2258a95a..8df624494b3c7879cc60480458ff860369d4fe92 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "sel.h"
 #include "cmsg.h"
+#include "chain.h"
 #include "debug.h"
 
 #define TEXT 1
@@ -95,8 +96,9 @@ int tabsize = 8;                              /* default tabsize for text messages */
 char *connsort = "local";              /* the connection variety */
 int state = 0;                                 /* the current state of the connection */
 int laststate = 0;                             /* the last state we were in */
-
-
+reft echobase;                                 /* the anti echo queue */
+int maxecho = 5;                               /* the depth of the anti echo queue */
+int echon;                                             /* no of entries in the anti echo queue */
 
 #define CONNECTED 100
 #define WAITLOGIN 1
@@ -112,10 +114,10 @@ myregex_t iscallreg[] = {         /* regexes to determine whether this is a reasonable
                "^[0-9]+[A-Z]+[0-9]+[A-Z]+[1-9]?$", 0          /* 2E0AAA 2E0AAA1 */
        },
        {
-               "^[A-Z]+[0-9]+[A-Z]+-[1-9]$", 0                /* G1TLH-2 */
+               "^[A-Z]+[0-9]+[A-Z]+-[0-9]$", 0                /* G1TLH-2 */
        },
        {
-               "^[0-9]+[A-Z]+[0-9]+[A-Z]+-[1-9]$", 0          /* 2E0AAA-2 */
+               "^[0-9]+[A-Z]+[0-9]+[A-Z]+-[0-9]$", 0          /* 2E0AAA-2 */
        },
        {
                "^[A-Z]+[0-9]+[A-Z]+-1[0-5]$", 0               /* G1TLH-11 */
@@ -221,7 +223,22 @@ fcb_t *fcb_new(int cnum, int sort)
 void flush_text(fcb_t *f)
 {
        if (f->obuf) {
-               cmsg_send(f->outq, f->obuf, 0);
+               /* save this onto the front of the echo chain */
+               cmsg_t *imp = f->obuf;
+               int size = imp->inp - imp->data;
+               cmsg_t *emp = cmsg_new(size, imp->sort, imp->portp);
+
+               emp->size = size;
+               memcpy(emp->data, imp->data, size);
+               emp->inp = emp->data + size; /* just in case */
+               chain_add(&echobase, emp);
+               if (++echon > maxecho) {
+                       emp = cmsg_prev(&echobase);
+                       cmsg_free(emp);
+               }
+               
+               /* queue it for sending */
+               cmsg_send(f->outq, imp, 0);
                f->sp->flags |= SEL_OUTPUT;
                f->obuf = 0;
        }
@@ -300,6 +317,26 @@ void send_msg(fcb_t *f, char let, UC *s, int l)
        f->sp->flags |= SEL_OUTPUT;
 }
 
+/* 
+ * send a file out to the user
+ */
+void send_file(char *name)
+{
+       int i;
+       char buf[MAXPACLEN+1];
+       
+       FILE *f = xopen("data", name, "r");
+       if (f) {
+               while (fgets(buf, paclen, f)) {
+                       i = strlen(buf);
+                       if (i && buf[i-1] == '\n') 
+                               buf[--i] = 0;
+                       send_text(in, buf, i, 1);
+               }
+               fclose(f);
+       }
+}
+
 /*
  * the callback (called by sel_run) that handles all the inputs and outputs
  */
@@ -448,12 +485,12 @@ int fcb_handler(sel_t *sp, int in, int out, int err)
 
                                case 1:
                                        mp->state = 2;
-                                       if (ch >= '2' && ch <= '9') 
+                                       if (ch >= '0' && ch <= '9') 
                                                c = (ch - '0') << 4;
                                        else if (ch >= 'A' && ch <= 'F')
                                                c = (ch - 'A' + 10) << 4;
                                        else {
-                                               dbg(DMSG, "Illegal hex char (%c) received in state %d", ch, mp->state);
+                                               dbg(DMSG, "Illegal hex char (%c) received in state 1", ch);
                                                mp->inp = mp->data;
                                                mp->state = 0;
                                        }
@@ -465,7 +502,7 @@ int fcb_handler(sel_t *sp, int in, int out, int err)
                                        else if (ch >= 'A' && ch <= 'F')
                                                *mp->inp++ = c | (ch - 'A' + 10);
                                        else {
-                                               dbg(DMSG, "Illegal hex char (%c) received in state %d", ch, mp->state);
+                                               dbg(DMSG, "Illegal hex char (%c) received in state 2", ch);
                                                mp->inp = mp->data;
                                        }
                                        mp->state = 0;
@@ -552,12 +589,20 @@ void setmode(char *m)
 
 void process_stdin()
 {
-       cmsg_t *mp = cmsg_next(in->inq);
+       cmsg_t *wmp, *mp = cmsg_next(in->inq);
        char *p, hasa, hasn, i;
        char callsign[MAXCALLSIGN+1];
        
        if (mp) {
                dbg(DMSG, "MSG size: %d", mp->size);
+               
+               /* check for echos */
+               for (wmp = 0; wmp = chain_get_next(&echobase, wmp); ) {
+                       if (!memcmp(wmp->data, mp->data, wmp->size)) {
+                               cmsg_callback(mp, 0);
+                               return;
+                       }
+               }
 
                switch (state) {
                case CONNECTED:
@@ -593,6 +638,11 @@ void process_stdin()
                        if (!iscallsign(call)) {
                                die("Sorry, %s isn't a valid callsign", call);
                        }
+                       
+                       /* strip off a '-0' at the end */
+                       i = strlen(call);
+                       if (call[i-1] == '0' && call[i-2] == '-')
+                               call[i-2] = 0;
 
                        alarm(0);
                        signal(SIGALRM, SIG_IGN);
@@ -601,6 +651,7 @@ void process_stdin()
                        send_msg(node, 'A', connsort, strlen(connsort));
                        
                        chgstate(CONNECTED);
+                       send_file("connected");
                }
 
                cmsg_callback(mp, 0);
@@ -828,6 +879,8 @@ main(int argc, char *argv[])
 #ifdef SIGPWR
        signal(SIGPWR, terminate);
 #endif
+       /* init a few things */
+       chain_init(&echobase);
 
        /* connect up stdin */
        in = fcb_new(0, TEXT);
@@ -852,34 +905,29 @@ main(int argc, char *argv[])
 
        /* is this a login? */
        if (eq(call, "LOGIN") || eq(call, "login")) {
-       
-               char buf[MAXPACLEN+1];
-               int r, i;
-               FILE *f = xopen("data", "issue", "r");
-               if (f) {
-                       while (fgets(buf, paclen, f)) {
-                               i = strlen(buf);
-                               if (i && buf[i-1] == '\n') 
-                                       buf[--i] = 0;
-                               send_text(in, buf, i, 1);
-                       }
-                       fclose(f);
-               }
+               send_file("issue");
                signal(SIGALRM, login_timeout);
                alarm(timeout);
                send_text(in, "login: ", 7, 0);
                chgstate(WAITLOGIN);
        } else {
-
+               int i;
+               
                /* check the callsign against the regexes */
                if (!iscallsign(call)) {
                        die("Sorry, %s isn't a valid callsign", call);
                }
 
+               /* strip off a '-0' at the end */
+               i = strlen(call);
+               if (call[i-1] == '0' && call[i-2] == '-')
+                       call[i-2] = 0;
+               
                /* tell the cluster who I am */
                send_msg(node, 'A', connsort, strlen(connsort));
        
                chgstate(CONNECTED);
+               send_file("connected");
        }