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

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