From 24f74bf9c5c97f8b3ee4f6658e9dac41f93f41a4 Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Mon, 23 Jul 2001 19:45:20 +0000 Subject: - Support NCP xon/xoff frames. - Support up to 256 channels on S5 --- ncpd/link.cc | 64 +++++++++++++++++++++++++++++---- ncpd/link.h | 2 ++ ncpd/main.cc | 10 +++--- ncpd/ncp.cc | 115 +++++++++++++++++++++++++++++++++++++---------------------- ncpd/ncp.h | 14 ++++---- 5 files changed, 146 insertions(+), 59 deletions(-) (limited to 'ncpd') diff --git a/ncpd/link.cc b/ncpd/link.cc index 7612b93..6811d10 100644 --- a/ncpd/link.cc +++ b/ncpd/link.cc @@ -44,6 +44,8 @@ link::link(const char *fname, int baud, IOWatch & iow, unsigned short _verbose) somethingToSend = false; timesSent = 0; failed = false; + for (int i; i < 256; i++) + xoff[i] = false; } link::~link() @@ -60,7 +62,8 @@ reset() { somethingToSend = false; timesSent = 0; failed = false; - // p->reset(); + for (int i; i < 256; i++) + xoff[i] = false; } short int link:: @@ -96,6 +99,20 @@ send(const bufferStore & buff) sendQueue += buff; } +void link:: +purgeQueue(int channel) +{ + bufferArray hsendQueue; + bufferStore b; + + while (!sendQueue.empty()) { + b = sendQueue.pop(); + if (b.getByte(0) != channel) + hsendQueue += b; + } + sendQueue = hsendQueue; +} + bufferArray link:: poll() { @@ -129,7 +146,26 @@ poll() // Send ack if (idLastGot != seq) { idLastGot = seq; - ret += buff; + // Must check for XOFF/XON ncp frames HERE! + if ((buff.getLen() == 3) && (buff.getByte(0) == 0)) { + switch (buff.getByte(2)) { + case 1: + // XOFF + xoff[buff.getByte(1)] = true; + if (verbose & LNK_DEBUG_LOG) + cout << "link: got XOFF for channel " << buff.getByte(1) << endl; + break; + case 2: + // XON + xoff[buff.getByte(1)] = false; + if (verbose & LNK_DEBUG_LOG) + cout << "link: got XON for channel " << buff.getByte(1) << endl; + break; + default: + ret += buff; + } + } else + ret += buff; } else { if (verbose & LNK_DEBUG_LOG) cout << "link: DUP\n"; @@ -147,6 +183,7 @@ poll() p->send(seq, blank); break; + case 0x00: // Incoming ack if (seq == idSent) { @@ -160,6 +197,7 @@ poll() timesSent = 0; } break; + case 0x20: // New link if (verbose & LNK_DEBUG_LOG) { @@ -175,6 +213,7 @@ poll() blank.init(); p->send(idLastGot, blank); break; + case 0x10: // Disconnect if (verbose & LNK_DEBUG_LOG) @@ -197,15 +236,25 @@ poll() newLink = false; idSent = 0; } else { - if (!sendQueue.empty()) { - somethingToSend = true; + bufferArray hsendQueue; + + while (!sendQueue.empty()) { toSend = sendQueue.pop(); - idSent++; - if (idSent > 7) - idSent = 0; + int remoteChan = toSend.getByte(0); + if (xoff[remoteChan]) + hsendQueue += toSend; + else { + somethingToSend = true; + idSent++; + if (idSent > 7) + idSent = 0; + break; + } } + sendQueue = hsendQueue + sendQueue; } } + if (somethingToSend) { if (countToResend == 0) { timesSent++; @@ -231,6 +280,7 @@ poll() } else countToResend--; } + return ret; } diff --git a/ncpd/link.h b/ncpd/link.h index 010100b..f8a7d73 100644 --- a/ncpd/link.h +++ b/ncpd/link.h @@ -47,6 +47,7 @@ class link { bool hasFailed(); void reset(); void flush(); + void purgeQueue(int); void setVerbose(short int); short int getVerbose(); void setPktVerbose(short int); @@ -64,6 +65,7 @@ class link { unsigned short verbose; bool somethingToSend; bool failed; + bool xoff[256]; }; #endif diff --git a/ncpd/main.cc b/ncpd/main.cc index d8a28ed..b9eb5af 100644 --- a/ncpd/main.cc +++ b/ncpd/main.cc @@ -71,17 +71,19 @@ checkForNewSocketConnection(ppsocket & skt, int &numScp, socketChan ** scp, ncp // New connect if (verbose) cout << "New socket connection from " << peer << endl; - if ((numScp == 7) || (!a->gotLinkChannel())) { + if ((numScp >= a->maxLinks()) || (!a->gotLinkChannel())) { bufferStore a; // Give the client time to send it's version request. - next->dataToGet(1,0); + next->dataToGet(1, 0); next->getBufferStore(a, false); a.init(); a.addStringT("No Psion Connected\n"); next->sendBufferStore(a); next->closeSocket(); + if (verbose) + cout << "rejected" << endl; } else scp[numScp++] = new socketChan(next, a); } @@ -183,7 +185,7 @@ main(int argc, char **argv) else serialDevice = DDEV; } - + if (dofork) pid = fork(); else @@ -210,7 +212,7 @@ main(int argc, char **argv) } ncp *a = new ncp(serialDevice, baudRate, iow); int numScp = 0; - socketChan *scp[MAX_CHANNEL+1]; + socketChan *scp[a->maxLinks() + 1]; a->setVerbose(nverbose); a->setLinkVerbose(lverbose); diff --git a/ncpd/ncp.cc b/ncpd/ncp.cc index 31ce2c3..891fc9f 100644 --- a/ncpd/ncp.cc +++ b/ncpd/ncp.cc @@ -35,40 +35,59 @@ #include "link.h" #include +#define MAX_CHANNELS_PSION 256 +#define MAX_CHANNELS_SIBO 8 #define NCP_SENDLEN 250 ncp::ncp(const char *fname, int baud, IOWatch & iow) { + channelPtr = new channel*[MAX_CHANNELS_PSION + 1]; + messageList = new bufferStore[MAX_CHANNELS_PSION + 1]; + remoteChanList = new int[MAX_CHANNELS_PSION + 1]; + l = new link(fname, baud, iow); failed = false; verbose = 0; - protocolVersion = PV_SERIES_5; // until detected on receipt of INFO + + // until detected on receipt of INFO we use these. + maxChannels = MAX_CHANNELS_SIBO; + protocolVersion = PV_SERIES_5; // init channels - for (int i = 0; i < MAX_CHANNEL; i++) + for (int i = 0; i < maxLinks(); i++) channelPtr[i] = NULL; } ncp::~ncp() { bufferStore b; - for (int i = 0; i < MAX_CHANNEL; i++) { + for (int i = 0; i < maxLinks(); i++) { if (channelPtr[i]) { bufferStore b2; b2.addByte(remoteChanList[i]); controlChannel(i, NCON_MSG_CHANNEL_DISCONNECT, b2); } + delete channelPtr[i]; channelPtr[i] = NULL; } controlChannel(0, NCON_MSG_NCP_END, b); delete l; + delete channelPtr; + delete messageList; + delete remoteChanList; +} + +int ncp:: +maxLinks() { + return maxChannels; } void ncp:: reset() { - for (int i = 0; i < MAX_CHANNEL; i++) { + for (int i = 0; i < maxLinks(); i++) { if (channelPtr[i]) channelPtr[i]->terminateWhenAsked(); + delete channelPtr[i]; channelPtr[i] = NULL; } failed = false; @@ -123,34 +142,30 @@ void ncp:: poll() { bufferArray res(l->poll()); - if (!res.empty()) { - do { - bufferStore s = res.pop(); - if (s.getLen() > 1) { - int channel = s.getByte(0); - s.discardFirstBytes(1); - if (channel == 0) { - decodeControlMessage(s); + while (!res.empty()) { + bufferStore s = res.pop(); + if (s.getLen() > 1) { + int channel = s.getByte(0); + s.discardFirstBytes(1); + if (channel == 0) { + decodeControlMessage(s); + } else { + int allData = s.getByte(1); + s.discardFirstBytes(2); + if (channelPtr[channel] == NULL) { + cerr << "ncp: Got message for unknown channel\n"; } else { - /* int remChan = */ s.getByte(0); - int allData = s.getByte(1); - s.discardFirstBytes(2); - if (channelPtr[channel] == NULL) { - cerr << "ncp: 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"; - } + 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()); + } else + cerr << "Got null message\n"; } } @@ -172,21 +187,23 @@ void ncp:: decodeControlMessage(bufferStore & buff) { int remoteChan = buff.getByte(0); - short int ver; - interControllerMessageType imt = (interControllerMessageType) buff.getByte(1); + + interControllerMessageType imt = (interControllerMessageType)buff.getByte(1); buff.discardFirstBytes(2); if (verbose & NCP_DEBUG_LOG) cout << "ncp: << " << ctrlMsgName(imt) << " " << remoteChan; + + bufferStore b; + switch (imt) { case NCON_MSG_CONNECT_TO_SERVER: - { if (verbose & NCP_DEBUG_LOG) { if (verbose & NCP_DEBUG_DUMP) cout << " [" << buff << "]"; cout << endl; } + int localChan; - bufferStore b; // Ack with connect response localChan = getFirstUnusedChan(); @@ -215,11 +232,13 @@ decodeControlMessage(bufferStore & buff) b.addByte(remoteChan); controlChannel(localChan, NCON_MSG_CHANNEL_DISCONNECT, b); } - } - break; + break; + case NCON_MSG_CONNECT_RESPONSE: - { - int forChan = buff.getByte(0); + + int forChan; + + forChan = buff.getByte(0); if (verbose & NCP_DEBUG_LOG) cout << " ch=" << forChan << " stat="; if (buff.getByte(1) == 0) { @@ -237,9 +256,12 @@ decodeControlMessage(bufferStore & buff) cout << "Unknown " << (int) buff.getByte(1) << endl; channelPtr[forChan]->ncpConnectNak(); } - } - break; + break; + case NCON_MSG_NCP_INFO: + + int ver; + ver = buff.getByte(0); // Series 3c returns '3', as does mclink. PsiWin 1.1 // returns version 2. We return whatever version we're @@ -256,8 +278,12 @@ decodeControlMessage(bufferStore & buff) cout << endl; } // Fake NCP version 2 for a Series 3 (behave like PsiWin 1.1) - if (ver == PV_SERIES_3) + if (ver == PV_SERIES_3) { ver = 2; + } else { + // Series 5 supports more channels + maxChannels = MAX_CHANNELS_PSION; + } b.addByte(ver); // Do we send a time of 0 or a real time? // The Psion uses this to determine whether to @@ -268,11 +294,14 @@ decodeControlMessage(bufferStore & buff) } else cout << "ALERT!!!! Unexpected Protocol Version!! (No Series 5/3?)!" << endl; break; + case NCON_MSG_CHANNEL_DISCONNECT: if (verbose & NCP_DEBUG_LOG) cout << " ch=" << (int) buff.getByte(0) << endl; disconnect(buff.getByte(0)); + l->purgeQueue(remoteChan); break; + case NCON_MSG_DATA_XOFF: case NCON_MSG_DATA_XON: case NCON_MSG_CHANNEL_CLOSED: @@ -283,13 +312,14 @@ decodeControlMessage(bufferStore & buff) cout << " [" << buff << "]"; cout << endl; } + } } int ncp:: getFirstUnusedChan() { - for (int cNum = 1; cNum < MAX_CHANNEL; cNum++) { + for (int cNum = 1; cNum < maxLinks(); cNum++) { if (channelPtr[cNum] == NULL) { if (verbose & NCP_DEBUG_LOG) cout << "ncp: getFirstUnusedChan=" << cNum << endl; @@ -304,9 +334,9 @@ RegisterAck(int chan, const char *name) { if (verbose & NCP_DEBUG_LOG) cout << "ncp: RegisterAck: chan=" << chan << endl; - for (int cNum = 1; cNum < MAX_CHANNEL; cNum++) { + for (int cNum = 1; cNum < maxLinks(); cNum++) { channel *ch = channelPtr[cNum]; - if (ch->getNcpChannel() == chan) { + if (ch && ch->getNcpChannel() == chan) { ch->setNcpConnectName(name); ch->ncpRegisterAck(); return; @@ -393,6 +423,7 @@ disconnect(int channel) channelPtr[channel]->terminateWhenAsked(); if (verbose & NCP_DEBUG_LOG) cout << "ncp: disconnect: channel=" << channel << endl; + delete channelPtr[channel]; channelPtr[channel] = NULL; bufferStore b; b.addByte(remoteChanList[channel]); diff --git a/ncpd/ncp.h b/ncpd/ncp.h index 1c4cbdc..abbf08e 100644 --- a/ncpd/ncp.h +++ b/ncpd/ncp.h @@ -35,7 +35,6 @@ class IOWatch; #define NCP_DEBUG_LOG 1 #define NCP_DEBUG_DUMP 2 -#define MAX_CHANNEL 8 class ncp { public: @@ -49,9 +48,11 @@ public: void send(int channel, bufferStore &a); void poll(); void reset(); + int maxLinks(); bool stuffToSend(); bool hasFailed(); bool gotLinkChannel(); + void setVerbose(short int); short int getVerbose(); void setLinkVerbose(short int); @@ -59,7 +60,7 @@ public: void setPktVerbose(short int); short int getPktVerbose(); short int getProtocolVersion(); - + private: enum c { MAX_LEN = 200, LAST_MESS = 1, NOT_LAST_MESS = 2 }; enum interControllerMessageType { @@ -78,15 +79,16 @@ private: void decodeControlMessage(bufferStore &buff); void controlChannel(int chan, enum interControllerMessageType t, bufferStore &command); char * ctrlMsgName(unsigned char); - + link *l; unsigned short verbose; - channel *channelPtr[MAX_CHANNEL+1]; - bufferStore messageList[MAX_CHANNEL+1]; - int remoteChanList[MAX_CHANNEL+1]; + channel **channelPtr; + bufferStore *messageList; + int *remoteChanList; bool failed; short int protocolVersion; linkChan *lChan; + int maxChannels; }; #endif -- cgit v1.2.3