aboutsummaryrefslogtreecommitdiffstats
path: root/ncpd
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2002-03-16 23:10:52 +0000
committerFritz Elfert <felfert@to.com>2002-03-16 23:10:52 +0000
commit193af441a127a0daabbd17c512e34817ddbcadfd (patch)
treedeef4cbfdf258ae3c7d8cde2b43a611520f73632 /ncpd
parent7121719ec7f473c3d26873d688179a7d7f466026 (diff)
downloadplptools-193af441a127a0daabbd17c512e34817ddbcadfd.tar.gz
plptools-193af441a127a0daabbd17c512e34817ddbcadfd.tar.bz2
plptools-193af441a127a0daabbd17c512e34817ddbcadfd.zip
- ncpd now works with both Series 3 and Series 5
- ncpd now has autobaud feature (default on), which cycles baudrate - lib: added getSpeed() for retrieving current speed of connection - plpftp: Use getSpeed() - plpbackup: Ongoing work - configure stuff: removed several entries from acconfig.h comments now defined as 3rd arg to AC_DEFINE...
Diffstat (limited to 'ncpd')
-rw-r--r--ncpd/channel.cc24
-rw-r--r--ncpd/channel.h7
-rw-r--r--ncpd/link.cc183
-rw-r--r--ncpd/link.h29
-rw-r--r--ncpd/main.cc5
-rw-r--r--ncpd/mp_serial.c5
-rw-r--r--ncpd/ncp.cc126
-rw-r--r--ncpd/ncp.h25
-rw-r--r--ncpd/packet.cc87
-rw-r--r--ncpd/packet.h6
-rw-r--r--ncpd/socketchan.cc44
11 files changed, 456 insertions, 85 deletions
diff --git a/ncpd/channel.cc b/ncpd/channel.cc
index e51b903..d3189e4 100644
--- a/ncpd/channel.cc
+++ b/ncpd/channel.cc
@@ -87,6 +87,30 @@ ncpDisconnect()
ncpController->disconnect(ncpChannel);
}
+PcServer *channel::
+ncpFindPcServer(const char *name)
+{
+ return ncpController->findPcServer(name);
+}
+
+void channel::
+ncpRegisterPcServer(ppsocket *skt, const char *name)
+{
+ ncpController->registerPcServer(skt, name);
+}
+
+void channel::
+ncpUnregisterPcServer(PcServer *server)
+{
+ ncpController->unregisterPcServer(server);
+}
+
+int channel::
+ncpGetSpeed()
+{
+ return ncpController->getSpeed();
+}
+
short int channel::
ncpProtocolVersion()
{
diff --git a/ncpd/channel.h b/ncpd/channel.h
index 585ef31..e9bf3ea 100644
--- a/ncpd/channel.h
+++ b/ncpd/channel.h
@@ -31,6 +31,8 @@
class ncp;
class bufferStore;
+class PcServer;
+class ppsocket;
class channel {
public:
@@ -61,6 +63,11 @@ public:
virtual bool terminate(); // Mainloop will terminate this class if true
void terminateWhenAsked();
+ PcServer *ncpFindPcServer(const char *name);
+ void ncpRegisterPcServer(ppsocket *skt, const char *name);
+ void ncpUnregisterPcServer(PcServer *server);
+ int ncpGetSpeed();
+
protected:
short int verbose;
const char *connectName;
diff --git a/ncpd/link.cc b/ncpd/link.cc
index a52e3ef..025e131 100644
--- a/ncpd/link.cc
+++ b/ncpd/link.cc
@@ -44,16 +44,21 @@ extern "C" {
Link *l = (Link *)arg;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
while (1) {
- usleep(l->retransTimeout * 500);
+ usleep(l->retransTimeout() * 500);
l->retransmit();
}
}
};
+ENUM_DEFINITION(Link::link_type, Link::LINK_TYPE_UNKNOWN) {
+ stringRep.add(Link::LINK_TYPE_UNKNOWN, N_("Unknown"));
+ stringRep.add(Link::LINK_TYPE_SIBO, N_("SIBO"));
+ stringRep.add(Link::LINK_TYPE_EPOC, N_("EPOC"));
+}
+
Link::Link(const char *fname, int baud, ncp *_ncp, unsigned short _verbose)
+ : p(0)
{
- p = new packet(fname, baud, this, _verbose);
- retransTimeout = ((unsigned long)baud * 1000 / 13200) + 200;
theNCP = _ncp;
verbose = _verbose;
txSequence = 1;
@@ -61,18 +66,20 @@ Link::Link(const char *fname, int baud, ncp *_ncp, unsigned short _verbose)
failed = false;
seqMask = 7;
maxOutstanding = 1;
+ linkType = LINK_TYPE_UNKNOWN;
for (int i = 0; i < 256; i++)
xoff[i] = false;
- // generate magic number for sendCon()
+ // generate magic number for sendReqCon()
srandom(time(NULL));
conMagic = random();
+ p = new packet(fname, baud, this, _verbose);
+
pthread_mutex_init(&queueMutex, NULL);
pthread_create(&checkthread, NULL, expire_check, this);
// submit a link request
- bufferStore blank;
- transmit(blank);
+ sendReqReq();
}
Link::~Link()
@@ -83,22 +90,27 @@ Link::~Link()
delete p;
}
+unsigned long Link::
+retransTimeout()
+{
+ return ((unsigned long)getSpeed() * 1000 / 13200) + 200;
+}
+
void Link::
reset() {
+ p->reset();
txSequence = 1;
rxSequence = -1;
failed = false;
-
- pthread_mutex_lock(&queueMutex);
- ackWaitQueue.clear();
- holdQueue.clear();
- pthread_mutex_unlock(&queueMutex);
+ seqMask = 7;
+ maxOutstanding = 1;
+ linkType = LINK_TYPE_UNKNOWN;
+ purgeAllQueues();
for (int i = 0; i < 256; i++)
xoff[i] = false;
// submit a link request
- bufferStore blank;
- transmit(blank);
+ sendReqReq();
}
unsigned short Link::
@@ -124,6 +136,15 @@ send(const bufferStore & buff)
}
void Link::
+purgeAllQueues()
+{
+ pthread_mutex_lock(&queueMutex);
+ ackWaitQueue.clear();
+ holdQueue.clear();
+ pthread_mutex_unlock(&queueMutex);
+}
+
+void Link::
purgeQueue(int channel)
{
pthread_mutex_lock(&queueMutex);
@@ -161,7 +182,7 @@ sendAck(int seq)
}
void Link::
-sendCon()
+sendReqCon()
{
if (hasFailed())
return;
@@ -182,8 +203,44 @@ sendCon()
}
void Link::
+sendReqReq()
+{
+ if (hasFailed())
+ return;
+ bufferStore tmp;
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: >> con seq=1" << endl;
+ tmp.addByte(0x21);
+ ackWaitQueueElement e;
+ e.seq = 0; // expected response is Ack with seq=0 or ReqCon
+ gettimeofday(&e.stamp, NULL);
+ e.data = tmp;
+ e.txcount = 4;
+ pthread_mutex_lock(&queueMutex);
+ ackWaitQueue.push_back(e);
+ pthread_mutex_unlock(&queueMutex);
+ p->send(tmp);
+}
+
+void Link::
+sendReq()
+{
+ if (hasFailed())
+ return;
+ bufferStore tmp;
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: >> con seq=1" << endl;
+ tmp.addByte(0x20);
+ // No Ack expected for this, so no new entry in ackWaitQueue
+ p->send(tmp);
+}
+
+void Link::
receive(bufferStore buff)
{
+ if (!p)
+ return;
+
vector<ackWaitQueueElement>::iterator i;
bool ackFound;
bool conFound;
@@ -267,17 +324,58 @@ receive(bufferStore buff)
}
pthread_mutex_unlock(&queueMutex);
if (ackFound) {
+ if ((linkType == LINK_TYPE_UNKNOWN) && (seq == 0)) {
+ // If the remote device runs SIBO protocol, this ACK
+ // should be 0 (the Ack on our ReqReq request, which is
+ // treated as a normal Req by the SIBO machine.
+ failed = false;
+ linkType = LINK_TYPE_SIBO;
+ seqMask = 7;
+ maxOutstanding = 1;
+ rxSequence = 0;
+ txSequence = 1;
+ purgeAllQueues();
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: 1-linkType set to " << linkType << endl;
+ }
// Older packets implicitely ack'ed
multiAck(refstamp);
// Transmit waiting packets
transmitWaitQueue();
} else {
if (verbose & LNK_DEBUG_LOG) {
- cout << "Link: << UNMATCHED ack seq=" << seq ;
+ cout << "Link: << UNMATCHED ack seq=" << seq;
if (verbose & LNK_DEBUG_DUMP)
cout << " " << buff;
cout << endl;
}
+ // If packet with seq+1 is in ackWaitQueue, resend it immediately
+ // (Receiving an ack for a packet not on our wait queue is a
+ // hint by the Psion about which was the last packet it
+ // received successfully.)
+ pthread_mutex_lock(&queueMutex);
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ for (i = ackWaitQueue.begin(); i != ackWaitQueue.end(); i++)
+ if (i->seq == seq+1) {
+ if (i->txcount-- == 0) {
+ // timeout, remove packet
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: >> TRANSMIT timeout seq=" <<
+ i->seq << endl;
+ ackWaitQueue.erase(i);
+ i--;
+ } else {
+ // retransmit it
+ i->stamp = now;
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: >> RETRANSMIT seq=" << i->seq
+ << endl;
+ p->send(i->data);
+ }
+ break;
+ }
+ pthread_mutex_unlock(&queueMutex);
}
break;
@@ -288,10 +386,13 @@ receive(bufferStore buff)
// May be a link confirm packet (EPOC)
pthread_mutex_lock(&queueMutex);
for (i = ackWaitQueue.begin(); i != ackWaitQueue.end(); i++)
- if ((i->seq > 0) && (i->seq < 4) &&
- (i->data.getByte(0) & 0xf0) == 0x20) {
+ if ((i->seq == 0) && (i->data.getByte(0) & 0xf0) == 0x20) {
ackWaitQueue.erase(i);
+ linkType = LINK_TYPE_EPOC;
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: 2-linkType set to " << linkType << endl;
conFound = true;
+ failed = false;
// EPOC can handle extended sequence numbers
seqMask = 0x7ff;
// EPOC can handle up to 8 unacknowledged packets
@@ -310,6 +411,7 @@ receive(bufferStore buff)
if (conFound) {
rxSequence = 0;
txSequence = 1;
+ purgeAllQueues();
sendAck(rxSequence);
} else {
if (verbose & LNK_DEBUG_LOG) {
@@ -320,14 +422,30 @@ receive(bufferStore buff)
}
rxSequence = txSequence = 0;
if (seq > 0) {
+ linkType = LINK_TYPE_EPOC;
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: 3-linkType set to " << linkType << endl;
// EPOC can handle extended sequence numbers
seqMask = 0x7ff;
// EPOC can handle up to 8 unacknowledged packets
maxOutstanding = 8;
p->setEpoc(true);
- sendCon();
- } else
+ purgeAllQueues();
+ failed = false;
+ sendReqCon();
+ } else {
+ // SIBO
+ linkType = LINK_TYPE_SIBO;
+ failed = false;
+ seqMask = 7;
+ maxOutstanding = 1;
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: 4-linkType set to " << linkType << endl;
+ rxSequence = 0;
+ txSequence = 1; // Our ReqReq was seq 0
+ purgeAllQueues();
sendAck(rxSequence);
+ }
}
break;
@@ -481,10 +599,7 @@ retransmit()
{
if (hasFailed()) {
- pthread_mutex_lock(&queueMutex);
- ackWaitQueue.clear();
- holdQueue.clear();
- pthread_mutex_unlock(&queueMutex);
+ purgeAllQueues();
return;
}
@@ -493,7 +608,7 @@ retransmit()
struct timeval now;
gettimeofday(&now, NULL);
struct timeval expired = now;
- timesub(&expired, retransTimeout);
+ timesub(&expired, retransTimeout());
for (i = ackWaitQueue.begin(); i != ackWaitQueue.end(); i++)
if (olderthan(i->stamp, expired)) {
if (i->txcount-- == 0) {
@@ -501,6 +616,7 @@ retransmit()
if (verbose & LNK_DEBUG_LOG)
cout << "Link: >> TRANSMIT timeout seq=" << i->seq << endl;
ackWaitQueue.erase(i);
+ failed = true;
i--;
} else {
// retransmit it
@@ -528,10 +644,27 @@ stuffToSend()
bool Link::
hasFailed()
{
- failed |= p->linkFailed();
+ bool lfailed = p->linkFailed();
+ if (failed || lfailed) {
+ if (verbose & LNK_DEBUG_LOG)
+ cout << "Link: hasFailed: " << failed << ", " << lfailed << endl;
+ }
+ failed |= lfailed;
return failed;
}
+Enum<Link::link_type> Link::
+getLinkType()
+{
+ return linkType;
+}
+
+int Link::
+getSpeed()
+{
+ return p->getSpeed();
+}
+
/*
* Local variables:
* c-basic-offset: 4
diff --git a/ncpd/link.h b/ncpd/link.h
index 81732b6..25cd280 100644
--- a/ncpd/link.h
+++ b/ncpd/link.h
@@ -32,6 +32,7 @@
#include "bufferstore.h"
#include "bufferarray.h"
+#include "Enum.h"
#include <vector>
#define LNK_DEBUG_LOG 4
@@ -70,6 +71,12 @@ extern "C" {
class Link {
public:
+ enum link_type {
+ LINK_TYPE_UNKNOWN = 0,
+ LINK_TYPE_SIBO = 1,
+ LINK_TYPE_EPOC = 2,
+ };
+
/**
* Construct a new link instance.
*
@@ -141,6 +148,20 @@ public:
*/
unsigned short getVerbose();
+ /**
+ * Get the current link type.
+ *
+ * @returns One of LINK_TYPE_... values.
+ */
+ Enum<link_type> getLinkType();
+
+ /**
+ * Get current speed of the serial device
+ *
+ * @returns The current speed in baud.
+ */
+ int getSpeed();
+
private:
friend class packet;
friend void * expire_check(void *);
@@ -148,11 +169,15 @@ private:
void receive(bufferStore buf);
void transmit(bufferStore buf);
void sendAck(int seq);
- void sendCon();
+ void sendReqReq();
+ void sendReqCon();
+ void sendReq();
void multiAck(struct timeval);
void retransmit();
void transmitHoldQueue(int channel);
void transmitWaitQueue();
+ void purgeAllQueues();
+ unsigned long retransTimeout();
pthread_t checkthread;
pthread_mutex_t queueMutex;
@@ -163,10 +188,10 @@ private:
int rxSequence;
int seqMask;
int maxOutstanding;
- unsigned long retransTimeout;
unsigned long conMagic;
unsigned short verbose;
bool failed;
+ Enum<link_type> linkType;
vector<ackWaitQueueElement> ackWaitQueue;
vector<bufferStore> holdQueue;
diff --git a/ncpd/main.cc b/ncpd/main.cc
index f1f7f14..4771744 100644
--- a/ncpd/main.cc
+++ b/ncpd/main.cc
@@ -288,7 +288,10 @@ main(int argc, char **argv)
autoexit = true;
break;
case 'b':
- baudRate = atoi(optarg);
+ if (!strcmp(optarg, "auto"))
+ baudRate = -1;
+ else
+ baudRate = atoi(optarg);
break;
case 's':
serialDevice = optarg;
diff --git a/ncpd/mp_serial.c b/ncpd/mp_serial.c
index 7f6a792..7483a3e 100644
--- a/ncpd/mp_serial.c
+++ b/ncpd/mp_serial.c
@@ -131,7 +131,7 @@ init_serial(const char *dev, int speed, int debug)
perror("seteuid");
exit(1);
}
- if ((fd = open(dev, O_RDWR /*FRITZTEST | O_NDELAY */ | O_NOCTTY, 0)) < 0) {
+ if ((fd = open(dev, O_RDWR | O_NOCTTY, 0)) < 0) {
perror(dev);
exit(1);
}
@@ -184,6 +184,9 @@ ser_exit(int fd)
{
struct termios ti;
+#ifdef TIOCNXCL
+ ioctl(fd, TIOCNXCL, (char *) 0);
+#endif
if (tcgetattr(fd, &ti) < 0)
perror("tcgetattr");
ti.c_cflag &= ~CRTSCTS;
diff --git a/ncpd/ncp.cc b/ncpd/ncp.cc
index 76f4d63..f20ca75 100644
--- a/ncpd/ncp.cc
+++ b/ncpd/ncp.cc
@@ -31,9 +31,10 @@
#include "ncp.h"
#include "linkchan.h"
-#include <bufferstore.h>
#include "link.h"
+#include <bufferstore.h>
#include <bufferarray.h>
+#include <rfsv.h>
#define MAX_CHANNELS_PSION 256
#define MAX_CHANNELS_SIBO 8
@@ -54,6 +55,7 @@ ncp::ncp(const char *fname, int baud, unsigned short _verbose)
// until detected on receipt of INFO we use these.
maxChannels = MAX_CHANNELS_SIBO;
protocolVersion = PV_SERIES_5;
+ lChan = NULL;
// init channels
for (int i = 0; i < MAX_CHANNELS_PSION; i++)
@@ -94,6 +96,8 @@ reset() {
channelPtr[i] = NULL;
}
failed = false;
+ if (lChan)
+ delete(lChan);
lChan = NULL;
protocolVersion = PV_SERIES_5; // until detected on receipt of INFO
l->reset();
@@ -158,6 +162,35 @@ controlChannel(int chan, enum interControllerMessageType t, bufferStore & comman
l->send(open);
}
+PcServer *ncp::
+findPcServer(const char *name)
+{
+ if (name) {
+ vector<PcServer>::iterator i;
+ for (i = pcServers.begin(); i != pcServers.end(); i++)
+ if (i->getName() == name)
+ return i;
+ }
+ return NULL;
+}
+
+void ncp::
+registerPcServer(ppsocket *skt, const char *name) {
+ pcServers.push_back(PcServer(skt, name));
+}
+
+void ncp::
+unregisterPcServer(PcServer *server) {
+ if (server) {
+ vector<PcServer>::iterator i;
+ for (i = pcServers.begin(); i != pcServers.end(); i++)
+ if (i == server) {
+ pcServers.erase(i);
+ return;
+ }
+ }
+}
+
void ncp::
decodeControlMessage(bufferStore & buff)
{
@@ -169,6 +202,7 @@ decodeControlMessage(bufferStore & buff)
cout << "ncp: << " << ctrlMsgName(imt) << " " << remoteChan;
bufferStore b;
+ int localChan;
switch (imt) {
case NCON_MSG_CONNECT_TO_SERVER:
@@ -178,33 +212,51 @@ decodeControlMessage(bufferStore & buff)
cout << endl;
}
- int localChan;
-
- // Ack with connect response
- localChan = getFirstUnusedChan();
- b.addByte(remoteChan);
- b.addByte(0);
- 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...
-
+ failed = false;
if (!strcmp(buff.getString(0), "LINK.*")) {
if (lChan)
- failed = true;
+ localChan = lChan->getNcpChannel();
+ else
+ localChan = getFirstUnusedChan();
+
+ // Ack with connect response
+ b.addByte(remoteChan);
+ b.addByte(0);
+ controlChannel(localChan, NCON_MSG_CONNECT_RESPONSE, b);
if (verbose & NCP_DEBUG_LOG)
cout << "ncp: Link UP" << endl;
- channelPtr[localChan] = lChan = new linkChan(this, localChan);
- lChan->setVerbose(verbose);
+ // Create linkchan if it does not yet exist
+ if (!lChan) {
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: new passive linkChan" << endl;
+ channelPtr[localChan] =
+ lChan = new linkChan(this, localChan);
+ lChan->setVerbose(verbose);
+ }
lChan->ncpConnectAck();
} else {
- if (verbose & NCP_DEBUG_LOG)
- cout << "ncp: REJECT connect" << endl;
- bufferStore b;
+ PcServer *s = findPcServer(buff.getString(0));
+ bool ok = false;
+
+ if (s) {
+ localChan = getFirstUnusedChan();
+ ok = s->clientConnect(localChan, remoteChan);
+ if (!ok)
+ // release channel ptr
+ channelPtr[localChan] = NULL;
+ }
b.addByte(remoteChan);
- controlChannel(0, NCON_MSG_CHANNEL_DISCONNECT, b);
+ if (ok) {
+ b.addByte(rfsv::E_PSI_GEN_NONE);
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: ACCEPT client connect" << endl;
+ } else {
+ localChan = 0;
+ b.addByte(rfsv::E_PSI_FILE_NXIST);
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: REJECT client connect" << endl;
+ }
+ controlChannel(localChan, NCON_MSG_CONNECT_RESPONSE, b);
}
break;
@@ -212,6 +264,7 @@ decodeControlMessage(bufferStore & buff)
int forChan;
+ failed = false;
forChan = buff.getByte(0);
if (verbose & NCP_DEBUG_LOG)
cout << " ch=" << forChan << " stat=";
@@ -237,6 +290,7 @@ decodeControlMessage(bufferStore & buff)
int ver;
+ failed = false;
ver = buff.getByte(0);
// Series 3c returns '3', as does mclink. PsiWin 1.1
// returns version 2. We return whatever version we're
@@ -263,11 +317,12 @@ decodeControlMessage(bufferStore & buff)
// 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
+ } else {
cout << "ALERT!!!! Unexpected Protocol Version!! (No Series 5/3?)!" << endl;
+ failed = true;
+ }
break;
case NCON_MSG_CHANNEL_DISCONNECT:
@@ -318,7 +373,7 @@ RegisterAck(int chan, const char *name)
cout << "ncp: RegisterAck: chan=" << chan << endl;
for (int cNum = 1; cNum < maxLinks(); cNum++) {
channel *ch = channelPtr[cNum];
- if (ch && ch->getNcpChannel() == chan) {
+ if (isValidChannel(cNum) && ch->getNcpChannel() == chan) {
ch->setNcpConnectName(name);
ch->ncpRegisterAck();
return;
@@ -420,9 +475,20 @@ stuffToSend()
bool ncp::
hasFailed()
{
- if (failed)
- return true;
- return l->hasFailed();
+ bool lfailed = l->hasFailed();
+ if (failed || lfailed) {
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: hasFailed: " << failed << ", " << lfailed << endl;
+ }
+ failed |= lfailed;
+ if (failed) {
+ if (lChan) {
+ channelPtr[lChan->getNcpChannel()] = NULL;
+ delete lChan;
+ }
+ lChan = NULL;
+ }
+ return failed;
}
bool ncp::
@@ -431,6 +497,12 @@ gotLinkChannel()
return (lChan != NULL);
}
+int ncp::
+getSpeed()
+{
+ return l->getSpeed();
+}
+
char *ncp::
ctrlMsgName(unsigned char msgType)
{
diff --git a/ncpd/ncp.h b/ncpd/ncp.h
index 72c5ca8..5a6a1ba 100644
--- a/ncpd/ncp.h
+++ b/ncpd/ncp.h
@@ -27,14 +27,33 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#include <vector>
+
#include "bufferstore.h"
#include "linkchan.h"
+#include "ppsocket.h"
+
class Link;
class channel;
#define NCP_DEBUG_LOG 1
#define NCP_DEBUG_DUMP 2
+/**
+ * Representation of a server process on the PC
+ * A dummy which does not allow connects for now.
+ */
+class PcServer {
+public:
+ PcServer(ppsocket *, string _name) { name = _name; }
+ ~PcServer() {}
+ bool clientConnect(int, int) { return false; }
+ string getName() { return name; }
+private:
+ string name;
+};
+
class ncp {
public:
ncp(const char *fname, int baud, unsigned short _verbose = 0);
@@ -51,9 +70,14 @@ public:
bool hasFailed();
bool gotLinkChannel();
+ PcServer *findPcServer(const char *name);
+ void registerPcServer(ppsocket *skt, const char *name);
+ void unregisterPcServer(PcServer *server);
+
void setVerbose(unsigned short);
unsigned short getVerbose();
short int getProtocolVersion();
+ int getSpeed();
private:
friend class Link;
@@ -87,6 +111,7 @@ private:
short int protocolVersion;
linkChan *lChan;
int maxChannels;
+ vector<PcServer> pcServers;
};
#endif
diff --git a/ncpd/packet.cc b/ncpd/packet.cc
index 84f0f66..1d3183b 100644
--- a/ncpd/packet.cc
+++ b/ncpd/packet.cc
@@ -138,10 +138,17 @@ static void *pump_run(void *arg)
}
}
-//static pthread_mutex_t outMutex;
-//static pthread_mutex_t inMutex;
};
+static const int baud_table[] = {
+ 115200,
+ 57600,
+ 38400,
+ 19200,
+ // Lower rates don't make sense ?!
+};
+#define BAUD_TABLE_SIZE (sizeof(baud_table) / sizeof(int))
+
packet::
packet(const char *fname, int _baud, Link *_link, unsigned short _verbose)
{
@@ -151,6 +158,7 @@ packet(const char *fname, int _baud, Link *_link, unsigned short _verbose)
baud = _baud;
theLINK = _link;
isEPOC = false;
+ justStarted = true;
// Initialize CRC table
crc_table[0] = 0;
@@ -174,12 +182,15 @@ packet(const char *fname, int _baud, Link *_link, unsigned short _verbose)
crcIn = crcOut = 0;
thisThread = pthread_self();
- fd = init_serial(devname, baud, 0);
+ realBaud = baud;
+ if (baud < 0) {
+ baud_index = 1;
+ realBaud = baud_table[0];
+ }
+ fd = init_serial(devname, realBaud, 0);
if (fd == -1)
lastFatal = true;
else {
-// pthread_mutex_init(&inMutex, NULL);
-// pthread_mutex_init(&outMutex, NULL);
signal(SIGUSR1, usr1handler);
pthread_create(&datapump, NULL, pump_run, this);
}
@@ -201,30 +212,46 @@ packet::
void packet::
reset()
{
+ if (fd != -1)
+ pthread_cancel(datapump);
+ outRead = outWrite = 0;
+ internalReset();
+ if (fd != -1)
+ pthread_create(&datapump, NULL, pump_run, this);
+}
+
+void packet::
+internalReset()
+{
if (verbose & PKT_DEBUG_LOG)
cout << "resetting serial connection" << endl;
if (fd != -1) {
- pthread_cancel(datapump);
ser_exit(fd);
fd = -1;
}
- usleep(100000);
- inRead = inWrite = outRead = outWrite = 0;
+ usleep(1000000);
+ inRead = inWrite = 0;
esc = false;
lastFatal = false;
serialStatus = -1;
lastSYN = startPkt = -1;
crcIn = crcOut = 0;
- fd = init_serial(devname, baud, 0);
- if (fd != -1)
- lastFatal = false;
- else {
-// pthread_mutex_init(&inMutex, NULL);
-// pthread_mutex_init(&outMutex, NULL);
- pthread_create(&datapump, NULL, pump_run, this);
+ realBaud = baud;
+ justStarted = true;
+ if (baud < 0) {
+ realBaud = baud_table[baud_index++];
+ if (baud_index >= BAUD_TABLE_SIZE)
+ baud_index = 0;
}
+
+ fd = init_serial(devname, realBaud, 0);
if (verbose & PKT_DEBUG_LOG)
- cout << "serial connection reset, fd=" << fd << endl;
+ cout << "serial connection set to " << dec << realBaud
+ << " baud, fd=" << fd << endl;
+ if (fd != -1) {
+ lastFatal = false;
+ realWrite();
+ }
}
short int packet::
@@ -245,6 +272,12 @@ setEpoc(bool _epoc)
isEPOC = _epoc;
}
+int packet::
+getSpeed()
+{
+ return realBaud;
+}
+
void packet::
send(bufferStore &b)
{
@@ -350,6 +383,7 @@ findSync()
}
}
if (startPkt >= 0) {
+ justStarted = false;
while (p != inw) {
unsigned char c = inBuffer[p];
switch (inCRCstate) {
@@ -393,7 +427,6 @@ findSync()
if (verbose & PKT_DEBUG_LOG)
cout << "packet: BAD CRC" << endl;
} else {
- // inQueue += rcv;
if (verbose & PKT_DEBUG_LOG) {
cout << "packet: << ";
if (verbose & PKT_DEBUG_DUMP)
@@ -412,6 +445,18 @@ findSync()
inc1(p);
}
lastSYN = p;
+ } else {
+ // If we get here, no sync was found.
+ // If we are just started and the amount of received data exceeds
+ // 15 bytes, the baudrate is obviously wrong.
+ // (or the connected device is not an EPOC device). Reset the
+ // serial connection and try next baudrate, if auto-baud is set.
+ if (justStarted) {
+ int rx_amount = (inw > inRead) ?
+ inw - inRead : BUFLEN - inRead + inw;
+ if (rx_amount > 15)
+ internalReset();
+ }
}
}
@@ -422,8 +467,8 @@ linkFailed()
int res;
bool failed = false;
- if (lastFatal)
- reset();
+ if (fd == -1)
+ return false;
res = ioctl(fd, TIOCMGET, &arg);
if (res < 0)
lastFatal = true;
@@ -453,10 +498,8 @@ linkFailed()
|| ((arg & TIOCM_DSR) == 0)
#endif
) {
- // eat possible junk on line
- //while (read(fd, &res, sizeof(res)) > 0)
- // ;
failed = true;
+ justStarted = true;
}
if ((verbose & PKT_DEBUG_LOG) && lastFatal)
cout << "packet: linkFATAL\n";
diff --git a/ncpd/packet.h b/ncpd/packet.h
index aa0b90c..dcf01cc 100644
--- a/ncpd/packet.h
+++ b/ncpd/packet.h
@@ -57,6 +57,7 @@ public:
void setEpoc(bool);
void setVerbose(short int);
short int getVerbose();
+ int getSpeed();
bool linkFailed();
void reset();
@@ -71,6 +72,7 @@ private:
void opByte(unsigned char a);
void opCByte(unsigned char a, unsigned short *crc);
void realWrite();
+ void internalReset();
Link *theLINK;
pthread_t datapump;
@@ -98,10 +100,14 @@ private:
int foundSync;
int fd;
int serialStatus;
+ int baud_index;
+ int realBaud;
short int verbose;
bool esc;
bool lastFatal;
bool isEPOC;
+ bool justStarted;
+
char *devname;
int baud;
};
diff --git a/ncpd/socketchan.cc b/ncpd/socketchan.cc
index 83d0695..fe2b683 100644
--- a/ncpd/socketchan.cc
+++ b/ncpd/socketchan.cc
@@ -32,6 +32,7 @@
#include "socketchan.h"
#include "ncp.h"
#include <ppsocket.h>
+#include <rfsv.h>
socketChan:: socketChan(ppsocket * _skt, ncp * _ncpController):
channel(_ncpController)
@@ -72,11 +73,10 @@ ncpCommand(bufferStore & a)
{
// 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();
+ const char *str = a.getString(4);
bool ok = false;
- if (!strncmp(str+4, "INFO", 4)) {
+ if (!strncmp(str, "INFO", 4)) {
// Send information discovered during the receipt of the
// NCON_MSG_NCP_INFO message.
a.init();
@@ -94,26 +94,50 @@ ncpCommand(bufferStore & a)
}
skt->sendBufferStore(a);
ok = true;
- } else if (!strncmp(str+4, "CONN", 4)) {
+ } else if (!strncmp(str, "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)) {
+ } else if (!strncmp(str, "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)) {
+ } else if (!strncmp(str, "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;
+ } else if (!strncmp(str, "GSPD", 4)) {
+ // Get Speed of serial device
+ cerr << "socketChan:: GETSPEED" << endl;
+ a.init();
+ a.addByte(rfsv::E_PSI_GEN_NONE);
+ a.addDWord(ncpGetSpeed());
+ skt->sendBufferStore(a);
+ ok = true;
+ } else if (!strncmp(str, "REGS", 4)) {
+ // Register a server-process on the PC side.
+ a.init();
+ const char *name = a.getString(8);
+ if (ncpFindPcServer(name))
+ a.addByte(rfsv::E_PSI_FILE_EXIST);
+ else {
+ ncpRegisterPcServer(skt, name);
+ a.addByte(rfsv::E_PSI_GEN_NONE);
+ }
+ skt->sendBufferStore(a);
+ ok = true;
}
- if (!ok)
+ if (!ok) {
cerr << "socketChan:: received unknown NCP command (" << a << ")" << endl;
+ a.init();
+ a.addByte(rfsv::E_PSI_GEN_NSUP);
+ skt->sendBufferStore(a);
+ }
return ok;
}
@@ -223,6 +247,12 @@ socketPoll()
ncpDisconnect();
skt->closeSocket();
} else if (res == 1) {
+ if (a.getLen() > 8 && !strncmp(a.getString(), "NCP$", 4)) {
+ if (!ncpCommand(a))
+ cerr << "ncpd: command " << a << " unrecognized."
+ << endl;
+ return;
+ }
ncpSend(a);
}
} else if (time(0) > (tryStamp + 15))