aboutsummaryrefslogtreecommitdiffstats
path: root/ncpd/socketchan.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ncpd/socketchan.cc')
-rw-r--r--ncpd/socketchan.cc107
1 files changed, 106 insertions, 1 deletions
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) {