aboutsummaryrefslogtreecommitdiffstats
path: root/ncpd/ncp.cc
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/ncp.cc
parentf3e248b6e75c7ce5beda577f5712915417313b0a (diff)
downloadplptools-6ab1aa5f2156ef781da6e1b57a183825b88bef9a.tar.gz
plptools-6ab1aa5f2156ef781da6e1b57a183825b88bef9a.tar.bz2
plptools-6ab1aa5f2156ef781da6e1b57a183825b88bef9a.zip
Initial import
Diffstat (limited to 'ncpd/ncp.cc')
-rw-r--r--ncpd/ncp.cc292
1 files changed, 292 insertions, 0 deletions
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";
+}