1// Copyright (C) 2017-2015 Ford Motor Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:data-parser-and-backend-provider
4
5#include "qconnectionfactories_p.h"
6#include "qremoteobjectpacket_p.h"
7
8// BEGIN: Backends
9#if defined(Q_OS_QNX)
10#include "qconnection_qnx_backend_p.h"
11#endif
12#include "qconnection_local_backend_p.h"
13#include "qconnection_tcpip_backend_p.h"
14// END: Backends
15
16QT_BEGIN_NAMESPACE
17
18using namespace QtRemoteObjects;
19
20class QtROFactoryLoader
21{
22public:
23 QtROClientFactory clientFactory;
24 QtROServerFactory serverFactory;
25};
26
27Q_GLOBAL_STATIC(QtROFactoryLoader, loader)
28
29inline bool fromDataStream(QDataStream &in, QRemoteObjectPacketTypeEnum &type, QString &name)
30{
31 quint16 _type;
32 in >> _type;
33 type = Invalid;
34 switch (_type) {
35 case Handshake: type = Handshake; break;
36 case InitPacket: type = InitPacket; break;
37 case InitDynamicPacket: type = InitDynamicPacket; break;
38 case AddObject: type = AddObject; break;
39 case RemoveObject: type = RemoveObject; break;
40 case InvokePacket: type = InvokePacket; break;
41 case InvokeReplyPacket: type = InvokeReplyPacket; break;
42 case PropertyChangePacket: type = PropertyChangePacket; break;
43 case ObjectList: type = ObjectList; break;
44 case Ping: type = Ping; break;
45 case Pong: type = Pong; break;
46 default:
47 qCWarning(QT_REMOTEOBJECT_IO) << "Invalid packet received" << _type;
48 }
49 if (type == Invalid)
50 return false;
51 if (type == ObjectList)
52 return true;
53 in >> name;
54 qCDebug(QT_REMOTEOBJECT_IO) << "Packet received of type" << type << "for object" << name;
55 return true;
56}
57
58/*!
59 All communication between nodes happens through some form of QIODevice with
60 an associated QDataStream to handle marshalling of Qt types. QtROIoDeviceBase
61 is an abstract base class that provides a consistent interface to QtRO, yet
62 can be extended to support different types of QIODevice.
63 */
64QtROIoDeviceBase::QtROIoDeviceBase(QObject *parent) : QObject(*new QtROIoDeviceBasePrivate, parent) { }
65
66QtROIoDeviceBase::QtROIoDeviceBase(QtROIoDeviceBasePrivate &dptr, QObject *parent) : QObject(dptr, parent) { }
67
68QtROIoDeviceBase::~QtROIoDeviceBase()
69{
70}
71
72bool QtROIoDeviceBase::read(QRemoteObjectPacketTypeEnum &type, QString &name)
73{
74 Q_D(QtROIoDeviceBase);
75 qCDebug(QT_REMOTEOBJECT_IO) << deviceType() << "read()" << d->m_curReadSize << bytesAvailable();
76
77 if (d->m_curReadSize == 0) {
78 if (bytesAvailable() < static_cast<int>(sizeof(quint32)))
79 return false;
80
81 d->m_dataStream >> d->m_curReadSize;
82 }
83
84 qCDebug(QT_REMOTEOBJECT_IO) << deviceType() << "read()-looking for map" << d->m_curReadSize
85 << bytesAvailable();
86
87 if (bytesAvailable() < d->m_curReadSize)
88 return false;
89
90 d->m_curReadSize = 0;
91 return fromDataStream(in&: d->m_dataStream, type, name);
92}
93
94void QtROIoDeviceBase::write(const QByteArray &data)
95{
96 Q_D(QtROIoDeviceBase);
97 if (connection()->isOpen() && !d->m_isClosing)
98 connection()->write(data);
99}
100
101void QtROIoDeviceBase::write(const QByteArray &data, qint64 size)
102{
103 Q_D(QtROIoDeviceBase);
104 if (connection()->isOpen() && !d->m_isClosing)
105 connection()->write(data: data.data(), len: size);
106}
107
108bool QtROIoDeviceBase::isOpen() const
109{
110 return !isClosing();
111}
112
113void QtROIoDeviceBase::close()
114{
115 Q_D(QtROIoDeviceBase);
116 d->m_isClosing = true;
117 doClose();
118}
119
120qint64 QtROIoDeviceBase::bytesAvailable() const
121{
122 return connection()->bytesAvailable();
123}
124
125void QtROIoDeviceBase::initializeDataStream()
126{
127 Q_D(QtROIoDeviceBase);
128 d->m_dataStream.setDevice(connection());
129 d->m_dataStream.resetStatus();
130}
131
132bool QtROIoDeviceBase::isClosing() const
133{
134 Q_D(const QtROIoDeviceBase);
135 return d->m_isClosing;
136}
137
138void QtROIoDeviceBase::addSource(const QString &name)
139{
140 Q_D(QtROIoDeviceBase);
141 d->m_remoteObjects.insert(value: name);
142}
143
144void QtROIoDeviceBase::removeSource(const QString &name)
145{
146 Q_D(QtROIoDeviceBase);
147 d->m_remoteObjects.remove(value: name);
148}
149
150QSet<QString> QtROIoDeviceBase::remoteObjects() const
151{
152 Q_D(const QtROIoDeviceBase);
153 return d->m_remoteObjects;
154}
155
156QtROClientIoDevice::QtROClientIoDevice(QObject *parent) : QtROIoDeviceBase(*new QtROClientIoDevicePrivate, parent)
157{
158}
159
160QtROClientIoDevice::~QtROClientIoDevice()
161{
162 if (!isClosing())
163 close();
164}
165
166void QtROClientIoDevice::disconnectFromServer()
167{
168 doDisconnectFromServer();
169 emit shouldReconnect(this);
170}
171
172QUrl QtROClientIoDevice::url() const
173{
174 Q_D(const QtROClientIoDevice);
175 return d->m_url;
176}
177
178QString QtROClientIoDevice::deviceType() const
179{
180 return QStringLiteral("QtROClientIoDevice");
181}
182
183void QtROClientIoDevice::setUrl(const QUrl &url)
184{
185 Q_D(QtROClientIoDevice);
186 d->m_url = url;
187}
188
189/*!
190 The Qt servers create QIODevice derived classes from handleConnection. The
191 problem is that they behave differently, so this class adds some
192 consistency.
193 */
194QtROServerIoDevice::QtROServerIoDevice(QObject *parent) : QtROIoDeviceBase(parent)
195{
196}
197
198QString QtROServerIoDevice::deviceType() const
199{
200 return QStringLiteral("QtROServerIoDevice");
201}
202
203QConnectionAbstractServer::QConnectionAbstractServer(QObject *parent)
204 : QObject(parent)
205{
206}
207
208QConnectionAbstractServer::~QConnectionAbstractServer()
209{
210}
211
212QtROServerIoDevice *QConnectionAbstractServer::nextPendingConnection()
213{
214 QtROServerIoDevice *iodevice = configureNewConnection();
215 iodevice->initializeDataStream();
216 return iodevice;
217}
218
219QtROExternalIoDevice::QtROExternalIoDevice(QIODevice *device, QObject *parent)
220 : QtROIoDeviceBase(*new QtROExternalIoDevicePrivate(device), parent)
221{
222 Q_D(QtROExternalIoDevice);
223 initializeDataStream();
224 connect(sender: device, signal: &QIODevice::aboutToClose, context: this, slot: [d]() { d->m_isClosing = true; });
225 connect(sender: device, signal: &QIODevice::readyRead, context: this, slot: &QtROExternalIoDevice::readyRead);
226 auto meta = device->metaObject();
227 if (-1 != meta->indexOfSignal(signal: "disconnected()"))
228 connect(sender: device, SIGNAL(disconnected()), receiver: this, SIGNAL(disconnected()));
229}
230
231QIODevice *QtROExternalIoDevice::connection() const
232{
233 Q_D(const QtROExternalIoDevice);
234 return d->m_device;
235}
236
237bool QtROExternalIoDevice::isOpen() const
238{
239 Q_D(const QtROExternalIoDevice);
240 if (!d->m_device)
241 return false;
242 return d->m_device->isOpen() && QtROIoDeviceBase::isOpen();
243}
244
245void QtROExternalIoDevice::doClose()
246{
247 Q_D(QtROExternalIoDevice);
248 if (isOpen())
249 d->m_device->close();
250}
251
252QString QtROExternalIoDevice::deviceType() const
253{
254 return QStringLiteral("QtROExternalIoDevice");
255}
256
257/*!
258 \class QtROServerFactory
259 \inmodule QtRemoteObjects
260 \brief A class that holds information about server backends available on the Qt Remote Objects network.
261*/
262QtROServerFactory::QtROServerFactory()
263{
264#ifdef Q_OS_QNX
265 registerType<QnxServerImpl>(QStringLiteral("qnx"));
266#endif
267#ifdef Q_OS_LINUX
268 registerType<AbstractLocalServerImpl>(QStringLiteral("localabstract"));
269#endif
270 registerType<LocalServerImpl>(QStringLiteral("local"));
271 registerType<TcpServerImpl>(QStringLiteral("tcp"));
272}
273
274QtROServerFactory *QtROServerFactory::instance()
275{
276 return &loader->serverFactory;
277}
278
279/*!
280 \class QtROClientFactory
281 \inmodule QtRemoteObjects
282 \brief A class that holds information about client backends available on the Qt Remote Objects network.
283*/
284QtROClientFactory::QtROClientFactory()
285{
286#ifdef Q_OS_QNX
287 registerType<QnxClientIo>(QStringLiteral("qnx"));
288#endif
289#ifdef Q_OS_LINUX
290 registerType<AbstractLocalClientIo>(QStringLiteral("localabstract"));
291#endif
292 registerType<LocalClientIo>(QStringLiteral("local"));
293 registerType<TcpClientIo>(QStringLiteral("tcp"));
294}
295
296QtROClientFactory *QtROClientFactory::instance()
297{
298 return &loader->clientFactory;
299}
300
301/*!
302 \fn template <typename T> void qRegisterRemoteObjectsClient(const QString &id)
303 \relates QtROClientFactory
304
305 Registers the Remote Objects client \a id for the type \c{T}.
306
307 If you need a custom transport protocol for Qt Remote Objects, you need to
308 register the client & server implementation here.
309
310 \note This function requires that \c{T} is a fully defined type at the point
311 where the function is called.
312
313 This example registers the class \c{CustomClientIo} as \c{"myprotocol"}:
314
315 \code
316 qRegisterRemoteObjectsClient<CustomClientIo>(QStringLiteral("myprotocol"));
317 \endcode
318
319 With this in place, you can now instantiate nodes using this new custom protocol:
320
321 \code
322 QRemoteObjectNode client(QUrl(QStringLiteral("myprotocol:registry")));
323 \endcode
324
325 \sa {qRegisterRemoteObjectsServer}
326*/
327
328/*!
329 \fn template <typename T> void qRegisterRemoteObjectsServer(const QString &id)
330 \relates QtROServerFactory
331
332 Registers the Remote Objects server \a id for the type \c{T}.
333
334 If you need a custom transport protocol for Qt Remote Objects, you need to
335 register the client & server implementation here.
336
337 \note This function requires that \c{T} is a fully defined type at the point
338 where the function is called.
339
340 This example registers the class \c{CustomServerImpl} as \c{"myprotocol"}:
341
342 \code
343 qRegisterRemoteObjectsServer<CustomServerImpl>(QStringLiteral("myprotocol"));
344 \endcode
345
346 With this in place, you can now instantiate nodes using this new custom protocol:
347
348 \code
349 QRemoteObjectNode client(QUrl(QStringLiteral("myprotocol:registry")));
350 \endcode
351
352 \sa {qRegisterRemoteObjectsClient}
353*/
354
355QtROIoDeviceBasePrivate::QtROIoDeviceBasePrivate() : QObjectPrivate()
356{
357 m_dataStream.setVersion(dataStreamVersion);
358 m_dataStream.setByteOrder(QDataStream::LittleEndian);
359}
360
361QT_END_NAMESPACE
362

source code of qtremoteobjects/src/remoteobjects/qconnectionfactories.cpp