summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKari Oikarinen <kari.oikarinen@qt.io>2016-06-27 15:48:11 +0300
committerKari Oikarinen <kari.oikarinen@qt.io>2016-08-23 08:12:56 +0000
commit178198621734906e6a5c40274058d6435277fb4f (patch)
treed7bfa02b8995719ad69b0e501305e83b3d3d92a8
parent1adcf3d43554d3601e8e998d3993ed36c0fff3b0 (diff)
Introduce version number to the protocol
Version number is sent as uint32 in the payload of the initial Connect message. For now Server always responds to the Connect message with the only protocol version that it knows, but also prints a warning if the asked for protocol version was not the same. Connection checks the version in the response and transitions to Connected state only if the version matches. Change-Id: I937af5a7e1f6bb5056efc03777178bed86b451d4 Reviewed-by: Kimmo Ollila <kimmo.ollila@theqtcompany.com>
-rw-r--r--client/connection.cpp35
-rw-r--r--client/connection.h3
-rw-r--r--libqdb/protocol/protocol.h1
-rw-r--r--qdbd/server.cpp27
-rw-r--r--qdbd/server.h3
-rw-r--r--test/streamtest.cpp64
6 files changed, 116 insertions, 17 deletions
diff --git a/client/connection.cpp b/client/connection.cpp
index f65e04d..747fcc2 100644
--- a/client/connection.cpp
+++ b/client/connection.cpp
@@ -21,6 +21,7 @@
#include "connection.h"
#include "../utils/make_unique.h"
+#include "protocol/protocol.h"
#include "protocol/qdbtransport.h"
#include "service.h"
@@ -41,7 +42,12 @@ Connection::Connection(QdbTransport *transport, QObject *parent)
void Connection::connect()
{
Q_ASSERT(m_state == ConnectionState::Disconnected);
- enqueueMessage(QdbMessage{QdbMessage::Connect, 0, 0});
+
+ QByteArray versionBuffer{};
+ QDataStream dataStream{&versionBuffer, QIODevice::WriteOnly};
+ dataStream << qdbProtocolVersion;
+
+ enqueueMessage(QdbMessage{QdbMessage::Connect, 0, 0, versionBuffer});
}
void Connection::close()
@@ -111,7 +117,10 @@ void Connection::handleMessage()
resetConnection();
break;
}
- m_state = ConnectionState::Connected;
+ if (checkVersion(message))
+ m_state = ConnectionState::Connected;
+ else
+ m_state = ConnectionState::Disconnected;
break;
case ConnectionState::Connected:
switch (message.command()) {
@@ -241,7 +250,8 @@ void Connection::resetConnection()
m_state = ConnectionState::Disconnected;
m_streamRequests.clear();
m_streams.clear();
- enqueueMessage(QdbMessage{QdbMessage::Connect, 0, 0});
+
+ connect();
}
void Connection::closeStream(StreamId id)
@@ -268,7 +278,7 @@ void Connection::finishCreateStream(StreamId hostId, StreamId deviceId)
callback(m_streams[hostId].get());
}
-void Connection::handleWrite(QdbMessage message)
+void Connection::handleWrite(const QdbMessage &message)
{
if (m_streams.find(message.hostStream()) == m_streams.end()) {
qWarning() << "Connection received message to non-existing stream" << message.hostStream();
@@ -278,3 +288,20 @@ void Connection::handleWrite(QdbMessage message)
acknowledge(message.hostStream(), message.deviceStream());
m_streams[message.hostStream()]->receiveMessage(message);
}
+
+bool Connection::checkVersion(const QdbMessage &message)
+{
+ Q_ASSERT(message.command() == QdbMessage::Connect);
+ Q_ASSERT(message.data().size() == sizeof(qdbProtocolVersion));
+
+ QDataStream dataStream{message.data()};
+ uint32_t protocolVersion;
+ dataStream >> protocolVersion;
+
+ if (protocolVersion != qdbProtocolVersion) {
+ qCritical() << "Device offered protocol version" << protocolVersion << ", but only version"
+ << qdbProtocolVersion << "is supported";
+ return false;
+ }
+ return true;
+}
diff --git a/client/connection.h b/client/connection.h
index dd6fe4f..1f3ed62 100644
--- a/client/connection.h
+++ b/client/connection.h
@@ -66,7 +66,8 @@ private:
void resetConnection();
void closeStream(StreamId id);
void finishCreateStream(StreamId hostId, StreamId deviceId);
- void handleWrite(QdbMessage message);
+ void handleWrite(const QdbMessage &message);
+ bool checkVersion(const QdbMessage &message);
ConnectionState m_state;
QHash<StreamId, StreamCreatedCallback> m_streamRequests;
diff --git a/libqdb/protocol/protocol.h b/libqdb/protocol/protocol.h
index c27e072..42a3081 100644
--- a/libqdb/protocol/protocol.h
+++ b/libqdb/protocol/protocol.h
@@ -29,5 +29,6 @@ const uint8_t qdbUsbProtocolId = 0x1;
const int qdbHeaderSize = 4*sizeof(uint32_t);
const int qdbMessageSize = 16*1024;
const int qdbMaxPayloadSize = qdbMessageSize - qdbHeaderSize;
+const uint32_t qdbProtocolVersion = 0;
#endif
diff --git a/qdbd/server.cpp b/qdbd/server.cpp
index b352333..16b0476 100644
--- a/qdbd/server.cpp
+++ b/qdbd/server.cpp
@@ -23,6 +23,7 @@
#include "../utils/make_unique.h"
#include "createexecutor.h"
#include "echoexecutor.h"
+#include "protocol/protocol.h"
#include "protocol/qdbmessage.h"
#include "protocol/qdbtransport.h"
#include "stream.h"
@@ -57,12 +58,14 @@ void Server::handleMessage()
resetServer(false);
break;
}
+ checkVersion(message);
resetServer(true);
break;
case ServerState::Connected:
switch (message.command()) {
case QdbMessage::Connect:
qWarning() << "Server received QdbMessage::Connect while already connected. Resetting.";
+ checkVersion(message);
resetServer(true);
break;
case QdbMessage::Open:
@@ -182,10 +185,15 @@ void Server::resetServer(bool hostConnected)
m_executors.clear();
m_streams.clear();
m_state = hostConnected ? ServerState::Connected : ServerState::Disconnected;
- enqueueMessage(QdbMessage{QdbMessage::Connect, 0, 0});
+
+ QByteArray buffer{};
+ QDataStream dataStream{&buffer, QIODevice::WriteOnly};
+ dataStream << qdbProtocolVersion;
+
+ enqueueMessage(QdbMessage{QdbMessage::Connect, 0, 0, buffer});
}
-void Server::handleWrite(QdbMessage message)
+void Server::handleWrite(const QdbMessage &message)
{
if (m_streams.find(message.deviceStream()) == m_streams.end()) {
qWarning() << "Server received message to non-existing stream" << message.deviceStream();
@@ -216,3 +224,18 @@ void Server::closeStream(StreamId id)
// Closes are not acknowledged
}
+void Server::checkVersion(const QdbMessage &message)
+{
+ Q_ASSERT(message.command() == QdbMessage::Connect);
+ Q_ASSERT(message.data().size() == sizeof(qdbProtocolVersion));
+
+ QDataStream dataStream{message.data()};
+ uint32_t protocolVersion;
+ dataStream >> protocolVersion;
+
+ if (protocolVersion != qdbProtocolVersion) {
+ qWarning() << "Protocol version" << protocolVersion << "requested, but only version"
+ << qdbProtocolVersion << "is known";
+ }
+}
+
diff --git a/qdbd/server.h b/qdbd/server.h
index 9c963f9..6f5d36a 100644
--- a/qdbd/server.h
+++ b/qdbd/server.h
@@ -54,8 +54,9 @@ private:
void processQueue();
void handleOpen(StreamId hostId, const QByteArray &tag);
void resetServer(bool hostConnected);
- void handleWrite(QdbMessage message);
+ void handleWrite(const QdbMessage &message);
void closeStream(StreamId id);
+ void checkVersion(const QdbMessage &message);
ServerState m_state;
std::unordered_map<StreamId, std::unique_ptr<Executor>> m_executors;
diff --git a/test/streamtest.cpp b/test/streamtest.cpp
index e47b586..df0c814 100644
--- a/test/streamtest.cpp
+++ b/test/streamtest.cpp
@@ -20,6 +20,7 @@
******************************************************************************/
#include "../utils/make_unique.h"
#include "usb/usbconnection.h"
+#include "protocol/protocol.h"
#include "protocol/qdbmessage.h"
#include "protocol/qdbtransport.h"
#include "protocol/services.h"
@@ -33,6 +34,13 @@ const int testTimeout = 500; // in milliseconds
class TestCase : public QObject
{
Q_OBJECT
+public:
+ TestCase()
+ : m_transport{nullptr}, m_versionBuffer{}, m_phase{0}
+ {
+ QDataStream dataStream{&m_versionBuffer, QIODevice::WriteOnly};
+ dataStream << qdbProtocolVersion;
+ }
public slots:
void run()
{
@@ -51,7 +59,8 @@ signals:
void passed();
protected:
std::unique_ptr<QdbTransport> m_transport;
- int m_phase = 0;
+ QByteArray m_versionBuffer;
+ int m_phase;
};
class OpenWriteCloseEchoTest : public TestCase
@@ -62,13 +71,14 @@ public slots:
{
switch (m_phase) {
case 0: {
- QdbMessage cnxn{QdbMessage::Connect, 0, 0};
+ QdbMessage cnxn{QdbMessage::Connect, 0, 0, m_versionBuffer};
QVERIFY(m_transport->send(cnxn));
break;
}
case 1: {
QdbMessage response = m_transport->receive();
QCOMPARE(response.command(), QdbMessage::Connect);
+ QCOMPARE(response.data(), m_versionBuffer);
QdbMessage open{QdbMessage::Open, m_hostId, 0, tagBuffer(EchoTag)};
QVERIFY(m_transport->send(open));
@@ -129,7 +139,7 @@ public slots:
{
switch (m_phase) {
case 0: {
- QdbMessage connect{QdbMessage::Connect, 0, 0};
+ QdbMessage connect{QdbMessage::Connect, 0, 0, m_versionBuffer};
QVERIFY(m_transport->send(connect));
break;
}
@@ -138,9 +148,9 @@ public slots:
QCOMPARE(response.command(), QdbMessage::Connect);
QCOMPARE(response.hostStream(), 0u);
QCOMPARE(response.deviceStream(), 0u);
- QCOMPARE(response.data(), QByteArray{});
+ QCOMPARE(response.data(), m_versionBuffer);
- QdbMessage connect{QdbMessage::Connect, 0, 0};
+ QdbMessage connect{QdbMessage::Connect, 0, 0, m_versionBuffer};
QVERIFY(m_transport->send(connect));
break;
}
@@ -149,7 +159,37 @@ public slots:
QCOMPARE(response.command(), QdbMessage::Connect);
QCOMPARE(response.hostStream(), 0u);
QCOMPARE(response.deviceStream(), 0u);
- QCOMPARE(response.data(), QByteArray{});
+ QCOMPARE(response.data(), m_versionBuffer);
+
+ emit passed();
+ break;
+ }
+ }
+ ++m_phase;
+ }
+};
+
+class ConnectWithUnsupportedVersionTest : public TestCase
+{
+ Q_OBJECT
+public slots:
+ void testPhases() override
+ {
+ switch (m_phase) {
+ case 0: {
+ QByteArray unsupported{};
+ QDataStream dataStream{&unsupported, QIODevice::WriteOnly};
+ dataStream << (qdbProtocolVersion + 1);
+ QdbMessage connect{QdbMessage::Connect, 0, 0, unsupported};
+ QVERIFY(m_transport->send(connect));
+ break;
+ }
+ case 1: {
+ QdbMessage response = m_transport->receive();
+ QCOMPARE(response.command(), QdbMessage::Connect);
+ QCOMPARE(response.hostStream(), 0u);
+ QCOMPARE(response.deviceStream(), 0u);
+ QCOMPARE(response.data(), m_versionBuffer);
emit passed();
break;
@@ -227,7 +267,7 @@ public slots:
{
switch (m_phase) {
case 0: {
- QdbMessage connect{QdbMessage::Connect, 0, 0};
+ QdbMessage connect{QdbMessage::Connect, 0, 0, m_versionBuffer};
QVERIFY(m_transport->send(connect));
break;
}
@@ -236,7 +276,7 @@ public slots:
QCOMPARE(response.command(), QdbMessage::Connect);
QCOMPARE(response.hostStream(), 0u);
QCOMPARE(response.deviceStream(), 0u);
- QCOMPARE(response.data(), QByteArray{});
+ QCOMPARE(response.data(), m_versionBuffer);
// Try to directly write to an unopened stream
QdbMessage write{QdbMessage::Write, m_hostId, m_deviceId};
@@ -297,7 +337,7 @@ public slots:
{
switch (m_phase) {
case 0: {
- QdbMessage cnxn{QdbMessage::Connect, 0, 0};
+ QdbMessage cnxn{QdbMessage::Connect, 0, 0, m_versionBuffer};
QVERIFY(m_transport->send(cnxn));
break;
}
@@ -452,6 +492,12 @@ private slots:
testCase(&test);
}
+ void connectWithUnsupportedVersion()
+ {
+ ConnectWithUnsupportedVersionTest test;
+ testCase(&test);
+ }
+
void writeToNonexistentStream()
{
WriteToNonExistentStreamTest test;