/* * Deskflow -- mouse and keyboard sharing utility * * SPDX-FileCopyrightText: Copyright (C) 2024 Symless Ltd. * SPDX-License-Identifier: GPL-2.0 */ #include "HelloBack.h" #include "base/Log.h" #include "deskflow/ProtocolUtil.h" #include "deskflow/protocol_types.h" #include #include namespace deskflow::client { // // HelloBack::Deps // void HelloBack::Deps::invalidHello() { m_invalidHello(); } void HelloBack::Deps::incompatible(int major, int minor) { m_incompatible(major, minor); } // // HelloBack // void HelloBack::handleHello(deskflow::IStream *stream, const std::string &clientName) const { SInt16 serverMajor; SInt16 serverMinor; // as luck would have it, both "Synergy" and "Barrier" are 7 chars, // so we eat 7 chars and then test for either protocol name. // we cannot re-use `readf` to check for various hello messages, // as `readf` eats bytes (advances the stream position reference). std::string protocolName; ProtocolUtil::readf(stream, kMsgHello, &protocolName, &serverMajor, &serverMinor); if (protocolName != kSynergyProtocolName && protocolName != kBarrierProtocolName) { m_deps->invalidHello(); return; } // check versions LOG_DEBUG("got hello version %s, %d.%d", protocolName.c_str(), serverMajor, serverMinor); const auto helloBackMajor = m_majorVersion; auto helloBackMinor = m_minorVersion; if (shouldDowngrade(serverMajor, serverMinor)) { LOG_NOTE("downgrading to %d.%d protocol for server", serverMajor, serverMinor); helloBackMinor = serverMinor; } else if (serverMajor < m_majorVersion || (serverMajor == m_majorVersion && serverMinor < m_minorVersion)) { m_deps->incompatible(serverMajor, serverMinor); return; } // say hello back with same protocol name and version LOG_DEBUG( "saying hello back with version %s %d.%d", // protocolName.c_str(), helloBackMajor, helloBackMinor ); // dynamically build write format for hello back since `ProtocolUtil::writef` // doesn't support formatting fixed length strings yet. std::string helloBackMessage = protocolName + kMsgHelloBackArgs; ProtocolUtil::writef(stream, helloBackMessage.c_str(), helloBackMajor, helloBackMinor, &clientName); } bool HelloBack::shouldDowngrade(int major, int minor) const { const std::map> map{ // 1.6 is compatible with 1.7 and 1.8 {6, {7, 8}}, // 1.7 is compatible with 1.8 {7, {8}}, }; if (major == m_majorVersion) { auto versions = map.find(minor); if (versions != map.end()) { auto compatibleVersions = versions->second; if (compatibleVersions.find(m_minorVersion) != compatibleVersions.end()) { return true; } } } return false; } } // namespace deskflow::client