loleaflet/src/core/Socket.js | 18 +++++++++++++++++- loolwsd/LOOLProtocol.cpp | 21 +++++++++++++++++++++ loolwsd/LOOLProtocol.hpp | 16 ++++++++++++++++ loolwsd/LoadTest.cpp | 16 ++++++++++++++++ loolwsd/MasterProcessSession.cpp | 14 ++++++++++++++ loolwsd/protocol.txt | 20 ++++++++++++++++++++ 6 files changed, 104 insertions(+), 1 deletion(-)
New commits: commit 2d385d697e2bced5a23c75aa5bcda43cafc33e61 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Wed Jan 6 12:00:44 2016 -0500 Protocol versioning added and documented Change-Id: I6e1df89c7330052bd2d442a42c0b24c8ae4facf6 Reviewed-on: https://gerrit.libreoffice.org/21168 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js index e8d34ef..eaf73a4 100644 --- a/loleaflet/src/core/Socket.js +++ b/loleaflet/src/core/Socket.js @@ -3,6 +3,8 @@ */ L.Socket = { + ProtocolVersionNumber: '0.1', + connect: function (map) { try { this.socket = new WebSocket(map.options.server); @@ -44,6 +46,10 @@ L.Socket = { }, _onOpen: function () { + // Always send the protocol version number. + // TODO: Move the version number somewhere sensible. + this.socket.send('loolclient ' + this.ProtocolVersionNumber); + var msg = 'load url=' + this._map.options.doc; if (this._map._docLayer) { // we are reconnecting after a lost connection @@ -85,7 +91,17 @@ L.Socket = { textMsg = String.fromCharCode.apply(null, imgBytes.subarray(0, index)); } - if (!textMsg.startsWith('tile:') && !textMsg.startsWith('renderfont:')) { + if (textMsg.startsWith('loolserver ')) { + // This must be the first message. + if (this._map._docLayer) { + this.fire('error', {msg: 'Unexpected loolserver message.'}); + } + // TODO: For now we expect perfect match. + if (textMsg.substring(11) !== this.ProtocolVersionNumber) { + this.fire('error', {msg: 'Unsupported server version.'}); + } + } + else if (!textMsg.startsWith('tile:') && !textMsg.startsWith('renderfont:')) { // log the tile msg separately as we need the tile coordinates L.Log.log(textMsg, L.INCOMING); if (imgBytes !== undefined) { diff --git a/loolwsd/LOOLProtocol.cpp b/loolwsd/LOOLProtocol.cpp index c831abc..0d358c2 100644 --- a/loolwsd/LOOLProtocol.cpp +++ b/loolwsd/LOOLProtocol.cpp @@ -23,6 +23,27 @@ using Poco::StringTokenizer; namespace LOOLProtocol { + std::tuple<signed, signed, std::string> ParseVersion(const std::string& version) + { + signed major = -1; + signed minor = -1; + std::string patch; + + StringTokenizer firstTokens(version, ".", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); + if (firstTokens.count() > 0) + { + major = std::stoi(firstTokens[0]); + + StringTokenizer secondTokens(firstTokens[1], "-", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); + minor = std::stoi(secondTokens[0]); + + if (secondTokens.count() > 1) + patch = secondTokens[1]; + } + + return std::make_tuple(major, minor, patch); + } + bool getTokenInteger(const std::string& token, const std::string& name, int& value) { size_t nextIdx; diff --git a/loolwsd/LOOLProtocol.hpp b/loolwsd/LOOLProtocol.hpp index 42e82df..1478713 100644 --- a/loolwsd/LOOLProtocol.hpp +++ b/loolwsd/LOOLProtocol.hpp @@ -62,6 +62,22 @@ namespace LOOLProtocol TILE, }; + // Protocol Version Number. + // See protocol.txt. + constexpr unsigned ProtocolMajorVersionNumber = 0; + constexpr unsigned ProtocolMinorVersionNumber = 1; + + inline + std::string GetProtocolVersion() + { + return std::to_string(ProtocolMajorVersionNumber) + '.' + + std::to_string(ProtocolMinorVersionNumber); + } + + // Parse a string into a version tuple. + // Negative numbers for error. + std::tuple<signed, signed, std::string> ParseVersion(const std::string& version); + bool getTokenInteger(const std::string& token, const std::string& name, int& value); bool getTokenString(const std::string& token, const std::string& name, std::string& value); bool getTokenKeyword(const std::string& token, const std::string& name, const std::map<std::string, int>& map, int& value); diff --git a/loolwsd/LoadTest.cpp b/loolwsd/LoadTest.cpp index 4fdc245..aaa2e3e 100644 --- a/loolwsd/LoadTest.cpp +++ b/loolwsd/LoadTest.cpp @@ -115,6 +115,20 @@ public: #endif response = getFirstLine(buffer, n); } + else if (tokens[0] == "loolclient") + { + const auto versionTuple = ParseVersion(tokens[1]); + if (std::get<0>(versionTuple) != ProtocolMajorVersionNumber || + std::get<1>(versionTuple) != ProtocolMinorVersionNumber) + { + const std::string error = "error: cmd=loolclient kind=badversion"; + _ws.sendFrame(error.c_str(), error.size()); + break; + } + + const auto version = "loolserver " + GetProtocolVersion(); + _ws.sendFrame(version.c_str(), version.size()); + } if (response.find("status:") == 0) { parseStatus(response, _type, _numParts, _currentPart, _width, _height); @@ -203,6 +217,8 @@ private: thread.start(output); + sendTextFrame(ws, "loolclient " + GetProtocolVersion()); + if (document[0] == '/') sendTextFrame(ws, "load " + document); else diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp index dd66fc2..704b93a 100644 --- a/loolwsd/MasterProcessSession.cpp +++ b/loolwsd/MasterProcessSession.cpp @@ -81,6 +81,20 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length) const std::string firstLine = getFirstLine(buffer, length); StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); + if (tokens[0] == "loolclient") + { + const auto versionTuple = ParseVersion(tokens[1]); + if (std::get<0>(versionTuple) != ProtocolMajorVersionNumber || + std::get<1>(versionTuple) != ProtocolMinorVersionNumber) + { + sendTextFrame("error: cmd=loolclient kind=badversion"); + return false; + } + + sendTextFrame("loolserver " + GetProtocolVersion()); + return true; + } + if (haveSeparateProcess()) { // Note that this handles both forwarding requests from the client to the child process, and diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt index e9cce86..81a069b 100644 --- a/loolwsd/protocol.txt +++ b/loolwsd/protocol.txt @@ -11,6 +11,16 @@ tiles proactively (guessing what the client might need). Etc. client -> server ================ +loolclient <major.minor[-patch]> + + Upon connection, a client must announce the version number it supports. + Major: an integer that must always match between client and server, + otherwise there are no guarantees of any sensible + compatibility. This is bumped when API changes. + Minor: an integer is more flexible and is at the discretion of either party. + Security fixes that do not alter the API would bump the minor version number. + Patch: an optional string that is informational. + canceltiles All outstanding tile messages from the client to the server are @@ -109,6 +119,16 @@ partpagerectangles server -> client ================ +loolserver <major.minor[-patch]> + + Upon connection, the server must announce the version number it supports. + Major: an integer that must always match between client and server, + otherwise there are no guarantees of any sensible + compatibility. This is bumped when API changes. + Minor: an integer is more flexible and is at the discretion of either party. + Security fixes that do not alter the API would bump the minor version number. + Patch: an optional string that is informational. + downloadas: jail=<jail directory> dir=<a tmp dir> name=<name> port=<port> The client should then request http://server:port/jail/dir/name in order to download _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits