From 6ab1aa5f2156ef781da6e1b57a183825b88bef9a Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Tue, 29 Jun 1999 02:23:31 +0000 Subject: Initial import --- ncpd/ncp.cc | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 ncpd/ncp.cc (limited to 'ncpd/ncp.cc') 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 +#include +#include + +#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"; +} -- cgit v1.2.3