aboutsummaryrefslogtreecommitdiffstats
path: root/ncpd
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2000-01-17 11:49:41 +0000
committerFritz Elfert <felfert@to.com>2000-01-17 11:49:41 +0000
commitab18114bfd38d4632c66401b5bc079241e27fab3 (patch)
tree14f9c1d5f020cf8ed2f205094ca9e2fc907bb969 /ncpd
parent6eceb82662300bf306e70bd943200665bc3c9bc3 (diff)
downloadplptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.gz
plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.bz2
plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.zip
Release of plptools-0.5
Diffstat (limited to 'ncpd')
-rw-r--r--ncpd/channel.cc25
-rw-r--r--ncpd/channel.h11
-rw-r--r--ncpd/linkchan.cc61
-rw-r--r--ncpd/linkchan.h9
-rw-r--r--ncpd/main.cc12
-rw-r--r--ncpd/ncp.cc101
-rw-r--r--ncpd/ncp.h15
-rw-r--r--ncpd/packet.cc11
-rw-r--r--ncpd/packet.h3
-rw-r--r--ncpd/socketchan.cc107
-rw-r--r--ncpd/socketchan.h8
11 files changed, 326 insertions, 37 deletions
diff --git a/ncpd/channel.cc b/ncpd/channel.cc
index a75c791..f52cea1 100644
--- a/ncpd/channel.cc
+++ b/ncpd/channel.cc
@@ -32,6 +32,7 @@
channel::channel(ncp * _ncpController)
{
verbose = 0;
+ ncpChannel = 0;
ncpController = _ncpController;
_terminate = false;
}
@@ -61,17 +62,41 @@ ncpConnect()
}
void channel::
+ncpRegister()
+{
+ ncpController->Register(this);
+}
+
+void channel::
+ncpDoRegisterAck(int ch)
+{
+ ncpController->RegisterAck(ch);
+}
+
+void channel::
ncpDisconnect()
{
ncpController->disconnect(ncpChannel);
}
+short int channel::
+ncpProtocolVersion()
+{
+ return ncpController->getProtocolVersion();
+}
+
void channel::
setNcpChannel(int chan)
{
ncpChannel = chan;
}
+int channel::
+getNcpChannel()
+{
+ return ncpChannel;
+}
+
void channel::
newNcpController(ncp * _ncpController)
{
diff --git a/ncpd/channel.h b/ncpd/channel.h
index a8f5225..2c06d6d 100644
--- a/ncpd/channel.h
+++ b/ncpd/channel.h
@@ -35,18 +35,25 @@ class bufferStore;
class channel {
public:
channel(ncp *ncpController);
+ virtual ~channel() {}
void newNcpController(ncp *ncpController);
void setNcpChannel(int chan);
+ int getNcpChannel(void);
void ncpSend(bufferStore &a);
void setVerbose(short int _verbose);
short int getVerbose();
virtual void ncpDataCallback(bufferStore &a) = NULL;
- virtual const char *getNcpConnectName() = NULL;
+ virtual char *getNcpConnectName() = NULL;
void ncpConnect();
+ void ncpRegister();
+ void ncpDoRegisterAck(int);
virtual void ncpConnectAck() = NULL;
virtual void ncpConnectTerminate() = NULL;
+ virtual void ncpConnectNak() = NULL;
+ virtual void ncpRegisterAck() = NULL;
void ncpDisconnect();
+ short int ncpProtocolVersion();
// The following two calls are used for destructing an instance
virtual bool terminate(); // Mainloop will terminate this class if true
@@ -57,8 +64,8 @@ class channel {
private:
ncp *ncpController;
- bool _terminate;
int ncpChannel;
+ bool _terminate;
};
#endif
diff --git a/ncpd/linkchan.cc b/ncpd/linkchan.cc
index e4891c1..4a2a4d4 100644
--- a/ncpd/linkchan.cc
+++ b/ncpd/linkchan.cc
@@ -23,30 +23,63 @@
// e-mail philip.proudman@btinternet.com
#include <stream.h>
+#include <iomanip.h>
#include "linkchan.h"
#include "bufferstore.h"
+#include "bufferarray.h"
linkChan::linkChan(ncp * _ncpController):channel(_ncpController)
{
+ registerSer = 0x1234;
+ ncpConnect();
}
void linkChan::
ncpDataCallback(bufferStore & a)
{
+ int len = a.getLen();
if (verbose & LINKCHAN_DEBUG_LOG) {
cout << "linkchan: << msg ";
if (verbose & LINKCHAN_DEBUG_DUMP)
cout << a << endl;
else
- cout << a.getLen() << endl;
+ cout << len << endl;
}
+ if ((len > 7) && (a.getByte(0) == 1)) {
+ unsigned int ser = a.getWord(1);
+ int res = a.getWord(3);
+ // int dontknow = a.getWord(5);
+ const char *srvName = a.getString(7);
+ bufferArray newStack;
+ bufferStore se;
+
+ if (verbose & LINKCHAN_DEBUG_LOG)
+ cout << "linkchan: received registerAck: ser=0x" << hex << setw(4)
+ << setfill(0) << ser << " res=" << res << " srvName=\""
+ << srvName << "\"" << endl;
+
+ while (!registerStack.empty()) {
+ se = registerStack.popBuffer();
+ if (se.getWord(0) == ser) {
+ if (verbose & LINKCHAN_DEBUG_LOG)
+ cout << "linkchan: found ser=0x" << hex << setw(4) <<
+ setfill(0) << se.getWord(0) <<
+ " on stack -> callBack to waiting chan" << endl;
+ ncpDoRegisterAck((int)se.getWord(2));
+ } else
+ newStack.pushBuffer(se);
+ }
+ registerStack = newStack;
+ return;
+ }
+ cerr << "linkchan: unknown message " << a.getByte(0) << endl;
}
-const char *linkChan::
+char *linkChan::
getNcpConnectName()
{
- return "LINK.*";
+ return "LINK";
}
void linkChan::
@@ -63,3 +96,25 @@ ncpConnectTerminate()
cout << "linkchan: << ctrm" << endl;
terminateWhenAsked();
}
+
+void linkChan::
+ncpConnectNak()
+{
+ ncpConnectTerminate();
+}
+
+void linkChan::
+Register(channel *ch)
+{
+ bufferStore a;
+ bufferStore stack;
+
+ stack.addWord(registerSer);
+ stack.addWord(ch->getNcpChannel());
+ registerStack.pushBuffer(stack);
+ a.addByte(0);
+ a.addWord(registerSer++);
+ a.addString(ch->getNcpConnectName());
+ a.addByte(0);
+ ncpSend(a);
+}
diff --git a/ncpd/linkchan.h b/ncpd/linkchan.h
index 2e2f7b9..4be75d0 100644
--- a/ncpd/linkchan.h
+++ b/ncpd/linkchan.h
@@ -26,6 +26,7 @@
#define _linkchan_h_
#include "channel.h"
+#include "bufferarray.h"
#define LINKCHAN_DEBUG_LOG 1
#define LINKCHAN_DEBUG_DUMP 2
@@ -35,9 +36,15 @@ class linkChan : public channel {
linkChan(ncp *ncpController);
void ncpDataCallback(bufferStore &a);
- const char *getNcpConnectName();
+ char *getNcpConnectName();
void ncpConnectAck();
void ncpConnectTerminate();
+ void ncpConnectNak();
+ void ncpRegisterAck() {}
+ void Register(channel *);
+ private:
+ int registerSer;
+ bufferArray registerStack;
};
#endif
diff --git a/ncpd/main.cc b/ncpd/main.cc
index 101d7aa..3a0ddb6 100644
--- a/ncpd/main.cc
+++ b/ncpd/main.cc
@@ -52,7 +52,7 @@ checkForNewSocketConnection(ppsocket & skt, int &numScp, socketChan ** scp, ncp
cout << "New socket connection from " << peer << endl;
if ((numScp == 7) || (!a->gotLinkChannel())) {
bufferStore a;
- a.addStringT("No psion");
+ a.addStringT("No Psion Connected\n");
next->sendBufferStore(a);
next->closeSocket();
} else
@@ -119,8 +119,16 @@ main(int argc, char **argv)
pverbose |= PKT_DEBUG_LOG;
if (!strcmp(argv[i], "pd"))
pverbose |= PKT_DEBUG_DUMP;
+ if (!strcmp(argv[i], "ph"))
+ lverbose |= PKT_DEBUG_HANDSHAKE;
if (!strcmp(argv[i], "m"))
verbose = true;
+ if (!strcmp(argv[i], "all")) {
+ nverbose = NCP_DEBUG_LOG | NCP_DEBUG_DUMP;
+ lverbose = LNK_DEBUG_LOG | LNK_DEBUG_DUMP;
+ pverbose = PKT_DEBUG_LOG | PKT_DEBUG_DUMP;
+ verbose = true;
+ }
} else if (!strcmp(argv[i], "-b") && i + 1 < argc) {
baudRate = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-d")) {
@@ -152,7 +160,7 @@ main(int argc, char **argv)
}
ncp *a = new ncp(serialDevice, baudRate, iow);
int numScp = 0;
- socketChan *scp[8];
+ socketChan *scp[MAX_CHANNEL+1];
a->setVerbose(nverbose);
a->setLinkVerbose(lverbose);
diff --git a/ncpd/ncp.cc b/ncpd/ncp.cc
index b13ba62..e1bf96a 100644
--- a/ncpd/ncp.cc
+++ b/ncpd/ncp.cc
@@ -41,9 +41,10 @@ ncp::ncp(const char *fname, int baud, IOWatch & iow)
l = new link(fname, baud, iow);
failed = false;
verbose = 0;
+ protocolVersion = PV_SERIES_5; // until detected on receipt of INFO
// init channels
- for (int i = 0; i < 8; i++)
+ for (int i = 0; i < MAX_CHANNEL; i++)
channelPtr[i] = NULL;
}
@@ -54,13 +55,13 @@ ncp::~ncp()
void ncp::
reset() {
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_CHANNEL; i++) {
if (channelPtr[i])
channelPtr[i]->terminateWhenAsked();
channelPtr[i] = NULL;
}
failed = false;
- gotLinkChan = false;
+ lChan = NULL;
l->reset();
}
@@ -100,6 +101,12 @@ setPktVerbose(short int _verbose)
l->setPktVerbose(_verbose);
}
+short int ncp::
+getProtocolVersion()
+{
+ return protocolVersion;
+}
+
void ncp::
poll()
{
@@ -153,6 +160,7 @@ void ncp::
decodeControlMessage(bufferStore & buff)
{
int remoteChan = buff.getByte(0);
+ short int ver;
interControllerMessageType imt = (interControllerMessageType) buff.getByte(1);
buff.discardFirstBytes(2);
if (verbose & NCP_DEBUG_LOG)
@@ -162,7 +170,7 @@ decodeControlMessage(bufferStore & buff)
{
if (verbose & NCP_DEBUG_LOG) {
if (verbose & NCP_DEBUG_DUMP)
- cout << " " << buff;
+ cout << " [" << buff << "]";
cout << endl;
}
int localChan;
@@ -174,15 +182,20 @@ decodeControlMessage(bufferStore & buff)
b.addByte(0x0);
controlChannel(localChan, NCON_MSG_CONNECT_RESPONSE, b);
+ // NOTE: we don't allow connections from the
+ // Psion to any local "processes" other than
+ // LINK.* - Matt might need to change this for
+ // his NCP<->TCP/IP bridge code...
+
if (!strcmp(buff.getString(0), "LINK.*")) {
- if (gotLinkChan)
+ if (lChan)
failed = true;
if (verbose & NCP_DEBUG_LOG)
cout << "ncp: Link UP" << endl;
- channelPtr[localChan] = new linkChan(this);
- channelPtr[localChan]->setNcpChannel(localChan);
- channelPtr[localChan]->ncpConnectAck();
- gotLinkChan = true;
+ channelPtr[localChan] = lChan = new linkChan(this);
+ lChan->setNcpChannel(localChan);
+ lChan->ncpConnectAck();
+ lChan->setVerbose(verbose);
} else {
if (verbose & NCP_DEBUG_LOG)
cout << "ncp: Link DOWN" << endl;
@@ -196,7 +209,7 @@ decodeControlMessage(bufferStore & buff)
{
int forChan = buff.getByte(0);
if (verbose & NCP_DEBUG_LOG)
- cout << "ch=" << forChan << " stat=";
+ cout << " ch=" << forChan << " stat=";
if (buff.getByte(1) == 0) {
if (verbose & NCP_DEBUG_LOG)
cout << "OK" << endl;
@@ -205,28 +218,43 @@ decodeControlMessage(bufferStore & buff)
channelPtr[forChan]->ncpConnectAck();
} else {
if (verbose & NCP_DEBUG_LOG)
- cout << "ncp: message for unknown channel\n";
+ cout << "ncp: message for unknown channel" << endl;
}
} else {
if (verbose & NCP_DEBUG_LOG)
cout << "Unknown " << (int) buff.getByte(1) << endl;
- channelPtr[forChan]->ncpConnectTerminate();
+ channelPtr[forChan]->ncpConnectNak();
}
}
break;
case NCON_MSG_NCP_INFO:
- if (buff.getByte(0) == 6) {
+ ver = buff.getByte(0);
+ // Series 3c returns '3', as does mclink. PsiWin 1.1
+ // returns version 2. We return whatever version we're
+ // sent, which is rather crude, but works for Series 3
+ // and probably 5. If Symbian have changed EPOC Connect
+ // for the Series 5mx/7, this may need to change.
+ //
+ if (ver == PV_SERIES_5 || ver == PV_SERIES_3) {
bufferStore b;
+ protocolVersion = ver;
if (verbose & NCP_DEBUG_LOG) {
if (verbose & NCP_DEBUG_DUMP)
- cout << " " << buff;
+ cout << " [" << buff << "]";
cout << endl;
}
- b.addByte(6);
- b.addDWord(0);
+ // Fake NCP version 2 for a Series 3 (behave like PsiWin 1.1)
+ if (ver == PV_SERIES_3)
+ ver = 2;
+ b.addByte(ver);
+ // Do we send a time of 0 or a real time?
+ // The Psion uses this to determine whether to
+ // restart. (See protocol docs for details)
+ // b.addDWord(0);
+ b.addDWord(time(NULL));
controlChannel(0, NCON_MSG_NCP_INFO, b);
} else
- cout << "ALERT!!!! Protocol-Version is NOT 6!! (No Series 5?)!" << endl;
+ cout << "ALERT!!!! Unexpected Protocol Version!! (No Series 5/3?)!" << endl;
break;
case NCON_MSG_CHANNEL_DISCONNECT:
if (verbose & NCP_DEBUG_LOG)
@@ -240,7 +268,7 @@ decodeControlMessage(bufferStore & buff)
default:
if (verbose & NCP_DEBUG_LOG) {
if (verbose & NCP_DEBUG_DUMP)
- cout << " " << buff;
+ cout << " [" << buff << "]";
cout << endl;
}
}
@@ -249,24 +277,53 @@ decodeControlMessage(bufferStore & buff)
int ncp::
getFirstUnusedChan()
{
- for (int cNum = 1; cNum < 8; cNum++) {
+ for (int cNum = 1; cNum < MAX_CHANNEL; cNum++) {
if (channelPtr[cNum] == NULL) {
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: getFirstUnusedChan=" << cNum << endl;
return cNum;
}
}
return 0;
}
+void ncp::
+RegisterAck(int chan)
+{
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: RegisterAck: chan=" << chan << endl;
+ for (int cNum = 1; cNum < MAX_CHANNEL; cNum++) {
+ channel *ch = channelPtr[cNum];
+ if (ch->getNcpChannel() == chan) {
+ ch->ncpRegisterAck();
+ return;
+ }
+ }
+ cerr << "ncp: RegisterAck: no channel to deliver" << endl;
+}
+
+void ncp::
+Register(channel * ch)
+{
+ if (lChan)
+ lChan->Register(ch);
+ else
+ cerr << "ncp: Register without established lChan" << endl;
+}
+
int ncp::
connect(channel * ch)
{
// look for first unused chan
- int cNum = getFirstUnusedChan();
+ int cNum = ch->getNcpChannel();
+ if (cNum == 0)
+ cNum = getFirstUnusedChan();
if (cNum > 0) {
channelPtr[cNum] = ch;
ch->setNcpChannel(cNum);
bufferStore b;
b.addString(ch->getNcpConnectName());
+ b.addString(".*");
b.addByte(0);
controlChannel(cNum, NCON_MSG_CONNECT_TO_SERVER, b);
return cNum;
@@ -304,6 +361,8 @@ void ncp::
disconnect(int channel)
{
channelPtr[channel]->terminateWhenAsked();
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: disconnect: channel=" << channel << endl;
channelPtr[channel] = NULL;
bufferStore b;
b.addByte(remoteChanList[channel]);
@@ -327,7 +386,7 @@ hasFailed()
bool ncp::
gotLinkChannel()
{
- return gotLinkChan;
+ return (lChan != NULL);
}
char *ncp::
diff --git a/ncpd/ncp.h b/ncpd/ncp.h
index f24edc6..c71fdc1 100644
--- a/ncpd/ncp.h
+++ b/ncpd/ncp.h
@@ -27,12 +27,14 @@
#include "bool.h"
#include "bufferstore.h"
+#include "linkchan.h"
class link;
class channel;
class IOWatch;
#define NCP_DEBUG_LOG 1
#define NCP_DEBUG_DUMP 2
+#define MAX_CHANNEL 8
class ncp {
public:
@@ -40,6 +42,8 @@ class ncp {
~ncp();
int connect(channel *c); // returns channel, or -1 if failure
+ void Register(channel *c);
+ void RegisterAck(int);
void disconnect(int channel);
void send(int channel, bufferStore &a);
void poll();
@@ -53,6 +57,7 @@ class ncp {
short int getLinkVerbose();
void setPktVerbose(short int);
short int getPktVerbose();
+ short int getProtocolVersion();
private:
enum c { MAX_LEN = 200, LAST_MESS = 1, NOT_LAST_MESS = 2 };
@@ -67,6 +72,7 @@ class ncp {
NCON_MSG_CHANNEL_DISCONNECT=7,
NCON_MSG_NCP_END=8
};
+ enum protocolVersionType { PV_SERIES_5 = 6, PV_SERIES_3 = 3 };
int getFirstUnusedChan();
void decodeControlMessage(bufferStore &buff);
void controlChannel(int chan, enum interControllerMessageType t, bufferStore &command);
@@ -74,11 +80,12 @@ class ncp {
link *l;
unsigned short verbose;
- channel *channelPtr[8];
- bufferStore messageList[8];
- int remoteChanList[8];
- bool gotLinkChan;
+ channel *channelPtr[MAX_CHANNEL+1];
+ bufferStore messageList[MAX_CHANNEL+1];
+ int remoteChanList[MAX_CHANNEL+1];
bool failed;
+ short int protocolVersion;
+ linkChan *lChan;
};
#endif
diff --git a/ncpd/packet.cc b/ncpd/packet.cc
index 8099bb9..26823c8 100644
--- a/ncpd/packet.cc
+++ b/ncpd/packet.cc
@@ -33,6 +33,7 @@
#include <iomanip.h>
#include <errno.h>
#include <sys/ioctl.h>
+#include <termios.h>
extern "C" {
#include "mp_serial.h"
@@ -170,6 +171,10 @@ get(unsigned char &type, bufferStore & ret)
}
if (res < 0)
return false;
+ // XXX Solaris returns 0 on non blocking TTY lines
+ // even when VMIN > 0
+ if( res == 0 && inLen == 0 )
+ return false;
if (inLen >= BUFFERLEN) {
cerr << "packet: input buffer overflow!!!!" << endl;
inLen = 0;
@@ -256,13 +261,17 @@ linkFailed()
int res = ioctl(fd, TIOCMGET, &arg);
if (res < 0)
failed = true;
- if (verbose & PKT_DEBUG_DUMP)
+ if (verbose & PKT_DEBUG_HANDSHAKE)
cout << "packet: DTR:" << ((arg & TIOCM_DTR)?1:0)
<< " RTS:" << ((arg & TIOCM_RTS)?1:0)
<< " DCD:" << ((arg & TIOCM_CAR)?1:0)
<< " DSR:" << ((arg & TIOCM_DSR)?1:0)
<< " CTS:" << ((arg & TIOCM_CTS)?1:0) << endl;
+#ifdef sun
+ if ((arg & TIOCM_CTS) == 0)
+#else
if (((arg & TIOCM_DSR) == 0) || ((arg & TIOCM_CTS) == 0))
+#endif
failed = true;
if ((verbose & PKT_DEBUG_LOG) && failed)
cout << "packet: linkFAILED\n";
diff --git a/ncpd/packet.h b/ncpd/packet.h
index 77ca4e9..26d4282 100644
--- a/ncpd/packet.h
+++ b/ncpd/packet.h
@@ -34,6 +34,7 @@ class IOWatch;
#define PKT_DEBUG_LOG 1
#define PKT_DEBUG_DUMP 2
+#define PKT_DEBUG_HANDSHAKE 4
class packet {
public:
@@ -63,7 +64,7 @@ class packet {
int outLen;
int termLen;
int fd;
- bool verbose;
+ short int verbose;
bool esc;
char *devname;
int baud;
diff --git a/ncpd/socketchan.cc b/ncpd/socketchan.cc
index d78d3b6..a7d612e 100644
--- a/ncpd/socketchan.cc
+++ b/ncpd/socketchan.cc
@@ -39,6 +39,7 @@ iow(_iow)
{
skt = _skt;
connectName = 0;
+ connectTry = 0;
iow.addIO(skt->socket());
connected = false;
}
@@ -61,12 +62,63 @@ ncpDataCallback(bufferStore & a)
cerr << "socketchan: Connect without name!!!\n";
}
-const char *socketChan::
+char *socketChan::
getNcpConnectName()
{
return connectName;
}
+// NCP Command processing
+bool socketChan::
+ncpCommand(bufferStore & a)
+{
+cerr << "socketChan:: received NCP command (" << a << ")" << endl;
+ // str is guaranteed to begin with NCP$, and all NCP commands are
+ // greater than or equal to 8 characters in length.
+ const char *str = a.getString();
+ // unsigned long len = a.getLen();
+ bool ok = false;
+
+ if (!strncmp(str+4, "INFO", 4)) {
+ // Send information discovered during the receipt of the
+ // NCON_MSG_NCP_INFO message.
+ a.init();
+ switch (ncpProtocolVersion()) {
+ case PV_SERIES_3:
+ a.addStringT("Series 3");
+ break;
+ case PV_SERIES_5:
+ a.addStringT("Series 5");
+ break;
+ default:
+ cerr << "ncpd: protocol version not known" << endl;
+ a.addStringT("Unknown!");
+ break;
+ }
+ skt->sendBufferStore(a);
+ ok = true;
+ } else if (!strncmp(str+4, "CONN", 4)) {
+ // Connect to a channel that was placed in 'pending' mode, by
+ // checking the channel table against the ID...
+ // DO ME LATER
+ ok = true;
+ } else if (!strncmp(str+4, "CHAL", 4)) {
+ // Challenge
+ // The idea is that the channel stays in 'secure' mode until a
+ // valid RESP is received
+ // DO ME LATER
+ ok = true;
+ } else if (!strncmp(str+4, "RESP", 4)) {
+ // Reponse - here is the plaintext as sent in the CHAL - the
+ // channel will only open up if this matches what ncpd has for
+ // the encrypted plaintext.
+ // DO ME LATER
+ ok = true;
+ }
+ return ok;
+}
+
+
void socketChan::
ncpConnectAck()
{
@@ -74,24 +126,77 @@ ncpConnectAck()
a.addStringT("Ok");
skt->sendBufferStore(a);
connected = true;
+ connectTry = 3;
}
void socketChan::
ncpConnectTerminate()
{
bufferStore a;
+ connectTry = 0;
a.addStringT("Close");
skt->sendBufferStore(a);
terminateWhenAsked();
}
void socketChan::
+ncpRegisterAck()
+{
+ connectTry++;
+ ncpConnect();
+}
+
+void socketChan::
+ncpConnectNak()
+{
+ if (!connectName || (connectTry > 1))
+ ncpConnectTerminate();
+ else {
+ connectTry++;
+ ncpRegister();
+ }
+}
+
+void socketChan::
socketPoll()
{
if (connectName == 0) {
bufferStore a;
if (skt->getBufferStore(a, false) == 1) {
+ // A client has connected, and is announcing who it
+ // is... e.g. "SYS$RFSV.*"
+ //
+ // An NCP Channel can be in 'Control' or 'Data' mode.
+ // Initially, it is in 'Control' mode, and can accept
+ // certain commands.
+ //
+ // When a command is received that ncpd does not
+ // understand, this is assumed to be a request to
+ // connect to the remote service of that name, and enter
+ // 'data' mode.
+ //
+ // Later, there might be an explicit command to enter
+ // 'data' mode, and also a challenge-response protocol
+ // before any connection can be made.
+ //
+ // All commands begin with "NCP$".
+
+ // There is a magic process name called "NCP$INFO.*"
+ // which is announced by the rfsvfactory. This causes a
+ // response to be issued containing the NCP version
+ // number. The rfsvfactory will create the correct type
+ // of RFSV protocol handler, which will then announce
+ // itself. So, first time in here, we might get the
+ // NCP$INFO.*
+ if (a.getLen() > 8 && !strncmp(a.getString(), "NCP$", 4)) {
+ if (!ncpCommand(a))
+ cerr << "ncpd: command " << a << " unrecognised." << endl;
+ return;
+ }
+
+ // This isn't a command, it's a remote process. Connect.
connectName = strdup(a.getString());
+ connectTry++;
ncpConnect();
}
} else if (connected) {
diff --git a/ncpd/socketchan.h b/ncpd/socketchan.h
index e352b36..5fe7a13 100644
--- a/ncpd/socketchan.h
+++ b/ncpd/socketchan.h
@@ -36,17 +36,23 @@ public:
virtual ~socketChan();
void ncpDataCallback(bufferStore& a);
- const char* getNcpConnectName();
+ char* getNcpConnectName();
void ncpConnectAck();
+ void ncpRegisterAck();
+ void ncpDoRegisterAck(int) {}
void ncpConnectTerminate();
+ void ncpConnectNak();
bool isConnected() const;
void socketPoll();
private:
+ enum protocolVersionType { PV_SERIES_5 = 6, PV_SERIES_3 = 3 };
+ bool ncpCommand(bufferStore &a);
ppsocket* skt;
IOWatch &iow;
char* connectName;
bool connected;
+ int connectTry;
};
#endif