Revision control

Copy as Markdown

// Copyright (C) 2021 Ford Motor Company
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:critical reason:data-parser
#ifndef QTREMOTEOBJECTPACKET_P_H
#define QTREMOTEOBJECTPACKET_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qtremoteobjectglobal.h"
#include "qremoteobjectsource.h"
#include "qconnectionfactories.h"
#include <QtCore/qhash.h>
#include <QtCore/qmap.h>
#include <QtCore/qpair.h>
#include <QtCore/qmetaassociation.h>
#include <QtCore/qmetasequence.h>
#include <QtCore/qurl.h>
#include <QtCore/qvariant.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qdatastream.h>
#include <QtCore/private/qglobal_p.h>
#include <cstdlib>
QT_BEGIN_NAMESPACE
class QMetaObjectBuilder;
class QRemoteObjectSourceBase;
class QRemoteObjectRootSource;
namespace QRemoteObjectPackets {
Q_NAMESPACE
class DataStreamPacket;
struct ObjectInfo
{
QString name;
QString typeName;
QByteArray signature;
};
inline QDebug operator<<(QDebug dbg, const ObjectInfo &info)
{
dbg.nospace() << "ObjectInfo(" << info.name << ", " << info.typeName << ", " << info.signature <<")";
return dbg.space();
}
inline QDataStream& operator<<(QDataStream &stream, const ObjectInfo &info)
{
return stream << info.name << info.typeName << info.signature;
}
inline QDataStream& operator>>(QDataStream &stream, ObjectInfo &info)
{
return stream >> info.name >> info.typeName >> info.signature;
}
using ObjectInfoList = QList<ObjectInfo>;
enum class ObjectType : quint8 { CLASS, MODEL, GADGET };
Q_ENUM_NS(ObjectType)
// Use a short name, as QVariant::save writes the name every time a qvariant of
// this type is serialized
class QRO_
{
public:
QRO_() : type(ObjectType::CLASS), isNull(true) {}
explicit QRO_(QRemoteObjectSourceBase *source);
explicit QRO_(const QVariant &value);
QString name, typeName;
ObjectType type;
bool isNull;
QByteArray classDefinition;
QByteArray parameters;
};
inline QDebug operator<<(QDebug dbg, const QRO_ &info)
{
dbg.nospace() << "QRO_(name: " << info.name << ", typeName: " << info.typeName
<< ", type: " << info.type << ", valid: " << (info.isNull ? "true" : "false")
<< ", parameters: {" << info.parameters << ")"
<< (info.classDefinition.isEmpty() ? " no definitions)" : " with definitions)");
return dbg.space();
}
QDataStream& operator<<(QDataStream &stream, const QRO_ &info);
QDataStream& operator>>(QDataStream &stream, QRO_ &info);
// Class for transmitting sequence data. Needed because containers for custom
// types (and even primitive types in Qt5) are not registered with the metaObject
// system. This wrapper allows us to create the desired container if it is
// registered, or a QtROSequentialContainer if it is not. QtROSequentialContainer
// is derived from QVariantList, so it can be used from QML similar to the API
// type.
class QSQ_
{
public:
QSQ_() {}
explicit QSQ_(const QVariant &lst);
QByteArray typeName, valueTypeName;
QByteArray values;
};
inline QDebug operator<<(QDebug dbg, const QSQ_ &seq)
{
dbg.nospace() << "QSQ_(typeName: " << seq.typeName << ", valueType: " << seq.valueTypeName
<< ", values: {" << seq.values <<")";
return dbg.space();
}
QDataStream& operator<<(QDataStream &stream, const QSQ_ &info);
QDataStream& operator>>(QDataStream &stream, QSQ_ &info);
// Class for transmitting associative containers. Needed because containers for
// custom types (and even primitive types in Qt5) are not registered with the
// metaObject system. This wrapper allows us to create the desired container if
// it is registered, or a QtROAssociativeContainer if it is not.
// QtROAssociativeContainer is derived from QVariantMap, so it can be used from
// QML similar to the API type.
class QAS_
{
public:
QAS_() {}
explicit QAS_(const QVariant &lst);
QByteArray typeName, keyTypeName, valueTypeName;
QByteArray values;
};
inline QDebug operator<<(QDebug dbg, const QAS_ &seq)
{
dbg.nospace() << "QAS_(typeName: " << seq.typeName << ", keyType: " << seq.keyTypeName
<< ", valueType: " << seq.valueTypeName << ", values: {" << seq.values <<")";
return dbg.space();
}
QDataStream& operator<<(QDataStream &stream, const QAS_ &info);
QDataStream& operator>>(QDataStream &stream, QAS_ &info);
//Helper class for creating a QByteArray from a QRemoteObjectPacket
class DataStreamPacket : public QDataStream
{
public:
DataStreamPacket(quint16 id = QtRemoteObjects::InvokePacket);
void setId(quint16 id)
{
device()->seek(baseAddress);
*this << quint32(0);
*this << id;
}
void finishPacket()
{
size = device()->pos();
device()->seek(baseAddress);
*this << quint32(size - baseAddress - sizeof(quint32));
baseAddress = size; // Allow appending until reset() is called
}
const QByteArray &payload()
{
array.resize(size);
return array;
}
void reset()
{
baseAddress = 0;
size = 0;
array.clear();
}
private:
QByteArray array;
int baseAddress;
int size;
Q_DISABLE_COPY(DataStreamPacket)
};
class CodecBase
{
public:
CodecBase() = default;
CodecBase(const CodecBase &) = default;
CodecBase(CodecBase &&) = default;
CodecBase &operator=(const CodecBase &) = default;
CodecBase &operator=(CodecBase &&) = default;
virtual ~CodecBase() = default;
virtual void serializeObjectListPacket(const ObjectInfoList &) = 0;
virtual void deserializeObjectListPacket(QDataStream &in, ObjectInfoList &) = 0;
virtual void serializeInitPacket(const QRemoteObjectRootSource *) = 0;
virtual void serializeInitDynamicPacket(const QRemoteObjectRootSource *) = 0;
virtual void serializePropertyChangePacket(QRemoteObjectSourceBase *source,
int signalIndex) = 0;
virtual void deserializePropertyChangePacket(QDataStream &in, int &index, QVariant &value) = 0;
virtual void serializeProperty(const QRemoteObjectSourceBase *source, int internalIndex) = 0;
// Heartbeat packets
virtual void serializePingPacket(const QString &name) = 0;
virtual void serializePongPacket(const QString &name) = 0;
virtual void serializeInvokePacket(const QString &name, int call, int index,
const QVariantList &args, int serialId = -1,
int propertyIndex = -1) = 0;
virtual void deserializeInvokePacket(QDataStream &in, int &call, int &index, QVariantList &args,
int &serialId, int &propertyIndex) = 0;
virtual void serializeInvokeReplyPacket(const QString &name, int ackedSerialId,
const QVariant &value) = 0;
virtual void serializeHandshakePacket() = 0;
virtual void serializeRemoveObjectPacket(const QString &name) = 0;
//There is no deserializeRemoveObjectPacket - no parameters other than id and name
virtual void serializeAddObjectPacket(const QString &name, bool isDynamic) = 0;
virtual void deserializeAddObjectPacket(QDataStream &, bool &isDynamic) = 0;
virtual void deserializeInitPacket(QDataStream &, QVariantList &) = 0;
virtual void deserializeInvokeReplyPacket(QDataStream &in, int &ackedSerialId,
QVariant &value) = 0;
void send(const QSet<QtROIoDeviceBase *> &connections);
void send(const QVector<QtROIoDeviceBase *> &connections);
void send(QtROIoDeviceBase *connection);
protected:
// A payload can consist of one or more packets
virtual const QByteArray &getPayload() = 0;
virtual void reset() {}
};
class QDataStreamCodec : public CodecBase
{
public:
void serializeObjectListPacket(const ObjectInfoList &) override;
void deserializeObjectListPacket(QDataStream &in, ObjectInfoList &) override;
void serializeInitPacket(const QRemoteObjectRootSource *) override;
void serializeInitDynamicPacket(const QRemoteObjectRootSource*) override;
void serializePropertyChangePacket(QRemoteObjectSourceBase *source, int signalIndex) override;
void deserializePropertyChangePacket(QDataStream &in, int &index, QVariant &value) override;
void serializeProperty(const QRemoteObjectSourceBase *source, int internalIndex) override;
void serializePingPacket(const QString &name) override;
void serializePongPacket(const QString &name) override;
void serializeInvokePacket(const QString &name, int call, int index, const QVariantList &args,
int serialId = -1, int propertyIndex = -1) override;
void deserializeInvokePacket(QDataStream &in, int &call, int &index, QVariantList &args,
int &serialId, int &propertyIndex) override;
void serializeInvokeReplyPacket(const QString &name, int ackedSerialId,
const QVariant &value) override;
void serializeHandshakePacket() override;
void serializeRemoveObjectPacket(const QString &name) override;
void serializeAddObjectPacket(const QString &name, bool isDynamic) override;
void deserializeAddObjectPacket(QDataStream &, bool &isDynamic) override;
void deserializeInitPacket(QDataStream &, QVariantList &) override;
void deserializeInvokeReplyPacket(QDataStream &in, int &ackedSerialId,
QVariant &value) override;
protected:
const QByteArray &getPayload() override {
return m_packet.payload();
}
void reset() override {
m_packet.reset();
}
private:
void serializeDefinition(QDataStream &, const QRemoteObjectSourceBase *);
void serializeProperty(QDataStream &ds, const QRemoteObjectSourceBase *source, int internalIndex);
void serializeProperties(const QRemoteObjectSourceBase *source);
DataStreamPacket m_packet;
};
QMetaType transferTypeForEnum(QMetaType enumType);
QVariant encodeVariant(const QVariant &value);
QVariant decodeVariant(QVariant &&value, QMetaType metaType);
} // namespace QRemoteObjectPackets
QT_END_NAMESPACE
QT_DECL_METATYPE_EXTERN_TAGGED(QRemoteObjectPackets::QRO_, QRemoteObjectPackets__QRO_,
/* not exported */)
#endif