diff options
author | Rainer Keller <Rainer.Keller@qt.io> | 2019-09-13 12:41:49 +0200 |
---|---|---|
committer | Rainer Keller <Rainer.Keller@qt.io> | 2019-10-02 11:43:21 +0200 |
commit | 2611803da202d9bfade0249ff07bd0d1fd669046 (patch) | |
tree | cbcae1126506141e9ae4c335c6c574529bc1e942 | |
parent | ccf05a36efeb9f50c23283c5f9f2fefcfde4180a (diff) |
Fix GUID binary encoder endianness
The OPC-UA standard defines in part 6 chapter 5.2.2.6 that
integer parts of a GUID have to be transferred in little endian
order.
Change-Id: I2082ecef414572d87cd5586fc4ea9f5f8887a4aa
Reviewed-by: Frank Meerkoetter <frank.meerkoetter@basyskom.com>
-rw-r--r-- | src/opcua/client/qopcuabinarydataencoding.h | 33 | ||||
-rw-r--r-- | tests/auto/qopcuaclient/tst_client.cpp | 29 |
2 files changed, 58 insertions, 4 deletions
diff --git a/src/opcua/client/qopcuabinarydataencoding.h b/src/opcua/client/qopcuabinarydataencoding.h index 3526614..e613a0d 100644 --- a/src/opcua/client/qopcuabinarydataencoding.h +++ b/src/opcua/client/qopcuabinarydataencoding.h @@ -339,8 +339,27 @@ inline QUuid QOpcUaBinaryDataEncoding::decode<QUuid>(bool &success) return QUuid(); } - const QUuid temp = QUuid::fromRfc4122(QByteArray::fromRawData(m_data->constData() + m_offset, uuidSize)); - m_offset += uuidSize; + const auto data1 = decode<quint32>(success); + if (!success) + return QUuid(); + + const auto data2 = decode<quint16>(success); + if (!success) + return QUuid(); + + const auto data3 = decode<quint16>(success); + if (!success) + return QUuid(); + + const auto data4 = QByteArray::fromRawData(m_data->constData() + m_offset, 8); + if (!success) + return QUuid(); + + m_offset += 8; + + const QUuid temp = QUuid(data1, data2, data3, data4[0], data4[1], data4[2], + data4[3], data4[4], data4[5], data4[6], data4[7]); + success = true; return temp; } @@ -700,10 +719,16 @@ inline bool QOpcUaBinaryDataEncoding::encode<QOpcUaXValue>(const QOpcUaXValue &s template <> inline bool QOpcUaBinaryDataEncoding::encode<QUuid>(const QUuid &src) { - if (!m_data) + if (!encode<quint32>(src.data1)) + return false; + if (!encode<quint16>(src.data2)) return false; + if (!encode<quint16>(src.data3)) + return false; + + auto data = QByteArray::fromRawData(reinterpret_cast<const char *>(src.data4), sizeof(src.data4)); + m_data->append(data); - m_data->append(src.toRfc4122()); return true; } diff --git a/tests/auto/qopcuaclient/tst_client.cpp b/tests/auto/qopcuaclient/tst_client.cpp index c80d3c6..bfb7eb4 100644 --- a/tests/auto/qopcuaclient/tst_client.cpp +++ b/tests/auto/qopcuaclient/tst_client.cpp @@ -476,6 +476,9 @@ private slots: defineDataMethod(resolveBrowsePath_data) void resolveBrowsePath(); + defineDataMethod(extensionObjectWithGuid_data) + void extensionObjectWithGuid(); + void statusStrings(); // This test case restarts the server. It must be run last to avoid @@ -3593,6 +3596,32 @@ void Tst_QOpcUaClient::resolveBrowsePath() QCOMPARE(spy.at(0).at(2).value<QOpcUa::UaStatusCode>(), QOpcUa::UaStatusCode::Good); } +void Tst_QOpcUaClient::extensionObjectWithGuid() +{ + const QByteArray uuidWireData = QByteArray::fromHex("f827ce6cbeb61f48a5a888fd2bbc4fb7"); + const QByteArray opcuaWireData = QByteArray::fromHex("040400") + uuidWireData; + const QString uuidId = QString::fromLatin1("6cce27f8-b6be-481f-a5a8-88fd2bbc4fb7"); + const QString sampleNodeId = QString::fromLatin1("ns=4;g=") + uuidId; + + const auto uuid = QUuid::fromString(uuidId); + QCOMPARE(uuid.toString(QUuid::WithoutBraces), uuidId); + + QOpcUaExtensionObject obj; + obj.setEncoding(QOpcUaExtensionObject::Encoding::ByteString); + obj.setEncodingTypeId(QStringLiteral("ns=2;s=MyEncoding1")); + QOpcUaBinaryDataEncoding encoder(obj); + encoder.encode<QString, QOpcUa::Types::NodeId>(sampleNodeId); + QCOMPARE(obj.encodedBody().toHex(), opcuaWireData.toHex()); + + QByteArray buffer = obj.encodedBody(); + QOpcUaBinaryDataEncoding decoder(&buffer); + + bool success = false; + const auto decodedNodeId = decoder.decode<QString, QOpcUa::Types::NodeId>(success); + QVERIFY(success); + QCOMPARE(decodedNodeId, sampleNodeId); +} + void Tst_QOpcUaClient::statusStrings() { QCOMPARE(statusToString(QOpcUa::Good), "Good"); |