plptools
Loading...
Searching...
No Matches
ncp.cc
Go to the documentation of this file.
1/*
2 * This file is part of plptools.
3 *
4 * Copyright (C) 1999 Philip Proudman <philip.proudman@btinternet.com>
5 * Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 *
20 */
21#include "config.h"
22
23#include <iostream>
24#include <string>
25
26#include <time.h>
27
28#include "bufferstore.h"
29#include "bufferarray.h"
30
31#include "link.h"
32#include "linkchan.h"
33#include "ncp_log.h"
34#include "ncp.h"
35#include "rfsv.h"
36
37using namespace std;
38
39NCP::NCP(const char *fname, int baud, unsigned short _verbose, const int cancellationFd)
40{
44
45 failed = false;
46 verbose = _verbose;
47
48 // until detected on receipt of INFO we use these.
51 lChan = NULL;
52
53 // init channels
54 for (int i = 0; i < MAX_CHANNELS_PSION; i++)
55 channelPtr[i] = NULL;
56
57 l = new Link(fname, baud, this, verbose, cancellationFd);
58}
59
61{
63 for (int i = 0; i < maxLinks(); i++) {
64 if (isValidChannel(i)) {
65 bufferStore b2;
68 }
69 channelPtr[i] = NULL;
70 }
72 delete l;
73 delete [] channelPtr;
74 delete [] remoteChanList;
75 delete [] messageList;
76}
77
79maxLinks() {
80 return maxChannels;
81}
82
84reset() {
85 for (int i = 0; i < maxLinks(); i++) {
86 if (isValidChannel(i))
87 channelPtr[i]->terminateWhenAsked();
88 channelPtr[i] = NULL;
89 }
90 failed = false;
91 if (lChan)
92 delete(lChan);
93 lChan = NULL;
94 protocolVersion = PV_SERIES_5; // until detected on receipt of INFO
95 l->reset();
96}
97
98unsigned short NCP::
100{
101 return verbose;
102}
103
105setVerbose(unsigned short _verbose)
106{
107 verbose = _verbose;
109}
110
111short int NCP::
113{
114 return protocolVersion;
115}
116
119 if (s.getLen() > 1) {
120 int channel = s.getByte(0);
122 if (channel == 0) {
124 } else {
125 int allData = s.getByte(1);
127
130 }
131
132 if (!isValidChannel(channel)) {
133 lerr << "ncp: Got message for unknown channel\n";
134 } else {
136 if (allData == LAST_MESS) {
139 } else if (allData != NOT_LAST_MESS) {
140 lerr << "ncp: bizarre third byte!\n";
141 }
142 }
143 }
144 } else
145 lerr << "Got null message\n";
146}
147
149controlChannel(int chan, enum interControllerMessageType t, bufferStore & command)
150{
151 bufferStore open;
152 open.addByte(0); // control
153
154 open.addByte(chan);
155 open.addByte(t);
156 open.addBuff(command);
158 lout << "ncp: >> " << ctrlMsgName(t) << " " << chan << endl;
159 l->send(open);
160}
161
163findPcServer(const char *name)
164{
165 if (name) {
166 vector<PcServer>::iterator i;
167 for (i = pcServers.begin(); i != pcServers.end(); i++)
168 if (i->getName() == name)
169 return i->self();
170 }
171 return NULL;
172}
173
175registerPcServer(TCPSocket *skt, const char *name) {
176 pcServers.push_back(PcServer(skt, name));
177}
178
181 if (server) {
182 vector<PcServer>::iterator i;
183 for (i = pcServers.begin(); i != pcServers.end(); i++)
184 if (i->self() == server) {
185 pcServers.erase(i);
186 return;
187 }
188 }
189}
190
193{
194 int remoteChan = buff.getByte(0);
195
197 buff.discardFirstBytes(2);
199 lout << "ncp: << " << ctrlMsgName(imt) << " " << remoteChan;
200
201 bufferStore b;
202 int localChan;
203
204 switch (imt) {
206 if (verbose & NCP_DEBUG_LOG) {
208 lout << " [" << buff << "]";
209 lout << endl;
210 }
211
212 failed = false;
213 if (!strcmp(buff.getString(0), "LINK.*")) {
214 if (lChan)
215 localChan = lChan->getNcpChannel();
216 else
217 localChan = getFirstUnusedChan();
218
219 // Ack with connect response
220 b.addByte(remoteChan);
221 b.addByte(0);
224 lout << "ncp: Link UP" << endl;
225 linf << _("Connected with a S")
226 << ((protocolVersion == PV_SERIES_5) ? 5 : 3) << _(" at ")
227 << getSpeed() << _(" baud") << endl;
228 // Create linkchan if it does not yet exist
229 if (!lChan) {
231 lout << "ncp: new passive linkChan" << endl;
232 channelPtr[localChan] =
233 lChan = new linkChan(this, localChan);
235 }
237 } else {
238 PcServer *s = findPcServer(buff.getString(0));
239 bool ok = false;
240
241 if (s) {
242 localChan = getFirstUnusedChan();
243 ok = s->clientConnect(localChan, remoteChan);
244 if (!ok)
245 // release channel ptr
246 channelPtr[localChan] = NULL;
247 }
248 b.addByte(remoteChan);
249 if (ok) {
252 lout << "ncp: ACCEPT client connect" << endl;
253 } else {
254 localChan = 0;
257 lout << "ncp: REJECT client connect" << endl;
258 }
260
261 // Create linkchan if it does not yet exist
262 if (!lChan) {
264 lout << "ncp: new active linkChan" << endl;
265 channelPtr[localChan] =
266 lChan = new linkChan(this, -1);
268 }
269
270 }
271 break;
272
274
275 int forChan;
276
277 failed = false;
278 forChan = buff.getByte(0);
280 lout << " ch=" << forChan << " stat=";
281 if (buff.getByte(1) == 0) {
283 lout << "OK" << endl;
284 if (isValidChannel(forChan)) {
285 remoteChanList[forChan] = remoteChan;
286 channelPtr[forChan]->ncpConnectAck();
287 } else {
289 lout << "ncp: message for unknown channel" << endl;
290 }
291 } else {
293 lout << "Unknown " << (int) buff.getByte(1) << endl;
294 if (isValidChannel(forChan))
295 channelPtr[forChan]->ncpConnectNak();
296 }
297 break;
298
300
301 int ver;
302
303 failed = false;
304 ver = buff.getByte(0);
305 // Series 3c returns '3', as does mclink. PsiWin 1.1
306 // returns version 2. We return whatever version we're
307 // sent, which is rather crude, but works for Series 3
308 // and probably 5. If Symbian have changed EPOC Connect
309 // for the Series 5mx/7, this may need to change.
310 //
311 if (ver == PV_SERIES_5 || ver == PV_SERIES_3) {
312 bufferStore b;
313 protocolVersion = ver;
314 if (verbose & NCP_DEBUG_LOG) {
316 lout << " [" << buff << "]";
317 lout << endl;
318 }
319 // Fake NCP version 2 for a Series 3 (behave like PsiWin 1.1)
320 if (ver == PV_SERIES_3) {
321 ver = 2;
322 } else {
323 // Series 5 supports more channels
325 }
326 b.addByte(ver);
327 // Do we send a time of 0 or a real time?
328 // The Psion uses this to determine whether to
329 // restart. (See protocol docs for details)
330 b.addDWord(time(NULL));
332 } else {
333 lout << "ALERT!!!! Unexpected Protocol Version!! (Not Series 3/5?)!" << endl;
334 failed = true;
335 }
336 break;
337
340 lout << " ch=" << (int) buff.getByte(0) << endl;
341 disconnect(buff.getByte(0));
342 l->purgeQueue(remoteChan);
343 break;
344
348 case NCON_MSG_NCP_END:
349 default:
350 if (verbose & NCP_DEBUG_LOG) {
352 lout << " [" << buff << "]";
353 lout << endl;
354 }
355
356 }
357}
358
361{
362 for (int cNum = 1; cNum < maxLinks(); cNum++) {
363 if (channelPtr[cNum] == NULL) {
365 lout << "ncp: getFirstUnusedChan=" << cNum << endl;
366 channelPtr[cNum] = (channel *)0xdeadbeef;
367 return cNum;
368 }
369 }
370 return 0;
371}
372
375{
376 return (channelPtr[channel] && ((long)channelPtr[channel] != 0xdeadbeef));
377}
378
380RegisterAck(int chan, const char *name)
381{
383 lout << "ncp: RegisterAck: chan=" << chan << endl;
384 for (int cNum = 1; cNum < maxLinks(); cNum++) {
385 channel *ch = channelPtr[cNum];
386 if (isValidChannel(cNum) && ch->getNcpChannel() == chan) {
387 ch->setNcpConnectName(name);
388 ch->ncpRegisterAck();
389 return;
390 }
391 }
392 lerr << "ncp: RegisterAck: no channel to deliver" << endl;
393}
394
396Register(channel * ch)
397{
398 if (lChan) {
399 int cNum = ch->getNcpChannel();
400 if (cNum == 0)
401 cNum = getFirstUnusedChan();
402 if (cNum > 0) {
403 channelPtr[cNum] = ch;
404 ch->setNcpChannel(cNum);
405 lChan->Register(ch);
406 } else
407 lerr << "ncp: Out of channels in register" << endl;
408 } else
409 lerr << "ncp: Register without established lChan" << endl;
410}
411
413connect(channel * ch)
414{
415 // look for first unused chan
416
417 int cNum = ch->getNcpChannel();
418 if (cNum == 0)
419 cNum = getFirstUnusedChan();
420 if (cNum > 0) {
421 channelPtr[cNum] = ch;
422 ch->setNcpChannel(cNum);
423 bufferStore b;
424 if (ch->getNcpConnectName())
426 else {
428 b.addString(".*");
429 }
430 b.addByte(0);
432 return cNum;
433 }
434 return -1;
435}
436
439{
440 bool last;
441 do {
442 last = true;
443
444 if (a.getLen() > NCP_SENDLEN)
445 last = false;
446
447 bufferStore out;
449 out.addByte(channel);
450
451 if (last) {
452 out.addByte(LAST_MESS);
453 } else {
455 }
456
457 out.addBuff(a, NCP_SENDLEN);
458 a.discardFirstBytes(NCP_SENDLEN);
459 l->send(out);
460 } while (!last);
462}
463
466{
467 if (!isValidChannel(channel)) {
468 lerr << "ncp: Ignored disconnect for unknown channel #" << channel << endl;
469 return;
470 }
473 lout << "ncp: disconnect: channel=" << channel << endl;
474 channelPtr[channel] = NULL;
475 bufferStore b;
478}
479
482{
483 return l->stuffToSend();
484}
485
487hasFailed()
488{
489 bool lfailed = l->hasFailed();
490 if (failed || lfailed) {
492 lout << "ncp: hasFailed: " << failed << ", " << lfailed << endl;
493 }
494 failed |= lfailed;
495 if (failed) {
496 if (lChan) {
497 channelPtr[lChan->getNcpChannel()] = NULL;
498 delete lChan;
499 }
500 lChan = NULL;
501 }
502 return failed;
503}
504
507{
508 return (lChan != NULL);
509}
510
512getSpeed()
513{
514 return l->getSpeed();
515}
516
517const char *NCP::
518ctrlMsgName(unsigned char msgType)
519{
520 switch (msgType) {
522 return "NCON_MSG_DATA_XOFF";
524 return "NCON_MSG_DATA_XON";
526 return "NCON_MSG_CONNECT_TO_SERVER";
528 return "NCON_MSG_CONNECT_RESPONSE";
530 return "NCON_MSG_CHANNEL_CLOSED";
532 return "NCON_MSG_NCP_INFO";
534 return "NCON_MSG_CHANNEL_DISCONNECT";
535 case NCON_MSG_NCP_END:
536 return "NCON_MSG_NCP_END";
537 }
538 return "NCON_MSG_UNKNOWN";
539}
@ LAST_MESS
Definition: ncp.h:82
@ NOT_LAST_MESS
Definition: ncp.h:82
const char * ctrlMsgName(unsigned char)
Definition: ncp.cc:518
bool failed
Definition: ncp.h:107
int * remoteChanList
Definition: ncp.h:106
@ PV_SERIES_3
Definition: ncp.h:94
@ PV_SERIES_5
Definition: ncp.h:94
friend class Link
Definition: ncp.h:80
unsigned short getVerbose()
Definition: ncp.cc:99
void registerPcServer(TCPSocket *skt, const char *name)
Definition: ncp.cc:175
PcServer * findPcServer(const char *name)
Definition: ncp.cc:163
void unregisterPcServer(PcServer *server)
Definition: ncp.cc:180
bufferStore * messageList
Definition: ncp.h:105
bool isValidChannel(int)
Definition: ncp.cc:374
channel ** channelPtr
Definition: ncp.h:104
int maxLinks()
Definition: ncp.cc:79
int lastSentChannel
Definition: ncp.h:112
linkChan * lChan
Definition: ncp.h:109
bool hasFailed()
Definition: ncp.cc:487
interControllerMessageType
Definition: ncp.h:83
@ NCON_MSG_NCP_END
Definition: ncp.h:92
@ NCON_MSG_DATA_XOFF
Definition: ncp.h:85
@ NCON_MSG_NCP_INFO
Definition: ncp.h:90
@ NCON_MSG_CONNECT_TO_SERVER
Definition: ncp.h:87
@ NCON_MSG_CHANNEL_DISCONNECT
Definition: ncp.h:91
@ NCON_MSG_CHANNEL_CLOSED
Definition: ncp.h:89
@ NCON_MSG_CONNECT_RESPONSE
Definition: ncp.h:88
@ NCON_MSG_DATA_XON
Definition: ncp.h:86
int connect(channel *c)
Definition: ncp.cc:413
Link * l
Definition: ncp.h:102
void Register(channel *c)
Definition: ncp.cc:396
void receive(bufferStore s)
Definition: ncp.cc:118
void decodeControlMessage(bufferStore &buff)
Definition: ncp.cc:192
int maxChannels
Definition: ncp.h:110
bool gotLinkChannel()
Definition: ncp.cc:506
void reset()
Definition: ncp.cc:84
int getFirstUnusedChan()
Definition: ncp.cc:360
void setVerbose(unsigned short)
Definition: ncp.cc:105
int getSpeed()
Definition: ncp.cc:512
unsigned short verbose
Definition: ncp.h:103
short int getProtocolVersion()
Definition: ncp.cc:112
NCP(const char *fname, int baud, unsigned short verbose, const int cancellationFd)
Definition: ncp.cc:39
bool stuffToSend()
Definition: ncp.cc:481
~NCP()
Definition: ncp.cc:60
short int protocolVersion
Definition: ncp.h:108
void disconnect(int channel)
Definition: ncp.cc:465
std::vector< PcServer > pcServers
Definition: ncp.h:111
void send(int channel, bufferStore &a)
Definition: ncp.cc:438
void controlChannel(int chan, enum interControllerMessageType t, bufferStore &command)
Definition: ncp.cc:149
void RegisterAck(int, const char *)
Definition: ncp.cc:380
Representation of a server process on the PC A dummy which does not allow connects for now.
Definition: ncp.h:43
PcServer * self()
Definition: ncp.h:49
bool clientConnect(int, int)
Definition: ncp.h:47
A class for dealing with sockets.
Definition: tcpsocket.h:38
A generic container for an array of bytes.
Definition: bufferstore.h:37
void discardFirstBytes(int len=0)
Removes bytes from the start of the buffer.
Definition: bufferstore.cc:143
void init()
Initializes the bufferStore.
Definition: bufferstore.cc:77
void addBuff(const bufferStore &b, long maxLen=-1)
Appends data to the content of this instance.
Definition: bufferstore.cc:182
void addByte(unsigned char c)
Appends a byte to the content of this instance.
Definition: bufferstore.cc:159
const char * getString(long pos=0) const
Retrieves the characters at index pos.
Definition: bufferstore.cc:120
void addDWord(long dw)
Appends a dword to the content of this instance.
Definition: bufferstore.cc:199
unsigned long getLen() const
Retrieves the length of a bufferStore.
Definition: bufferstore.cc:94
void addString(const char *s)
Appends a string to the content of this instance.
Definition: bufferstore.cc:164
unsigned char getByte(long pos=0) const
Retrieves the byte at index pos.
Definition: bufferstore.cc:98
virtual const char * getNcpRegisterName()=0
void setNcpChannel(int chan)
Definition: channel.cc:118
virtual void ncpConnectAck()=0
void terminateWhenAsked()
Definition: channel.cc:58
virtual void ncpRegisterAck()=0
virtual void ncpDataCallback(bufferStore &a)=0
int getNcpChannel(void)
Definition: channel.cc:124
const char * getNcpConnectName()
Definition: channel.cc:148
void setNcpConnectName(const char *)
Definition: channel.cc:154
void setVerbose(short int _verbose)
Definition: channel.cc:136
void ncpConnectAck()
Definition: linkchan.cc:97
void Register(channel *)
Definition: linkchan.cc:118
@ E_PSI_GEN_NONE
Definition: rfsv.h:110
@ E_PSI_FILE_NXIST
Definition: rfsv.h:135
Definition: doctest.h:522
#define MAX_CHANNELS_SIBO
Definition: ncp.h:33
#define NCP_SENDLEN
Definition: ncp.h:34
#define MAX_CHANNELS_PSION
Definition: ncp.h:32
#define NCP_DEBUG_DUMP
Definition: ncp_log.h:30
std::ostream lerr
std::ostream lout
#define NCP_DEBUG_LOG
Definition: ncp_log.h:29
std::ostream linf
static rfsv * a
Definition: main.cc:53
#define _(String)
Definition: plpintl.h:35