[Libreoffice-commits] online.git: loleaflet/src loolwsd/LoadTest.cpp loolwsd/LOOLProtocol.cpp loolwsd/LOOLProtocol.hpp loolwsd/MasterProcessSession.cpp loolwsd/protocol.txt
Ashod Nakashian
ashod.nakashian at collabora.co.uk
Wed Jan 6 09:07:06 PST 2016
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.nakashian at 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 <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at 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
More information about the Libreoffice-commits
mailing list