From 193af441a127a0daabbd17c512e34817ddbcadfd Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Sat, 16 Mar 2002 23:10:52 +0000 Subject: - 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... --- ncpd/channel.cc | 24 +++++++ ncpd/channel.h | 7 ++ ncpd/link.cc | 183 +++++++++++++++++++++++++++++++++++++++++++++-------- ncpd/link.h | 29 ++++++++- ncpd/main.cc | 5 +- ncpd/mp_serial.c | 5 +- ncpd/ncp.cc | 126 ++++++++++++++++++++++++++++-------- ncpd/ncp.h | 25 ++++++++ ncpd/packet.cc | 87 ++++++++++++++++++------- ncpd/packet.h | 6 ++ ncpd/socketchan.cc | 44 +++++++++++-- 11 files changed, 456 insertions(+), 85 deletions(-) (limited to 'ncpd') 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:: @@ -123,6 +135,15 @@ send(const bufferStore & buff) transmit(buff); } +void Link:: +purgeAllQueues() +{ + pthread_mutex_lock(&queueMutex); + ackWaitQueue.clear(); + holdQueue.clear(); + pthread_mutex_unlock(&queueMutex); +} + void Link:: purgeQueue(int channel) { @@ -161,7 +182,7 @@ sendAck(int seq) } void Link:: -sendCon() +sendReqCon() { if (hasFailed()) return; @@ -181,9 +202,45 @@ sendCon() p->send(tmp); } +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::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:: +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 #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 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 linkType; vector ackWaitQueue; vector 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 #include "link.h" +#include #include +#include #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::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::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 #endif + +#include + #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 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); } @@ -200,31 +211,47 @@ 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 +#include 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)) -- cgit v1.2.3