From a2fa7c6f4bcec25e99db93e64487356769448c42 Mon Sep 17 00:00:00 2001 From: Tobias Blomberg Date: Sun, 20 Oct 2019 14:06:23 +0200 Subject: [PATCH] The reflector server can now handle newer clients The reflector server now have a mechanism to handle clients using a newer protocol version than the server supports. If a client upon connect indicates a protocol version newer than what the server can handle it will ask the client to downgrade its protocol version. It is up to the client to choose wether it can handle the downgrade or not. --- src/svxlink/reflector/ReflectorClient.cpp | 35 ++++++---- src/svxlink/reflector/ReflectorMsg.h | 85 ++++++++++++++++------- src/svxlink/svxlink/ReflectorLogic.cpp | 20 ++++++ src/svxlink/svxlink/ReflectorLogic.h | 1 + src/versions | 2 +- 5 files changed, 104 insertions(+), 39 deletions(-) diff --git a/src/svxlink/reflector/ReflectorClient.cpp b/src/svxlink/reflector/ReflectorClient.cpp index 354b0611..ea2cc06a 100644 --- a/src/svxlink/reflector/ReflectorClient.cpp +++ b/src/svxlink/reflector/ReflectorClient.cpp @@ -357,24 +357,35 @@ void ReflectorClient::handleMsgProtoVer(std::istream& is) MsgProtoVer msg; if (!msg.unpack(is)) { - cout << "Client " << m_con->remoteHost() << ":" << m_con->remotePort() - << " ERROR: Could not unpack MsgProtoVer\n"; + std::cout << "Client " << m_con->remoteHost() << ":" << m_con->remotePort() + << " ERROR: Could not unpack MsgProtoVer\n"; sendError("Illegal MsgProtoVer protocol message received"); return; } m_client_proto_ver.set(msg.majorVer(), msg.minorVer()); - ProtoVerRange valid_proto_ver_range( - ProtoVer(MIN_MAJOR_VER, MIN_MINOR_VER), - ProtoVer(MsgProtoVer::MAJOR, MsgProtoVer::MINOR)); - if (!valid_proto_ver_range.isWithinRange(m_client_proto_ver)) + ProtoVer max_proto_ver(MsgProtoVer::MAJOR, MsgProtoVer::MINOR); + if (m_client_proto_ver > max_proto_ver) { - cout << "Client " << m_con->remoteHost() << ":" << m_con->remotePort() - << " Incompatible protocol version: " - << msg.majorVer() << "." << msg.minorVer() << ". Should be " - << MsgProtoVer::MAJOR << "." << MsgProtoVer::MINOR << "." << endl; - stringstream ss; + std::cout << "Client " << m_con->remoteHost() << ":" << m_con->remotePort() + << " use protocol version " + << msg.majorVer() << "." << msg.minorVer() + << " which is newer than we can handle. Asking for downgrade to " + << MsgProtoVer::MAJOR << "." << MsgProtoVer::MINOR << "." + << std::endl; + sendMsg(MsgProtoVerDowngrade()); + return; + } + else if (m_client_proto_ver < ProtoVer(MIN_MAJOR_VER, MIN_MINOR_VER)) + { + std::cout << "Client " << m_con->remoteHost() << ":" << m_con->remotePort() + << " is using protocol version " + << msg.majorVer() << "." << msg.minorVer() + << " which is too old. Must at least be version " + << MIN_MAJOR_VER << "." << MIN_MINOR_VER << "." << std::endl; + std::ostringstream ss; ss << "Unsupported protocol version " << msg.majorVer() << "." - << msg.minorVer(); + << msg.minorVer() << ". Must be at least " + << MIN_MAJOR_VER << "." << MIN_MINOR_VER << "."; sendError(ss.str()); return; } diff --git a/src/svxlink/reflector/ReflectorMsg.h b/src/svxlink/reflector/ReflectorMsg.h index 3f919c44..d544e2ae 100644 --- a/src/svxlink/reflector/ReflectorMsg.h +++ b/src/svxlink/reflector/ReflectorMsg.h @@ -224,32 +224,6 @@ class ReflectorUdpMsgBase : public ReflectorUdpMsg /************************** Administrative Messages **************************/ -/** -@brief Protocol version TCP network message -@author Tobias Blomberg / SM0SVX -@date 2017-02-12 - -This is the first message exchanged between the client and the server. It tells -the server what protocol version that the client supports. If the client use a -protocol version that the server does not support, the client is denied access. -*/ -class MsgProtoVer : public ReflectorMsgBase<5> -{ - public: - static const uint16_t MAJOR = 2; - static const uint16_t MINOR = 0; - MsgProtoVer(void) : m_major(MAJOR), m_minor(MINOR) {} - uint16_t majorVer(void) const { return m_major; } - uint16_t minorVer(void) const { return m_minor; } - - ASYNC_MSG_MEMBERS(m_major, m_minor); - - private: - uint16_t m_major; - uint16_t m_minor; -}; /* MsgProtoVer */ - - /** @brief Heartbeat TCP network message @author Tobias Blomberg / SM0SVX @@ -265,6 +239,65 @@ class MsgHeartbeat : public ReflectorMsgBase<1> }; /* MsgHeartbeat */ +/** +@brief Protocol version TCP network message +@author Tobias Blomberg / SM0SVX +@date 2017-02-12 + +This is the first message exchanged between the client and the server. It is +sent by the client to tell the server what protocol version that the client +supports. If the client use a protocol version that the server does not +support, the client is denied access. Alternatively, if the client protocol +version is larger than what the server supports, the server may send a +MsgProtoVerDowngrade message to ask the client to use an older version of the +protocol. +*/ +class MsgProtoVer : public ReflectorMsgBase<5> +{ + public: + static const uint16_t MAJOR = 2; + static const uint16_t MINOR = 0; + MsgProtoVer(void) : m_major(MAJOR), m_minor(MINOR) {} + MsgProtoVer(uint16_t major, uint16_t minor) + : m_major(major), m_minor(minor) {} + uint16_t majorVer(void) const { return m_major; } + uint16_t minorVer(void) const { return m_minor; } + + ASYNC_MSG_MEMBERS(m_major, m_minor); + + private: + uint16_t m_major; + uint16_t m_minor; +}; /* MsgProtoVer */ + + +/** +@brief Protocol version downgrade request +@author Tobias Blomberg / SM0SVX +@date 2019-10-19 + +This message is sent by the reflector server to a client that announces a newer +protocol version than the server is able to support. The client should resend +the MsgProtoVer message set to a version number no larger than what the server +indicates in this message. The client must then use only protocol messages +compatible with the lower protocol version. +*/ +class MsgProtoVerDowngrade : public ReflectorMsgBase<6> +{ + public: + MsgProtoVerDowngrade(void) + : m_major(MsgProtoVer::MAJOR), m_minor(MsgProtoVer::MINOR) {} + uint16_t majorVer(void) const { return m_major; } + uint16_t minorVer(void) const { return m_minor; } + + ASYNC_MSG_MEMBERS(m_major, m_minor); + + private: + uint16_t m_major; + uint16_t m_minor; +}; /* MsgProtoVerDowngrade */ + + /** @brief Authentication challenge TCP network message @author Tobias Blomberg / SM0SVX diff --git a/src/svxlink/svxlink/ReflectorLogic.cpp b/src/svxlink/svxlink/ReflectorLogic.cpp index 2d401f32..dbc563d7 100644 --- a/src/svxlink/svxlink/ReflectorLogic.cpp +++ b/src/svxlink/svxlink/ReflectorLogic.cpp @@ -657,6 +657,9 @@ void ReflectorLogic::onFrameReceived(FramedTcpConnection *con, case MsgError::TYPE: handleMsgError(ss); break; + case MsgProtoVerDowngrade::TYPE: + handleMsgProtoVerDowngrade(ss); + break; case MsgAuthChallenge::TYPE: handleMsgAuthChallenge(ss); break; @@ -711,6 +714,23 @@ void ReflectorLogic::handleMsgError(std::istream& is) } /* ReflectorLogic::handleMsgError */ +void ReflectorLogic::handleMsgProtoVerDowngrade(std::istream& is) +{ + MsgProtoVerDowngrade msg; + if (!msg.unpack(is)) + { + cerr << "*** ERROR[" << name() << "]: Could not unpack MsgProtoVerDowngrade" << endl; + disconnect(); + return; + } + cout << name() << ": Server too old and we cannot downgrade to protocol version " + << msg.majorVer() << "." << msg.minorVer() << " from " + << MsgProtoVer::MAJOR << "." << MsgProtoVer::MINOR + << endl; + disconnect(); +} /* ReflectorLogic::handleMsgProtoVerDowngrade */ + + void ReflectorLogic::handleMsgAuthChallenge(std::istream& is) { if (m_con_state != STATE_EXPECT_AUTH_CHALLENGE) diff --git a/src/svxlink/svxlink/ReflectorLogic.h b/src/svxlink/svxlink/ReflectorLogic.h index f42e6fd5..26ab52f8 100644 --- a/src/svxlink/svxlink/ReflectorLogic.h +++ b/src/svxlink/svxlink/ReflectorLogic.h @@ -253,6 +253,7 @@ class ReflectorLogic : public LogicBase void onFrameReceived(Async::FramedTcpConnection *con, std::vector& data); void handleMsgError(std::istream& is); + void handleMsgProtoVerDowngrade(std::istream& is); void handleMsgAuthChallenge(std::istream& is); void handleMsgNodeList(std::istream& is); void handleMsgNodeJoined(std::istream& is); diff --git a/src/versions b/src/versions index a6f0485c..aa8f2c36 100644 --- a/src/versions +++ b/src/versions @@ -11,7 +11,7 @@ LIBECHOLIB=1.3.3 LIBASYNC=1.6.0.99.3-reflector_tg # SvxLink versions -SVXLINK=1.7.99.10-reflector_tg +SVXLINK=1.7.99.11-reflector_tg MODULE_HELP=1.0.0 MODULE_PARROT=1.1.1 MODULE_ECHO_LINK=1.5.0