plptools
Loading...
Searching...
No Matches
ncpclient.h
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-2002 Fritz Elfert <felfert@to.com>
6 * Copyright (C) 2006-2025 Reuben Thomas <rrt@sc3d.org>
7 * Copyright (C) 2026 Jason Morley <hello@jbmorley.co.uk>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * along with this program; if not, see <https://www.gnu.org/licenses/>.
21 *
22 */
23
24#pragma once
25
26#include "config.h"
27
28#include <memory>
29#include <string>
30#include <vector>
31
32#include "connectionerror.h"
33#include "bufferstore.h"
34#include "Enum.h"
35#include "tcpsocket.h"
36
37class TCPClient;
38
39namespace ncp_client {
40
52template<typename Client, typename Client16, typename Client32>
53Client *connect(const std::string &host, int port, bool waitForDevice, Enum<ConnectionError> *error) {
54
55 if (error) {
57 }
58
59 auto socket = std::make_unique<TCPSocket>();
60 if (!socket->connect(host.c_str(), port)) {
61 if (error) {
63 }
64 return nullptr;
65 }
66
67 // At this point the socket is connected to the ncp daemon, which will have (hopefully) seen an INFO exchange, where
68 // the protocol version of the remote Psion was sent, and noted. We have to ask the ncp daemon which protocol it
69 // saw, so we can instantiate the correct RPCS protocol handler for the caller. We announce ourselves to the NCP
70 // daemon, and the relevant RPCS module will also announce itself.
71
72 BufferStore bufferStore;
73
74 bufferStore.addStringT("NCP$INFO");
75 if (!socket->sendBufferStore(bufferStore)) {
76 if (!waitForDevice) {
77 if (error) {
79 }
80 } else {
81 socket->closeSocket();
82 socket->reconnect();
83 if (error) {
85 }
86 }
87 return nullptr;
88 }
89 if (socket->getBufferStore(bufferStore) == 1) {
90 if (bufferStore.getLen() > 8 && !strncmp(bufferStore.getString(), "Series 3", 8)) {
91 return new Client16(std::move(socket));
92 }
93 else if (bufferStore.getLen() > 8 && !strncmp(bufferStore.getString(), "Series 5", 8)) {
94 return new Client32(std::move(socket));
95 }
96 if ((bufferStore.getLen() > 8) && !strncmp(bufferStore.getString(), "No Psion", 8)) {
97 socket->closeSocket();
98 socket->reconnect();
99 if (error) {
101 }
102 return nullptr;
103 }
104 // Invalid protocol version
105 if (error) {
107 }
108 } else {
109 if (error) {
111 }
112 }
113
114 // No message returned.
115 return nullptr;
116}
117
118};
A generic container for an array of bytes.
Definition: bufferstore.h:36
const char * getString(long pos=0) const
Retrieves the characters at index pos.
Definition: bufferstore.cc:118
void addStringT(const char *s)
Appends a string to the content of this instance.
Definition: bufferstore.cc:169
unsigned long getLen() const
Retrieves the length of a BufferStore.
Definition: bufferstore.cc:92
Wrapper class featuring range-checking and string representation of enumerated values.
Definition: Enum.h:135
@ FACERR_PROTVERSION
@ FACERR_AGAIN
@ FACERR_NONE
@ FACERR_COULD_NOT_SEND
@ FACERR_NORESPONSE
@ FACERR_NOPSION
@ FACERR_CONNECTION_FAILURE
Client * connect(const std::string &host, int port, bool waitForDevice, Enum< ConnectionError > *error)
Create a new NCP client instance, selecting the appropriate subclass based on the device type reporte...
Definition: ncpclient.h:53
static void error(int line)
Definition: sismain.cpp:44