1// Copyright (C) 2021 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
4
5#ifndef QTREMOTEOBJECTPACKET_P_H
6#define QTREMOTEOBJECTPACKET_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include "qtremoteobjectglobal.h"
20#include "qremoteobjectsource.h"
21#include "qconnectionfactories.h"
22
23#include <QtCore/qassociativeiterable.h>
24#include <QtCore/qhash.h>
25#include <QtCore/qmap.h>
26#include <QtCore/qpair.h>
27#include <QtCore/qsequentialiterable.h>
28#include <QtCore/qurl.h>
29#include <QtCore/qvariant.h>
30#include <QtCore/qloggingcategory.h>
31#include <QtCore/qdatastream.h>
32#include <QtCore/private/qglobal_p.h>
33
34#include <cstdlib>
35
36QT_BEGIN_NAMESPACE
37
38class QMetaObjectBuilder;
39class QRemoteObjectSourceBase;
40class QRemoteObjectRootSource;
41
42namespace QRemoteObjectPackets {
43
44Q_NAMESPACE
45
46class DataStreamPacket;
47
48struct ObjectInfo
49{
50 QString name;
51 QString typeName;
52 QByteArray signature;
53};
54
55inline QDebug operator<<(QDebug dbg, const ObjectInfo &info)
56{
57 dbg.nospace() << "ObjectInfo(" << info.name << ", " << info.typeName << ", " << info.signature <<")";
58 return dbg.space();
59}
60
61inline QDataStream& operator<<(QDataStream &stream, const ObjectInfo &info)
62{
63 return stream << info.name << info.typeName << info.signature;
64}
65
66inline QDataStream& operator>>(QDataStream &stream, ObjectInfo &info)
67{
68 return stream >> info.name >> info.typeName >> info.signature;
69}
70
71using ObjectInfoList = QList<ObjectInfo>;
72
73enum class ObjectType : quint8 { CLASS, MODEL, GADGET };
74Q_ENUM_NS(ObjectType)
75
76// Use a short name, as QVariant::save writes the name every time a qvariant of
77// this type is serialized
78class QRO_
79{
80public:
81 QRO_() : type(ObjectType::CLASS), isNull(true) {}
82 explicit QRO_(QRemoteObjectSourceBase *source);
83 explicit QRO_(const QVariant &value);
84 QString name, typeName;
85 ObjectType type;
86 bool isNull;
87 QByteArray classDefinition;
88 QByteArray parameters;
89};
90
91inline QDebug operator<<(QDebug dbg, const QRO_ &info)
92{
93 dbg.nospace() << "QRO_(name: " << info.name << ", typeName: " << info.typeName
94 << ", type: " << info.type << ", valid: " << (info.isNull ? "true" : "false")
95 << ", parameters: {" << info.parameters << ")"
96 << (info.classDefinition.isEmpty() ? " no definitions)" : " with definitions)");
97 return dbg.space();
98}
99
100QDataStream& operator<<(QDataStream &stream, const QRO_ &info);
101
102QDataStream& operator>>(QDataStream &stream, QRO_ &info);
103
104// Class for transmitting sequence data. Needed because containers for custom
105// types (and even primitive types in Qt5) are not registered with the metaObject
106// system. This wrapper allows us to create the desired container if it is
107// registered, or a QtROSequentialContainer if it is not. QtROSequentialContainer
108// is derived from QVariantList, so it can be used from QML similar to the API
109// type.
110class QSQ_
111{
112public:
113 QSQ_() {}
114 explicit QSQ_(const QVariant &lst);
115 QByteArray typeName, valueTypeName;
116 QByteArray values;
117};
118
119inline QDebug operator<<(QDebug dbg, const QSQ_ &seq)
120{
121 dbg.nospace() << "QSQ_(typeName: " << seq.typeName << ", valueType: " << seq.valueTypeName
122 << ", values: {" << seq.values <<")";
123 return dbg.space();
124}
125
126QDataStream& operator<<(QDataStream &stream, const QSQ_ &info);
127
128QDataStream& operator>>(QDataStream &stream, QSQ_ &info);
129
130// Class for transmitting associative containers. Needed because containers for
131// custom types (and even primitive types in Qt5) are not registered with the
132// metaObject system. This wrapper allows us to create the desired container if
133// it is registered, or a QtROAssociativeContainer if it is not.
134// QtROAssociativeContainer is derived from QVariantMap, so it can be used from
135// QML similar to the API type.
136class QAS_
137{
138public:
139 QAS_() {}
140 explicit QAS_(const QVariant &lst);
141 QByteArray typeName, keyTypeName, valueTypeName;
142 QByteArray values;
143};
144
145inline QDebug operator<<(QDebug dbg, const QAS_ &seq)
146{
147 dbg.nospace() << "QAS_(typeName: " << seq.typeName << ", keyType: " << seq.keyTypeName
148 << ", valueType: " << seq.valueTypeName << ", values: {" << seq.values <<")";
149 return dbg.space();
150}
151
152QDataStream& operator<<(QDataStream &stream, const QAS_ &info);
153
154QDataStream& operator>>(QDataStream &stream, QAS_ &info);
155
156//Helper class for creating a QByteArray from a QRemoteObjectPacket
157class DataStreamPacket : public QDataStream
158{
159public:
160 DataStreamPacket(quint16 id = QtRemoteObjects::InvokePacket);
161
162 void setId(quint16 id)
163 {
164 device()->seek(pos: baseAddress);
165 *this << quint32(0);
166 *this << id;
167 }
168
169 void finishPacket()
170 {
171 size = device()->pos();
172 device()->seek(pos: baseAddress);
173 *this << quint32(size - baseAddress - sizeof(quint32));
174 baseAddress = size; // Allow appending until reset() is called
175 }
176
177 const QByteArray &payload()
178 {
179 array.resize(size);
180 return array;
181 }
182
183 void reset()
184 {
185 baseAddress = 0;
186 size = 0;
187 array.clear();
188 }
189
190private:
191 QByteArray array;
192 int baseAddress;
193 int size;
194
195 Q_DISABLE_COPY(DataStreamPacket)
196};
197
198class CodecBase
199{
200public:
201 CodecBase() = default;
202 CodecBase(const CodecBase &) = default;
203 CodecBase(CodecBase &&) = default;
204 CodecBase &operator=(const CodecBase &) = default;
205 CodecBase &operator=(CodecBase &&) = default;
206 virtual ~CodecBase() = default;
207
208 virtual void serializeObjectListPacket(const ObjectInfoList &) = 0;
209 virtual void deserializeObjectListPacket(QDataStream &in, ObjectInfoList &) = 0;
210 virtual void serializeInitPacket(const QRemoteObjectRootSource *) = 0;
211 virtual void serializeInitDynamicPacket(const QRemoteObjectRootSource *) = 0;
212 virtual void serializePropertyChangePacket(QRemoteObjectSourceBase *source,
213 int signalIndex) = 0;
214 virtual void deserializePropertyChangePacket(QDataStream &in, int &index, QVariant &value) = 0;
215 virtual void serializeProperty(const QRemoteObjectSourceBase *source, int internalIndex) = 0;
216 // Heartbeat packets
217 virtual void serializePingPacket(const QString &name) = 0;
218 virtual void serializePongPacket(const QString &name) = 0;
219 virtual void serializeInvokePacket(const QString &name, int call, int index,
220 const QVariantList &args, int serialId = -1,
221 int propertyIndex = -1) = 0;
222 virtual void deserializeInvokePacket(QDataStream &in, int &call, int &index, QVariantList &args,
223 int &serialId, int &propertyIndex) = 0;
224 virtual void serializeInvokeReplyPacket(const QString &name, int ackedSerialId,
225 const QVariant &value) = 0;
226 virtual void serializeHandshakePacket() = 0;
227 virtual void serializeRemoveObjectPacket(const QString &name) = 0;
228 //There is no deserializeRemoveObjectPacket - no parameters other than id and name
229 virtual void serializeAddObjectPacket(const QString &name, bool isDynamic) = 0;
230 virtual void deserializeAddObjectPacket(QDataStream &, bool &isDynamic) = 0;
231 virtual void deserializeInitPacket(QDataStream &, QVariantList &) = 0;
232 virtual void deserializeInvokeReplyPacket(QDataStream &in, int &ackedSerialId,
233 QVariant &value) = 0;
234 void send(const QSet<QtROIoDeviceBase *> &connections);
235 void send(const QVector<QtROIoDeviceBase *> &connections);
236 void send(QtROIoDeviceBase *connection);
237
238protected:
239 // A payload can consist of one or more packets
240 virtual const QByteArray &getPayload() = 0;
241 virtual void reset() {}
242};
243
244class QDataStreamCodec : public CodecBase
245{
246public:
247 void serializeObjectListPacket(const ObjectInfoList &) override;
248 void deserializeObjectListPacket(QDataStream &in, ObjectInfoList &) override;
249 void serializeInitPacket(const QRemoteObjectRootSource *) override;
250 void serializeInitDynamicPacket(const QRemoteObjectRootSource*) override;
251 void serializePropertyChangePacket(QRemoteObjectSourceBase *source, int signalIndex) override;
252 void deserializePropertyChangePacket(QDataStream &in, int &index, QVariant &value) override;
253 void serializeProperty(const QRemoteObjectSourceBase *source, int internalIndex) override;
254 void serializePingPacket(const QString &name) override;
255 void serializePongPacket(const QString &name) override;
256 void serializeInvokePacket(const QString &name, int call, int index, const QVariantList &args,
257 int serialId = -1, int propertyIndex = -1) override;
258 void deserializeInvokePacket(QDataStream &in, int &call, int &index, QVariantList &args,
259 int &serialId, int &propertyIndex) override;
260 void serializeInvokeReplyPacket(const QString &name, int ackedSerialId,
261 const QVariant &value) override;
262 void serializeHandshakePacket() override;
263 void serializeRemoveObjectPacket(const QString &name) override;
264 void serializeAddObjectPacket(const QString &name, bool isDynamic) override;
265 void deserializeAddObjectPacket(QDataStream &, bool &isDynamic) override;
266 void deserializeInitPacket(QDataStream &, QVariantList &) override;
267 void deserializeInvokeReplyPacket(QDataStream &in, int &ackedSerialId,
268 QVariant &value) override;
269
270protected:
271 const QByteArray &getPayload() override {
272 return m_packet.payload();
273 }
274 void reset() override {
275 m_packet.reset();
276 }
277private:
278 void serializeDefinition(QDataStream &, const QRemoteObjectSourceBase *);
279 void serializeProperty(QDataStream &ds, const QRemoteObjectSourceBase *source, int internalIndex);
280 void serializeProperties(const QRemoteObjectSourceBase *source);
281 DataStreamPacket m_packet;
282};
283
284QMetaType transferTypeForEnum(QMetaType enumType);
285QVariant encodeVariant(const QVariant &value);
286QVariant decodeVariant(QVariant &&value, QMetaType metaType);
287
288} // namespace QRemoteObjectPackets
289
290QT_END_NAMESPACE
291
292QT_DECL_METATYPE_EXTERN_TAGGED(QRemoteObjectPackets::QRO_, QRemoteObjectPackets__QRO_,
293 /* not exported */)
294
295#endif
296

source code of qtremoteobjects/src/remoteobjects/qremoteobjectpacket_p.h