* $Id$
*/
+#include <sys/types.h>
#include <stdio.h>
#include <sys/time.h>
-#include <sys/types.h>
+#include <sys/wait.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include "sel.h"
#include "cmsg.h"
+#include "chain.h"
#include "debug.h"
#define TEXT 1
#define MAXPATHLEN 256
#endif
-#define DEFPACLEN 128
+#define DEFPACLEN 236
#define MAXPACLEN 236
#define MAXCALLSIGN 9
char *connsort = "local"; /* the connection variety */
int state = 0; /* the current state of the connection */
int laststate = 0; /* the last state we were in */
-
-
+char echocancel = 1; /* echo cancelling */
+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
#define WAITPASSWD 2
#define WAITINPUT 10
-
+#define DOCHAT 20
myregex_t iscallreg[] = { /* regexes to determine whether this is a reasonable callsign */
{
"^[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 */
return 0;
}
+void reaper(int i)
+{
+ pid_t mypid;
+ while ((mypid = waitpid(-1, 0, WNOHANG)) > 0) {
+ ;
+ }
+}
+
/*
* higher level send and receive routines
*/
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 */
+ if (echocancel) {
+ 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;
}
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
*/
default:
if (nl == '\n' && *p == '\r') { /* ignore \r in telnet mode (ugh) */
p++;
+ } else if (nl == '\r' && *p == '\n') { /* and ignore \n in ax25 mode (double ugh) */
+ p++;
} else if (*p == nl) {
if (mp->inp == mp->data)
*mp->inp++ = ' ';
c = (ch - '0') << 4;
else if (ch >= 'A' && ch <= 'F')
c = (ch - 'A' + 10) << 4;
- else if (ch >= 'a' && ch <= 'a')
- 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;
}
*mp->inp++ = c | (ch - '0');
else if (ch >= 'A' && ch <= 'F')
*mp->inp++ = c | (ch - 'A' + 10);
- else if (ch >= 'a' && ch <= 'a')
- *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;
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 */
+ if (echocancel) {
+ 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:
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);
send_msg(node, 'A', connsort, strlen(connsort));
chgstate(CONNECTED);
+ send_file("connected");
+ break;
+
+ case DOCHAT:
+
+ break;
}
cmsg_callback(mp, 0);
{
int i, c, err = 0;
- while ((c = getopt(argc, argv, "h:p:x:")) > 0) {
+ while ((c = getopt(argc, argv, "eh:l:p:x:")) > 0) {
switch (c) {
+ case 'e':
+ echocancel ^= 1;
+ break;
case 'h':
node_addr = optarg;
break;
lerr:
if (err) {
- die("usage: client [-x n|-h<host>|-p<port>|-l<paclen>] <call>|login [local|telnet|ax25]");
+ die("usage: client [-e|-x n|-h<host>|-p<port>|-l<paclen>] <call>|login [local|telnet|ax25]");
}
if (optind < argc) {
#ifdef SIGPWR
signal(SIGPWR, terminate);
#endif
+ signal(SIGCLD, reaper);
+
+ /* init a few things */
+ chain_init(&echobase);
/* connect up stdin */
in = fcb_new(0, TEXT);
/* 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");
}