aboutsummaryrefslogtreecommitdiffstats
path: root/ncpd
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>1999-06-29 02:23:31 +0000
committerFritz Elfert <felfert@to.com>1999-06-29 02:23:31 +0000
commit6ab1aa5f2156ef781da6e1b57a183825b88bef9a (patch)
tree76d2b37e54731e68c9855e5658ac18558a369313 /ncpd
parentf3e248b6e75c7ce5beda577f5712915417313b0a (diff)
downloadplptools-6ab1aa5f2156ef781da6e1b57a183825b88bef9a.tar.gz
plptools-6ab1aa5f2156ef781da6e1b57a183825b88bef9a.tar.bz2
plptools-6ab1aa5f2156ef781da6e1b57a183825b88bef9a.zip
Initial import
Diffstat (limited to 'ncpd')
-rw-r--r--ncpd/Makefile.am8
-rw-r--r--ncpd/channel.cc60
-rw-r--r--ncpd/channel.h34
-rw-r--r--ncpd/link.cc166
-rw-r--r--ncpd/link.h34
-rw-r--r--ncpd/linkchan.cc54
-rw-r--r--ncpd/linkchan.h16
-rw-r--r--ncpd/main.cc157
-rw-r--r--ncpd/mp_serial.c191
-rw-r--r--ncpd/mp_serial.h7
-rw-r--r--ncpd/ncp.cc292
-rw-r--r--ncpd/ncp.h49
-rw-r--r--ncpd/packet.cc226
-rw-r--r--ncpd/packet.h43
-rw-r--r--ncpd/socketchan.cc105
-rw-r--r--ncpd/socketchan.h28
16 files changed, 1470 insertions, 0 deletions
diff --git a/ncpd/Makefile.am b/ncpd/Makefile.am
new file mode 100644
index 0000000..6ee7caf
--- /dev/null
+++ b/ncpd/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES=-I../lib
+
+LIBS = -L../lib -lutils
+
+sbin_PROGRAMS = ncpd
+
+ncpd_SOURCES = channel.cc link.cc linkchan.cc main.cc \
+ ncp.cc packet.cc socketchan.cc mp_serial.c
diff --git a/ncpd/channel.cc b/ncpd/channel.cc
new file mode 100644
index 0000000..6cc3ff3
--- /dev/null
+++ b/ncpd/channel.cc
@@ -0,0 +1,60 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+
+#include <stream.h>
+
+#include "bool.h"
+#include "channel.h"
+#include "ncp.h"
+
+channel::channel(ncp *_ncpController) {
+ ncpController = _ncpController;
+ _terminate = false;
+}
+
+void channel::ncpSend(bufferStore &a) {
+ ncpController->send(ncpChannel, a);
+}
+
+bool channel::terminate() {
+ return _terminate;
+}
+
+void channel::terminateWhenAsked() {
+ _terminate = true;
+}
+
+void channel::ncpConnect() {
+ ncpController->connect(this);
+}
+
+void channel::ncpDisconnect() {
+ ncpController->disconnect(ncpChannel);
+}
+
+void channel::setNcpChannel(int chan) {
+ ncpChannel = chan;
+}
+
+void channel::newNcpController(ncp *_ncpController) {
+ ncpController = _ncpController;
+}
diff --git a/ncpd/channel.h b/ncpd/channel.h
new file mode 100644
index 0000000..b71e248
--- /dev/null
+++ b/ncpd/channel.h
@@ -0,0 +1,34 @@
+#ifndef _channel_h_
+#define _channel_h_
+
+#include <stdio.h>
+
+#include "bool.h"
+
+class ncp;
+class bufferStore;
+
+class channel {
+public:
+ channel(ncp *ncpController);
+ void newNcpController(ncp *ncpController);
+
+ void setNcpChannel(int chan);
+ void ncpSend(bufferStore &a);
+ virtual void ncpDataCallback(bufferStore &a) = NULL;
+ virtual const char *getNcpConnectName() = NULL;
+ void ncpConnect();
+ virtual void ncpConnectAck() = NULL;
+ virtual void ncpConnectTerminate() = NULL;
+ void ncpDisconnect();
+
+ // The following two calls are used for destructing an instance
+ virtual bool terminate(); // Mainloop will terminate this class if true
+ void terminateWhenAsked();
+private:
+ ncp *ncpController;
+ bool _terminate;
+ int ncpChannel;
+};
+
+#endif
diff --git a/ncpd/link.cc b/ncpd/link.cc
new file mode 100644
index 0000000..f3a13df
--- /dev/null
+++ b/ncpd/link.cc
@@ -0,0 +1,166 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stream.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "link.h"
+#include "packet.h"
+#include "bufferstore.h"
+#include "bufferarray.h"
+
+link::link(const char *fname, int baud, IOWatch & iow, bool _s5, bool _verbose):
+s5(_s5)
+{
+ p = new packet(fname, baud, iow, PACKET_LAYER_DIAGNOSTICS);
+ verbose = _verbose;
+ idSent = 0;
+ idLastGot = -1;
+ newLink = true;
+ somethingToSend = false;
+ timesSent = 0;
+ failed = false;
+}
+
+link::~link()
+{
+ delete p;
+}
+
+void link::
+send(const bufferStore & buff)
+{
+ if (buff.getLen() > 300)
+ failed = true;
+ else
+ sendQueue.pushBuffer(buff);
+}
+
+bufferArray link::
+poll()
+{
+ bufferArray ret;
+ bufferStore buff;
+ unsigned char type;
+
+ while (p->get(type, buff)) {
+ if ((type & 0xf0) == 0x30) {
+ // Data
+ int ser = type & 0x0f;
+ if (verbose)
+ cout << "link: Got data ser " << ser << " : " << buff << endl;
+ // Send ack
+ if (idLastGot != ser) {
+ idLastGot = ser;
+ ret.pushBuffer(buff);
+ } else {
+ if (verbose)
+ cout << "link: Duplicated data - not passing back, repeating ack\n";
+ }
+ if (verbose)
+ cout << "link: Send ack ser " << ser << endl;
+ bufferStore blank;
+ p->send(ser, blank);
+ break;
+ } else if ((type & 0xf0) == 0x00) {
+ // Ack
+ int ser = type & 0x0f;
+ if (ser == idSent) {
+ if (verbose)
+ cout << "link: Got ack " << ser << " : " << buff << endl;
+ somethingToSend = false;
+ timesSent = 0;
+ }
+ } else if ((type & 0xf0) == 0x20) {
+ // New link
+ int ser = type & 0x0f;
+ if (verbose)
+ cout << "link: got New link request " << ser << " : " << buff << endl;
+ idLastGot = 0;
+ bufferStore blank;
+ if (verbose)
+ cout << "link: Sending ack of new link\n";
+ somethingToSend = false;
+ p->send(idLastGot, blank);
+ } else if ((type & 0xf0) == 0x10) {
+ // Disconnect
+ cerr << "Disconnect?\n";
+ failed = true;
+ return ret;
+ }
+ }
+
+ if (!somethingToSend) {
+ countToResend = 0;
+ if (newLink) {
+ somethingToSend = true;
+ toSend.init();
+ newLink = false;
+ idSent = 0;
+ } else {
+ if (!sendQueue.empty()) {
+ somethingToSend = true;
+ toSend = sendQueue.popBuffer();
+ idSent++;
+ if (idSent > 7)
+ idSent = 0;
+ }
+ }
+ }
+ if (somethingToSend) {
+ if (countToResend == 0) {
+ timesSent++;
+ if (timesSent == 5) {
+ failed = true;
+ } else {
+ if (toSend.empty()) {
+ // Request for new link
+ if (verbose)
+ cout << "link: Send req new session ser " << idSent << endl;
+ p->send(0x20 + idSent, toSend);
+ } else {
+ if (verbose)
+ cout << "link: Send data packet ser " << idSent << " : " << toSend << endl;
+ p->send(0x30 + idSent, toSend);
+ }
+ countToResend = 5;
+ }
+ } else {
+ countToResend--;
+ }
+ }
+ return ret;
+}
+
+bool link::
+stuffToSend()
+{
+ return (somethingToSend || !sendQueue.empty());
+}
+
+bool link::
+hasFailed()
+{
+ return failed;
+}
diff --git a/ncpd/link.h b/ncpd/link.h
new file mode 100644
index 0000000..f166513
--- /dev/null
+++ b/ncpd/link.h
@@ -0,0 +1,34 @@
+#ifndef _link_h_
+#define _link_h_
+
+#include "bool.h"
+#include "bufferstore.h"
+#include "bufferarray.h"
+class packet;
+class IOWatch;
+
+class link {
+public:
+ link(const char *fname, int baud, IOWatch &iow, bool s5, bool _verbose = false);
+ ~link();
+ void send(const bufferStore &buff);
+ bufferArray poll();
+ bool stuffToSend();
+ bool hasFailed();
+
+private:
+ packet *p;
+ int idSent;
+ int countToResend;
+ int timesSent;
+ bufferArray sendQueue;
+ bufferStore toSend;
+ int idLastGot;
+ bool newLink;
+ bool verbose;
+ bool somethingToSend;
+ bool failed;
+ bool s5;
+};
+
+#endif
diff --git a/ncpd/linkchan.cc b/ncpd/linkchan.cc
new file mode 100644
index 0000000..e5d7c13
--- /dev/null
+++ b/ncpd/linkchan.cc
@@ -0,0 +1,54 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stream.h>
+
+#include "linkchan.h"
+#include "bufferstore.h"
+
+linkChan::linkChan(ncp * _ncpController):channel(_ncpController)
+{
+}
+
+void linkChan::
+ncpDataCallback(bufferStore & a)
+{
+ cout << "linkchan: got message " << a << endl;
+}
+
+const char *linkChan::
+getNcpConnectName()
+{
+ return "LINK.*";
+}
+
+void linkChan::
+ncpConnectAck()
+{
+ cout << "linkchan: got connect ack\n";
+}
+
+void linkChan::
+ncpConnectTerminate()
+{
+ cout << "linkchan: got connect terminate\n";
+ terminateWhenAsked();
+}
diff --git a/ncpd/linkchan.h b/ncpd/linkchan.h
new file mode 100644
index 0000000..e90dee2
--- /dev/null
+++ b/ncpd/linkchan.h
@@ -0,0 +1,16 @@
+#ifndef _linkchan_h_
+#define _linkchan_h_
+
+#include "channel.h"
+
+class linkChan : public channel {
+public:
+ linkChan(ncp *ncpController);
+
+ void ncpDataCallback(bufferStore &a);
+ const char *getNcpConnectName();
+ void ncpConnectAck();
+ void ncpConnectTerminate();
+};
+
+#endif
diff --git a/ncpd/main.cc b/ncpd/main.cc
new file mode 100644
index 0000000..dd32729
--- /dev/null
+++ b/ncpd/main.cc
@@ -0,0 +1,157 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stdio.h>
+#include <string.h>
+#include <stream.h>
+#include <stdlib.h>
+
+#include "defs.h"
+#include "ncp.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "socketchan.h"
+#include "iowatch.h"
+#include "linkchan.h"
+
+void
+checkForNewSocketConnection(ppsocket & skt, int &numScp, socketChan ** scp, ncp * a, IOWatch & iow)
+{
+ char peer[201];
+ ppsocket *next = skt.accept(peer, 200);
+ if (next != NULL) {
+ // New connect
+ cout << "New socket connection from " << peer << endl;
+ if ((numScp == 7) || (!a->gotLinkChannel())) {
+ bufferStore a;
+ a.addStringT("No psion ncp channel free");
+ next->sendBufferStore(a);
+ } else
+ scp[numScp++] = new socketChan(next, a, iow);
+ }
+}
+
+void
+pollSocketConnections(int &numScp, socketChan ** scp)
+{
+ for (int i = 0; i < numScp; i++) {
+ scp[i]->socketPoll();
+ if (scp[i]->terminate()) {
+ // Requested channel termination
+ delete scp[i];
+ numScp--;
+ for (int j = i; j < numScp; j++)
+ scp[j] = scp[j + 1];
+ i--;
+ }
+ }
+}
+
+void
+resetSocketConnections(int &numScp, socketChan ** scp, ncp * a)
+{
+ for (int i = 0; i < numScp; i++) {
+ if (scp[i]->isConnected()) {
+ cout << "Killing\n";
+ delete scp[i];
+ numScp--;
+ for (int j = i; j < numScp; j++)
+ scp[j] = scp[j + 1];
+ i--;
+ } else {
+ scp[i]->newNcpController(a);
+ if (scp[i]->getNcpConnectName() != NULL) {
+ cout << "Connecting\n";
+ scp[i]->ncpConnect();
+ } else
+ cout << "Ignoring\n";
+ }
+ }
+}
+
+void
+usage()
+{
+ cout << "Version : " << VERSION << endl;
+ cout << "Usage : ncp [-s <socket number>] [-d <device>] [-b <baud rate>]\n";
+}
+
+int
+main(int argc, char **argv)
+{
+ ppsocket skt;
+ IOWatch iow;
+ skt.startup();
+
+ // Command line parameter processing
+ int sockNum = DPORT;
+ int baudRate = DSPEED;
+ const char *serialDevice = DDEV;
+
+ for (int i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-s") && i + 1 < argc) {
+ sockNum = atoi(argv[++i]);
+ } else if (!strcmp(argv[i], "-d") && i + 1 < argc) {
+ serialDevice = argv[++i];
+ } else if (!strcmp(argv[i], "-b") && i + 1 < argc) {
+ baudRate = atoi(argv[++i]);
+ } else {
+ usage();
+ exit(1);
+ }
+ }
+
+ if (!skt.listen("127.0.0.1", sockNum)) {
+ cerr << "Could not initiate listen on socket " << sockNum << endl;
+ cerr << "NCP is now started by rfsv - you don't have to do it explicitly yourself" << endl;
+ } else {
+ ncp *a = NULL;
+ int numScp;
+ socketChan *scp[8];
+
+ while (true) {
+ if (a == NULL) {
+ a = new ncp(serialDevice, baudRate, iow);
+ numScp = 0;
+ iow.addIO(skt.socket());
+ }
+ // sockets
+ checkForNewSocketConnection(skt, numScp, scp, a, iow);
+ pollSocketConnections(numScp, scp);
+
+ // psion
+ a->poll();
+
+ if (a->stuffToSend())
+ iow.watch(0, 100000);
+ else
+ iow.watch(100000, 0);
+ if (a->hasFailed()) {
+ cout << "ncp: restarting\n";
+ resetSocketConnections(numScp, scp, a);
+ delete a;
+ a = NULL;
+ }
+ }
+ delete a;
+ }
+ skt.closeSocket();
+}
diff --git a/ncpd/mp_serial.c b/ncpd/mp_serial.c
new file mode 100644
index 0000000..0b452f6
--- /dev/null
+++ b/ncpd/mp_serial.c
@@ -0,0 +1,191 @@
+/*
+ // PLP - An implementation of the PSION link protocol
+ //
+ //
+ // The code in this file was written by Rudolf Koenig
+ // (rfkoenig@immd4.informatik.uni-erlangen.de). (from his p3nfs code)
+ // The Copyright remains his
+ //
+ //
+ // This program is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2 of the License, or
+ // (at your option) any later version.
+ //
+ // This program is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with this program; if not, write to the Free Software
+ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ //
+ // e-mail philip.proudman@btinternet.com
+ */
+
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h> /* for usleep() */
+#include <string.h> /* for bzero() */
+#include <termios.h>
+#if defined(linux) || defined(_IBMR2) || defined(__NetBSD__)
+#include <sys/ioctl.h> /* for ioctl() */
+#endif
+#include <sys/errno.h>
+#ifdef sun
+#include <sys/ttold.h> /* sun has TIOCEXCL there */
+#endif
+#if defined (__SVR4)
+#include <stdlib.h>
+#endif
+
+#ifndef hpux
+#define mflag int
+#else /* hpux */
+#include <sys/termiox.h>
+#include <sys/modem.h>
+#endif
+
+
+/*
+ #if !defined(CRTSCTS) && defined(_IBMR2)
+ #define CRTSCTS 0x80000000
+ #endif
+ */
+
+#ifdef __sgi
+#define CRTSCTS CNEW_RTSCTS
+#endif
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
+int
+init_serial(const char *dev, int speed, int debug)
+{
+ int fd, baud, clocal;
+ int uid, euid;
+ struct termios ti;
+#ifdef hpux
+ struct termiox tx;
+#endif
+ static struct baud {
+ int speed, baud;
+ } btable[] = {
+ { 9600, B9600 },
+#ifdef B19200
+ { 19200, B19200 },
+#else
+#ifdef EXTA
+ { 19200, EXTA },
+#endif
+#endif
+#ifdef B38400
+ { 38400, B38400 },
+#else
+#ifdef EXTB
+ { 38400, EXTB },
+#endif
+#endif
+#ifdef B57600
+ { 57600, B57600 },
+#endif
+#ifdef B115200
+ { 115200, B115200 },
+#endif
+ { 4800, B4800 },
+ { 2400, B2400 },
+ { 1200, B1200 },
+ { 300, B300 },
+ { 75, B75 },
+ { 50, B50 },
+ { 0, 0 }
+ }, *bptr;
+
+ if (speed) {
+ for (bptr = btable; bptr->speed; bptr++)
+ if (bptr->speed == speed)
+ break;
+ if (!bptr->baud) {
+ fprintf(stderr, "Cannot match selected speed %d\n", speed);
+ exit(1);
+ }
+ baud = bptr->baud;
+ } else
+ baud = 0;
+
+ if (debug)
+ printf("using %s...\n", dev);
+ euid = geteuid();
+ uid = getuid();
+
+#ifdef hpux
+#define seteuid(a) setresuid(-1, a, -1)
+#endif
+
+ clocal = CLOCAL;
+ if (seteuid(uid)) {
+ perror("seteuid");
+ exit(1);
+ }
+ if ((fd = open(dev, O_RDWR | O_NDELAY | O_NOCTTY, 0)) < 0) {
+ perror(dev);
+ exit(1);
+ }
+ if (seteuid(euid)) {
+ perror("seteuid back");
+ exit(1);
+ }
+ if (debug)
+ printf("open done\n");
+#ifdef TIOCEXCL
+ ioctl(fd, TIOCEXCL, (char *) 0); /* additional open() calls shall fail */
+#else
+ fprintf(stderr, "WARNING: opened %s non-exclusive!\n", dev);
+#endif
+
+ memset(&ti, 0, sizeof(struct termios));
+#if defined(hpux) || defined(_IBMR2)
+ ti.c_cflag = CS8 | HUPCL | clocal | CREAD;
+#endif
+#if defined(sun) || defined(linux) || defined(__sgi) || defined(__NetBSD__)
+ ti.c_cflag = CS8 | HUPCL | clocal | CRTSCTS | CREAD;
+ ti.c_iflag = IGNBRK | IGNPAR;
+ ti.c_cc[VMIN] = 1;
+ ti.c_cc[VTIME] = 0;
+#endif
+ cfsetispeed(&ti, baud);
+ cfsetospeed(&ti, baud);
+
+ if (tcsetattr(fd, TCSADRAIN, &ti) < 0)
+ perror("tcsetattr TCSADRAIN");
+
+#ifdef hpux
+ bzero(&tx, sizeof(struct termiox));
+ tx.x_hflag = RTSXOFF | CTSXON;
+ if (ioctl(fd, TCSETXW, &tx) < 0)
+ perror("TCSETXW");
+#endif
+
+#if defined(_IBMR2)
+ ioctl(fd, TXDELCD, "dtr");
+ ioctl(fd, TXDELCD, "xon");
+ ioctl(fd, TXADDCD, "rts"); /* That's how AIX does CRTSCTS */
+#endif
+ return fd;
+}
+
+void
+ser_exit(int fd)
+{
+ struct termios ti;
+ if (ioctl(fd, TCGETS, (caddr_t) & ti) < 0)
+ perror("TCGETSW");
+ ti.c_cflag &= ~CRTSCTS;
+ if (tcsetattr(fd, TCSANOW, &ti) < 0)
+ perror("TCSETSW");
+ (void) close(fd);
+}
diff --git a/ncpd/mp_serial.h b/ncpd/mp_serial.h
new file mode 100644
index 0000000..4f7835a
--- /dev/null
+++ b/ncpd/mp_serial.h
@@ -0,0 +1,7 @@
+#ifndef _mp_serial_h
+#define _mp_serial_h
+
+int init_serial(const char *dev, int speed, int debug);
+void ser_exit(int fd);
+
+#endif
diff --git a/ncpd/ncp.cc b/ncpd/ncp.cc
new file mode 100644
index 0000000..d859ea9
--- /dev/null
+++ b/ncpd/ncp.cc
@@ -0,0 +1,292 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stream.h>
+#include <string.h>
+#include <time.h>
+
+#include "bool.h"
+#include "defs.h"
+#include "ncp.h"
+#include "linkchan.h"
+#include "bufferstore.h"
+#include "link.h"
+#include "bufferarray.h"
+
+#define NCP_SENDLEN 250
+
+ncp::ncp(const char *fname, int baud, IOWatch & iow)
+{
+ l = new link(fname, baud, iow, LINK_LAYER_DIAGNOSTICS);
+ gotLinkChan = false;
+ failed = false;
+
+ // init channels
+ for (int i = 0; i < 8; i++)
+ channelPtr[i] = NULL;
+}
+
+ncp::~ncp()
+{
+ delete l;
+}
+
+void ncp::
+poll()
+{
+ bufferArray res(l->poll());
+ if (!res.empty()) {
+ do {
+ bufferStore s = res.popBuffer();
+ if (s.getLen() > 1) {
+ int channel = s.getByte(0);
+ s.discardFirstBytes(1);
+ if (channel == 0) {
+ decodeControlMessage(s);
+ } else {
+ /* int remChan = */ s.getByte(0);
+ int allData = s.getByte(1);
+ s.discardFirstBytes(2);
+ if (channelPtr[channel] == NULL) {
+ cerr << "Got message for unknown channel\n";
+ } else {
+ messageList[channel].addBuff(s);
+ if (allData == LAST_MESS) {
+ channelPtr[channel]->ncpDataCallback(messageList[channel]);
+ messageList[channel].init();
+ } else if (allData != NOT_LAST_MESS) {
+ cerr << "ncp: bizarre third byte!\n";
+ }
+ }
+ }
+ } else {
+ cerr << "Got null message\n";
+ }
+ } while (!res.empty());
+ }
+}
+
+void ncp::
+controlChannel(int chan, enum interControllerMessageType t, bufferStore & command)
+{
+ bufferStore open;
+ open.addByte(0); // control
+
+ open.addByte(chan);
+ open.addByte(t);
+ open.addBuff(command);
+ cout << "put " << ctrlMsgName(t) << endl;
+ l->send(open);
+}
+
+void ncp::
+decodeControlMessage(bufferStore & buff)
+{
+ int remoteChan = buff.getByte(0);
+ interControllerMessageType imt = (interControllerMessageType) buff.getByte(1);
+ buff.discardFirstBytes(2);
+ cout << "got " << ctrlMsgName(imt) << " " << remoteChan << " ";
+ switch (imt) {
+ case NCON_MSG_DATA_XOFF:
+ cout << remoteChan << " " << buff << endl;
+ break;
+ case NCON_MSG_DATA_XON:
+ cout << buff << endl;
+ break;
+ case NCON_MSG_CONNECT_TO_SERVER:{
+ cout << buff << endl;
+ int localChan;
+ bufferStore b;
+
+ // Ack with connect response
+ localChan = getFirstUnusedChan();
+ b.addByte(remoteChan);
+ b.addByte(0x0);
+ controlChannel(localChan, NCON_MSG_CONNECT_RESPONSE, b);
+
+ if (!strcmp(buff.getString(0), "LINK.*")) {
+ if (gotLinkChan)
+ failed = true;
+ cout << "Accepted link channel" << endl;
+ channelPtr[localChan] = new linkChan(this);
+ channelPtr[localChan]->setNcpChannel(localChan);
+ channelPtr[localChan]->ncpConnectAck();
+ gotLinkChan = true;
+ } else {
+ cout << "Disconnecting channel" << endl;
+ bufferStore b;
+ b.addByte(remoteChan);
+ controlChannel(localChan, NCON_MSG_CHANNEL_DISCONNECT, b);
+ }
+ }
+ break;
+ case NCON_MSG_CONNECT_RESPONSE:{
+ int forChan = buff.getByte(0);
+ cout << "for channel " << forChan << " status ";
+ if (buff.getByte(1) == 0) {
+ cout << "OK" << endl;
+ if (channelPtr[forChan]) {
+ remoteChanList[forChan] = remoteChan;
+ channelPtr[forChan]->ncpConnectAck();
+ } else {
+ cerr << "Got message for unknown channel\n";
+ }
+ } else {
+ cout << "Unknown status " << (int) buff.getByte(1) << endl;
+ channelPtr[forChan]->ncpConnectTerminate();
+ }
+ }
+ break;
+ case NCON_MSG_CHANNEL_CLOSED:
+ cout << buff << endl;
+ break;
+ case NCON_MSG_NCP_INFO:
+ if (buff.getByte(0) == 6) {
+ cout << buff << endl;
+ {
+ // Send time info
+ bufferStore b;
+ b.addByte(6);
+ b.addDWord(0);
+ controlChannel(0, NCON_MSG_NCP_INFO, b);
+ }
+ } else
+ cout << "ALERT!!!! Protocol-Version is NOT 6!! (No Series 5?)!" << endl;
+ break;
+ case NCON_MSG_CHANNEL_DISCONNECT:
+ cout << "channel " << (int) buff.getByte(0) << endl;
+ disconnect(buff.getByte(0));
+ break;
+ case NCON_MSG_NCP_END:
+ cout << buff << endl;
+ break;
+ default:
+ cout << endl;
+ }
+}
+
+int ncp::
+getFirstUnusedChan()
+{
+ for (int cNum = 1; cNum < 8; cNum++) {
+ if (channelPtr[cNum] == NULL) {
+ return cNum;
+ }
+ }
+ return 0;
+}
+
+int ncp::
+connect(channel * ch)
+{
+ // look for first unused chan
+ int cNum = getFirstUnusedChan();
+ if (cNum > 0) {
+ channelPtr[cNum] = ch;
+ ch->setNcpChannel(cNum);
+ bufferStore b;
+ b.addString(ch->getNcpConnectName());
+ b.addByte(0);
+ controlChannel(cNum, NCON_MSG_CONNECT_TO_SERVER, b);
+ return cNum;
+ }
+ return -1;
+}
+
+void ncp::
+send(int channel, bufferStore & a)
+{
+ bool last;
+ do {
+ last = true;
+
+ if (a.getLen() > NCP_SENDLEN)
+ last = false;
+
+ bufferStore out;
+ out.addByte(remoteChanList[channel]);
+ out.addByte(channel);
+
+ if (last) {
+ out.addByte(LAST_MESS);
+ } else {
+ out.addByte(NOT_LAST_MESS);
+ }
+
+ out.addBuff(a, NCP_SENDLEN);
+ a.discardFirstBytes(NCP_SENDLEN);
+ l->send(out);
+ } while (!last);
+}
+
+void ncp::
+disconnect(int channel)
+{
+ channelPtr[channel]->terminateWhenAsked();
+ channelPtr[channel] = NULL;
+ bufferStore b;
+ b.addByte(remoteChanList[channel]);
+ controlChannel(channel, NCON_MSG_CHANNEL_DISCONNECT, b);
+}
+
+bool ncp::
+stuffToSend()
+{
+ return l->stuffToSend();
+}
+
+bool ncp::
+hasFailed()
+{
+ if (failed)
+ return true;
+ return l->hasFailed();
+}
+
+bool ncp::
+gotLinkChannel()
+{
+ return gotLinkChan;
+}
+
+char *ncp::
+ctrlMsgName(unsigned char msgType)
+{
+ switch (msgType) {
+ case NCON_MSG_DATA_XOFF:
+ return "NCON_MSG_DATA_XOFF";
+ case NCON_MSG_DATA_XON:
+ return "NCON_MSG_DATA_XON";
+ case NCON_MSG_CONNECT_TO_SERVER:
+ return "NCON_MSG_CONNECT_TO_SERVER";
+ case NCON_MSG_CONNECT_RESPONSE:
+ return "NCON_MSG_CONNECT_RESPONSE";
+ case NCON_MSG_CHANNEL_CLOSED:
+ return "NCON_MSG_CHANNEL_CLOSED";
+ case NCON_MSG_NCP_INFO:
+ return "NCON_MSG_NCP_INFO";
+ case NCON_MSG_CHANNEL_DISCONNECT:
+ return "NCON_MSG_CHANNEL_DISCONNECT";
+ case NCON_MSG_NCP_END:
+ return "NCON_MSG_NCP_END";
+ }
+ return "NCON_MSG_UNKNOWN";
+}
diff --git a/ncpd/ncp.h b/ncpd/ncp.h
new file mode 100644
index 0000000..9e8444c
--- /dev/null
+++ b/ncpd/ncp.h
@@ -0,0 +1,49 @@
+#ifndef _ncp_h_
+#define _ncp_h_
+
+#include "bool.h"
+#include "bufferstore.h"
+class link;
+class channel;
+class IOWatch;
+
+class ncp {
+ public:
+ ncp(const char *fname, int baud, IOWatch &iow);
+ ~ncp();
+
+ int connect(channel *c); // returns channel, or -1 if failure
+ void disconnect(int channel);
+ void send(int channel, bufferStore &a);
+ void poll();
+ bool stuffToSend();
+ bool hasFailed();
+ bool gotLinkChannel();
+
+ private:
+ enum c { MAX_LEN = 200, LAST_MESS = 1, NOT_LAST_MESS = 2 };
+ enum interControllerMessageType {
+ // Inter controller message types
+ NCON_MSG_DATA_XOFF=1,
+ NCON_MSG_DATA_XON=2,
+ NCON_MSG_CONNECT_TO_SERVER=3,
+ NCON_MSG_CONNECT_RESPONSE=4,
+ NCON_MSG_CHANNEL_CLOSED=5,
+ NCON_MSG_NCP_INFO=6,
+ NCON_MSG_CHANNEL_DISCONNECT=7,
+ NCON_MSG_NCP_END=8
+ };
+ int getFirstUnusedChan();
+ void decodeControlMessage(bufferStore &buff);
+ void controlChannel(int chan, enum interControllerMessageType t, bufferStore &command);
+ char * ctrlMsgName(unsigned char);
+
+ link *l;
+ channel *channelPtr[8];
+ bufferStore messageList[8];
+ int remoteChanList[8];
+ bool gotLinkChan;
+ bool failed;
+};
+
+#endif
diff --git a/ncpd/packet.cc b/ncpd/packet.cc
new file mode 100644
index 0000000..62f6b09
--- /dev/null
+++ b/ncpd/packet.cc
@@ -0,0 +1,226 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+
+#include <stdio.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <string.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <errno.h>
+
+extern "C" {
+#include "mp_serial.h"
+}
+#include "bool.h"
+#include "bufferstore.h"
+#include "packet.h"
+#include "iowatch.h"
+
+#define BUFFERLEN 2000
+
+packet::packet(const char *fname, int _baud, IOWatch & _iow, bool _verbose):
+iow(_iow)
+{
+ verbose = _verbose;
+ devname = strdup(fname);
+ baud = _baud;
+ inPtr = inBuffer = new unsigned char[BUFFERLEN + 1];
+ outPtr = outBuffer = new unsigned char[BUFFERLEN + 1];
+ inLen = outLen = termLen = 0;
+ esc = false;
+ crcIn = crcOut = 0;
+
+ fd = init_serial(devname, baud, 0);
+ iow.addIO(fd);
+}
+
+packet::~packet()
+{
+ iow.remIO(fd);
+ ser_exit(fd);
+ usleep(100000);
+
+ delete[]inBuffer;
+ delete[]outBuffer;
+ free(devname);
+}
+
+void packet::
+send(unsigned char type, const bufferStore & b)
+{
+ if (verbose)
+ cout << "packet: send ";
+ opByte(0x16);
+ opByte(0x10);
+ opByte(0x02);
+
+ crcOut = 0;
+ opByte(type);
+ addToCrc(type, &crcOut);
+
+ long len = b.getLen();
+ for (int i = 0; i < len; i++) {
+ unsigned char c = b.getByte(i);
+ if (c == 0x10)
+ opByte(c);
+ opByte(c);
+ addToCrc(c, &crcOut);
+ }
+
+ opByte(0x10);
+ opByte(0x03);
+
+ opByte(crcOut >> 8);
+ opByte(crcOut & 0xff);
+ if (verbose)
+ cout << endl;
+ realWrite();
+}
+
+void packet::
+addToCrc(unsigned short c, unsigned short *crc)
+{
+ c <<= 8;
+ for (int i = 0; i < 8; i++) {
+ if ((*crc ^ c) & 0x8000)
+ *crc = (*crc << 1) ^ 0x1021;
+ else
+ *crc <<= 1;
+ c <<= 1;
+ }
+}
+
+void packet::
+opByte(unsigned char a)
+{
+ *outPtr++ = a;
+ outLen++;
+ if (verbose)
+ cout << hex << setw(2) << setfill('0') << (int) a << " ";
+ if (outLen >= BUFFERLEN)
+ realWrite();
+}
+
+void packet::
+realWrite()
+{
+ outPtr = outBuffer;
+ while (outLen > 0) {
+ int r = write(fd, outPtr, outLen);
+ if (verbose)
+ cout << "realW:" << dec << r << endl;
+ if (r > 0) {
+ outLen -= r;
+ outPtr += r;
+ }
+ }
+ outPtr = outBuffer;
+}
+
+bool packet::
+get(unsigned char &type, bufferStore & ret)
+{
+ while (!terminated()) {
+ int res = read(fd, inPtr, BUFFERLEN - inLen);
+ if (res > 0) {
+ if (verbose)
+ cout << "packet: rcv " << dec << res << endl;
+ inPtr += res;
+ inLen += res;
+ }
+ if (res < 0)
+ return false;
+ if (inLen >= BUFFERLEN) {
+ cerr << "input Overflow!!!!" << endl;
+ inLen = 0;
+ inPtr = inBuffer;
+ return false;
+ }
+ }
+ if (verbose) {
+ cout << "packet: get ";
+ for (int i = 0; i < termLen; i++)
+ cout << hex << setw(2) << setfill('0') << (int) inBuffer[i] << " ";
+ cout << endl;
+ }
+ inLen -= termLen;
+ termLen = 0;
+ bool crcOk = (endPtr[0] == ((crcIn >> 8) & 0xff) && endPtr[1] == (crcIn & 0xff));
+ if (inLen > 0)
+ memmove(inBuffer, &endPtr[2], inLen);
+ inPtr = inBuffer + inLen;
+ if (crcOk) {
+ type = rcv.getByte(0);
+ ret = rcv;
+ ret.discardFirstBytes(1);
+ return true;
+ } else
+ cout << "packet::Warning - bad crc packet " << endl;
+ return false;
+}
+
+bool packet::
+terminated()
+{
+ unsigned char *p;
+ int l;
+
+ if (inLen < 6)
+ return false;
+ p = inBuffer + termLen;
+ if (termLen == 0) {
+ if (*p++ != 0x16)
+ return false;
+ if (*p++ != 0x10)
+ return false;
+ if (*p++ != 0x02)
+ return false;
+ esc = false;
+ termLen = 3;
+ crcIn = 0;
+ rcv.init();
+ }
+ for (l = termLen; l < inLen - 2; p++, l++) {
+ if (esc) {
+ esc = false;
+ if (*p == 0x03) {
+ endPtr = p + 1;
+ termLen = l + 3;
+ return true;
+ }
+ addToCrc(*p, &crcIn);
+ rcv.addByte(*p);
+ } else {
+ if (*p == 0x10)
+ esc = true;
+ else {
+ addToCrc(*p, &crcIn);
+ rcv.addByte(*p);
+ }
+ }
+ }
+ termLen = l;
+ return false;
+}
diff --git a/ncpd/packet.h b/ncpd/packet.h
new file mode 100644
index 0000000..cd02513
--- /dev/null
+++ b/ncpd/packet.h
@@ -0,0 +1,43 @@
+#ifndef _packet_h
+#define _packet_h
+
+#include <stdio.h>
+
+#include "bool.h"
+class psiEmul;
+class bufferStore;
+class IOWatch;
+
+class packet {
+ public:
+ packet(const char *fname, int baud, IOWatch &iow, bool verbose = false);
+ ~packet();
+ void send(unsigned char type, const bufferStore &b);
+ bool get(unsigned char &type, bufferStore &b);
+
+ private:
+ bool terminated();
+ void addToCrc(unsigned short a, unsigned short *crc);
+ void opByte(unsigned char a);
+ void realWrite();
+
+ unsigned short crcOut;
+ unsigned short crcIn;
+ unsigned char *inPtr;
+ unsigned char *outPtr;
+ unsigned char *endPtr;
+ unsigned char *inBuffer;
+ unsigned char *outBuffer;
+ bufferStore rcv;
+ int inLen;
+ int outLen;
+ int termLen;
+ int fd;
+ bool verbose;
+ bool esc;
+ char *devname;
+ int baud;
+ IOWatch &iow;
+};
+
+#endif
diff --git a/ncpd/socketchan.cc b/ncpd/socketchan.cc
new file mode 100644
index 0000000..0afabf2
--- /dev/null
+++ b/ncpd/socketchan.cc
@@ -0,0 +1,105 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stream.h>
+#include "stdio.h"
+#include "string.h"
+#include "malloc.h"
+
+#include "bool.h"
+#include "socketchan.h"
+#include "ncp.h"
+#include "ppsocket.h"
+#include "iowatch.h"
+
+socketChan::socketChan(ppsocket *_skt, ncp *_ncpController, IOWatch &_iow) :
+ channel(_ncpController),
+ iow(_iow)
+{
+ skt = _skt;
+ connectName = 0;
+ iow.addIO(skt->socket());
+ connected = false;
+}
+
+socketChan::~socketChan() {
+ iow.remIO(skt->socket());
+ skt->closeSocket();
+ delete skt;
+ if (connectName) free(connectName);
+}
+
+void socketChan::ncpDataCallback(bufferStore &a) {
+ if (connectName != 0) {
+ skt->sendBufferStore(a);
+ }
+ else {
+ cerr << "This should not happen\n";
+ }
+}
+
+const char *socketChan::getNcpConnectName() {
+ return connectName;
+}
+
+void socketChan::ncpConnectAck() {
+ bufferStore a;
+ a.addStringT("Ok");
+ skt->sendBufferStore(a);
+ connected = true;
+}
+
+void socketChan::ncpConnectTerminate() {
+ bufferStore a;
+ a.addStringT("Close");
+ skt->sendBufferStore(a);
+ terminateWhenAsked();
+}
+
+void socketChan::socketPoll() {
+ if (connectName == 0) {
+ bufferStore a;
+ if (skt->getBufferStore(a, false) == 1) {
+ connectName = strdup(a.getString());
+ ncpConnect();
+ }
+ }
+ else if (connected) {
+ bufferStore a;
+ int res = skt->getBufferStore(a, false);
+ if ( res == -1 ) {
+ ncpDisconnect();
+ }
+ else if (res == 1) {
+ if (a.getLen() > 5 &&
+ !strncmp(a.getString(), "Close", 5)) {
+ ncpDisconnect();
+ }
+ else {
+ ncpSend(a);
+ }
+ }
+ }
+}
+
+bool socketChan::isConnected() const {
+ return connected;
+}
diff --git a/ncpd/socketchan.h b/ncpd/socketchan.h
new file mode 100644
index 0000000..0911c0c
--- /dev/null
+++ b/ncpd/socketchan.h
@@ -0,0 +1,28 @@
+#ifndef _socketchan_h_
+#define _socketchan_h_
+
+#include "bool.h"
+#include "channel.h"
+class ppsocket;
+class IOWatch;
+
+class socketChan : public channel {
+public:
+ socketChan(ppsocket* comms, ncp* ncpController, IOWatch &iow);
+ virtual ~socketChan();
+
+ void ncpDataCallback(bufferStore& a);
+ const char* getNcpConnectName();
+ void ncpConnectAck();
+ void ncpConnectTerminate();
+
+ bool isConnected() const;
+ void socketPoll();
+private:
+ ppsocket* skt;
+ IOWatch &iow;
+ char* connectName;
+ bool connected;
+};
+
+#endif