aboutsummaryrefslogtreecommitdiffstats
path: root/ncpd
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2001-07-23 19:45:20 +0000
committerFritz Elfert <felfert@to.com>2001-07-23 19:45:20 +0000
commit24f74bf9c5c97f8b3ee4f6658e9dac41f93f41a4 (patch)
tree2423ca1b31d77d089055c7fef1e926603fc9c5ca /ncpd
parent0c63f12fc440ddd144f95170d9d903aeb9b7ef2c (diff)
downloadplptools-24f74bf9c5c97f8b3ee4f6658e9dac41f93f41a4.tar.gz
plptools-24f74bf9c5c97f8b3ee4f6658e9dac41f93f41a4.tar.bz2
plptools-24f74bf9c5c97f8b3ee4f6658e9dac41f93f41a4.zip
- Support NCP xon/xoff frames.
- Support up to 256 channels on S5
Diffstat (limited to 'ncpd')
-rw-r--r--ncpd/link.cc64
-rw-r--r--ncpd/link.h2
-rw-r--r--ncpd/main.cc10
-rw-r--r--ncpd/ncp.cc115
-rw-r--r--ncpd/ncp.h14
5 files changed, 146 insertions, 59 deletions
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 <bufferarray.h>
+#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