[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-4' - 4 commits - common/Util.cpp common/Util.hpp loleaflet/html loleaflet/src net/WebSocketHandler.hpp test/test.cpp wsd/Admin.cpp wsd/ClientSession.cpp wsd/DocumentBroker.cpp wsd/LOOLWSD.cpp wsd/LOOLWSD.hpp
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Fri May 17 10:59:41 UTC 2019
common/Util.cpp | 10 +
common/Util.hpp | 3
loleaflet/html/loleaflet.html.m4 | 2
loleaflet/src/core/Socket.js | 9 -
net/WebSocketHandler.hpp | 275 +++++++++++++++++++++++++--------------
test/test.cpp | 39 ++---
wsd/Admin.cpp | 7
wsd/ClientSession.cpp | 8 -
wsd/DocumentBroker.cpp | 3
wsd/LOOLWSD.cpp | 15 +-
wsd/LOOLWSD.hpp | 3
11 files changed, 248 insertions(+), 126 deletions(-)
New commits:
commit 994669aedbe131e3386110210b6863988c74fa5c
Author: Gabriel Masei <gabriel.masei at 1and1.ro>
AuthorDate: Fri Mar 8 10:21:17 2019 +0200
Commit: Michael Meeks <michael.meeks at collabora.com>
CommitDate: Fri May 17 11:44:38 2019 +0100
Added support for defragmentation of incoming websocket fragmented messages and handled some protocol error cases
Change-Id: I4d11a6527b6b131c65101fd53b71015529645f74
Reviewed-on: https://gerrit.libreoffice.org/68901
Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
Tested-by: Michael Meeks <michael.meeks at collabora.com>
diff --git a/net/WebSocketHandler.hpp b/net/WebSocketHandler.hpp
index 3b65ee89a..b4c14ede6 100644
--- a/net/WebSocketHandler.hpp
+++ b/net/WebSocketHandler.hpp
@@ -37,6 +37,8 @@ private:
std::atomic<bool> _shuttingDown;
bool _isClient;
bool _isMasking;
+ bool _inFragmentBlock;
+ bool _isManualDefrag;
protected:
struct WSFrameMask
@@ -50,16 +52,29 @@ protected:
public:
/// Perform upgrade ourselves, or select a client web socket.
- WebSocketHandler(bool isClient = false, bool isMasking = true) :
+ /// Parameters:
+ /// isClient: the instance should behave like a client (true) or like a server (false)
+ /// (from websocket perspective)
+ /// isMasking: a client should mask (true) or not (false) outgoing frames
+ /// isManualDefrag: the message handler should be called for every fragment of a message and
+ /// defragmentation should be handled inside message handler (true) or the message handler
+ /// should be called after all fragments of a message were received and the message
+ /// was defragmented (false).
+ WebSocketHandler(bool isClient = false, bool isMasking = true, bool isManualDefrag = false) :
_lastPingSentTime(std::chrono::steady_clock::now()),
_pingTimeUs(0),
_shuttingDown(false),
_isClient(isClient),
- _isMasking(isClient && isMasking)
+ _isMasking(isClient && isMasking),
+ _inFragmentBlock(false),
+ _isManualDefrag(isManualDefrag)
{
}
/// Upgrades itself to a websocket directly.
+ /// Parameters:
+ /// socket: the TCP socket which received the upgrade request
+ /// request: the HTTP upgrade request to WebSocket
WebSocketHandler(const std::weak_ptr<StreamSocket>& socket,
const Poco::Net::HTTPRequest& request) :
_socket(socket),
@@ -69,7 +84,9 @@ public:
_pingTimeUs(0),
_shuttingDown(false),
_isClient(false),
- _isMasking(false)
+ _isMasking(false),
+ _inFragmentBlock(false),
+ _isManualDefrag(false)
{
upgradeToWebSocket(request);
}
@@ -99,8 +116,8 @@ public:
RESERVED_TLS_FAILURE = 1015
};
- /// Sends WS shutdown message to the peer.
- void shutdown(const StatusCodes statusCode = StatusCodes::NORMAL_CLOSE, const std::string& statusMessage = "")
+ /// Sends WS Close frame to the peer.
+ void sendCloseFrame(const StatusCodes statusCode = StatusCodes::NORMAL_CLOSE, const std::string& statusMessage = "")
{
std::shared_ptr<StreamSocket> socket = _socket.lock();
if (socket == nullptr)
@@ -126,7 +143,22 @@ public:
#endif
}
- bool handleOneIncomingMessage(const std::shared_ptr<StreamSocket>& socket)
+ void shutdown(const StatusCodes statusCode = StatusCodes::NORMAL_CLOSE, const std::string& statusMessage = "")
+ {
+ if (!_shuttingDown)
+ sendCloseFrame(statusCode, statusMessage);
+ std::shared_ptr<StreamSocket> socket = _socket.lock();
+ if (socket)
+ {
+ socket->closeConnection();
+ socket->getInBuffer().clear();
+ }
+ _wsPayload.clear();
+ _inFragmentBlock = false;
+ _shuttingDown = false;
+ }
+
+ bool handleTCPStream(const std::shared_ptr<StreamSocket>& socket)
{
assert(socket && "Expected a valid socket instance.");
@@ -177,7 +209,7 @@ public:
headerLen += 8;
}
- unsigned char *data, *mask;
+ unsigned char *data, *mask = nullptr;
if (hasMask)
{
@@ -187,121 +219,164 @@ public:
if (payloadLen + headerLen > len)
{ // partial read wait for more data.
- LOG_TRC("#" << socket->getFD() << ": Still incomplete WebSocket message, have " << len
- << " bytes, message is " << payloadLen + headerLen << " bytes");
+ LOG_TRC("#" << socket->getFD() << ": Still incomplete WebSocket frame, have " << len << " bytes, frame is " << payloadLen + headerLen << " bytes");
return false;
}
- LOG_TRC("#" << socket->getFD() << ": Incoming WebSocket data of " << len << " bytes: "
- << Util::stringifyHexLine(socket->getInBuffer(), 0, std::min((size_t)32, len)));
-
- data = p + headerLen;
-
- if (hasMask)
+ if (hasMask && _isClient)
{
- const size_t end = _wsPayload.size();
- _wsPayload.resize(end + payloadLen);
- char* wsData = &_wsPayload[end];
- for (size_t i = 0; i < payloadLen; ++i)
- *wsData++ = data[i] ^ mask[i % 4];
- } else
- _wsPayload.insert(_wsPayload.end(), data, data + payloadLen);
-#else
- unsigned char * const p = reinterpret_cast<unsigned char*>(&socket->getInBuffer()[0]);
- _wsPayload.insert(_wsPayload.end(), p, p + len);
- const size_t headerLen = 0;
- const size_t payloadLen = len;
-#endif
-
- assert(_wsPayload.size() >= payloadLen);
+ LOG_ERR("#" << socket->getFD() << ": Servers should not send masked frames. Only clients.");
+ shutdown(StatusCodes::PROTOCOL_ERROR);
+ return true;
+ }
- socket->getInBuffer().erase(socket->getInBuffer().begin(),
- socket->getInBuffer().begin() + headerLen + payloadLen);
+ LOG_TRC("#" << socket->getFD() << ": Incoming WebSocket data of " << len << " bytes: " << Util::stringifyHexLine(socket->getInBuffer(), 0, std::min((size_t)32, len)));
-#if !MOBILEAPP
+ data = p + headerLen;
- // FIXME: fin, aggregating payloads into _wsPayload etc.
- LOG_TRC("#" << socket->getFD() << ": Incoming WebSocket message code "
- << static_cast<unsigned>(code) << ", fin? " << fin << ", mask? " << hasMask
- << ", payload length: " << _wsPayload.size()
- << ", residual socket data: " << socket->getInBuffer().size() << " bytes.");
+ if (isControlFrame(code))
+ {
+ //Process control frames
+ std::vector<char> ctrlPayload;
- bool doClose = false;
+ readPayload(data, payloadLen, mask, ctrlPayload);
+ socket->getInBuffer().erase(socket->getInBuffer().begin(), socket->getInBuffer().begin() + headerLen + payloadLen);
+ LOG_TRC("#" << socket->getFD() << ": Incoming WebSocket frame code " << static_cast<unsigned>(code) <<
+ ", fin? " << fin << ", mask? " << hasMask << ", payload length: " << payloadLen <<
+ ", residual socket data: " << socket->getInBuffer().size() << " bytes.");
- switch (code)
- {
- case WSOpCode::Pong:
- {
- if (_isClient)
+ // All control frames MUST NOT be fragmented and MUST have a payload length of 125 bytes or less
+ if (!fin)
{
- LOG_ERR("#" << socket->getFD() << ": Servers should not send pongs, only clients");
- doClose = true;
- break;
+ LOG_ERR("#" << socket->getFD() << ": A control frame cannot be fragmented.");
+ shutdown(StatusCodes::PROTOCOL_ERROR);
+ return true;
}
- else
+ if (payloadLen > 125)
{
- _pingTimeUs = std::chrono::duration_cast<std::chrono::microseconds>
- (std::chrono::steady_clock::now() - _lastPingSentTime).count();
- LOG_TRC("#" << socket->getFD() << ": Pong received: " << _pingTimeUs << " microseconds");
- break;
+ LOG_ERR("#" << socket->getFD() << ": The payload length of a control frame must not exceed 125 bytes.");
+ shutdown(StatusCodes::PROTOCOL_ERROR);
+ return true;
}
- }
- case WSOpCode::Ping:
- if (_isClient)
+
+ switch (code)
{
- auto now = std::chrono::steady_clock::now();
- _pingTimeUs = std::chrono::duration_cast<std::chrono::microseconds>
- (now - _lastPingSentTime).count();
- sendPong(now, &_wsPayload[0], payloadLen, socket);
+ case WSOpCode::Pong:
+ if (_isClient)
+ {
+ LOG_ERR("#" << socket->getFD() << ": Servers should not send pongs, only clients");
+ shutdown(StatusCodes::POLICY_VIOLATION);
+ return true;
+ }
+ else
+ {
+ _pingTimeUs = std::chrono::duration_cast<std::chrono::microseconds>
+ (std::chrono::steady_clock::now() - _lastPingSentTime).count();
+ LOG_TRC("#" << socket->getFD() << ": Pong received: " << _pingTimeUs << " microseconds");
+ }
+ break;
+ case WSOpCode::Ping:
+ if (_isClient)
+ {
+ auto now = std::chrono::steady_clock::now();
+ _pingTimeUs = std::chrono::duration_cast<std::chrono::microseconds>
+ (now - _lastPingSentTime).count();
+ sendPong(now, &ctrlPayload[0], payloadLen, socket);
+ }
+ else
+ {
+ LOG_ERR("#" << socket->getFD() << ": Clients should not send pings, only servers");
+ shutdown(StatusCodes::POLICY_VIOLATION);
+ return true;
+ }
+ break;
+ case WSOpCode::Close:
+ {
+ std::string message;
+ StatusCodes statusCode = StatusCodes::NORMAL_CLOSE;
+ if (!_shuttingDown)
+ {
+ // Peer-initiated shutdown must be echoed.
+ // Otherwise, this is the echo to _our_ shutdown message, which we should ignore.
+ LOG_TRC("#" << socket->getFD() << ": Peer initiated socket shutdown. Code: " << static_cast<int>(statusCode));
+ if (ctrlPayload.size())
+ {
+ statusCode = static_cast<StatusCodes>((((uint64_t)(unsigned char)ctrlPayload[0]) << 8) +
+ (((uint64_t)(unsigned char)ctrlPayload[1]) << 0));
+ if (ctrlPayload.size() > 2)
+ message.assign(&ctrlPayload[2], &ctrlPayload[2] + ctrlPayload.size() - 2);
+ }
+ }
+ shutdown(statusCode, message);
+ return true;
+ }
+ default:
+ LOG_ERR("#" << socket->getFD() << ": Received unknown control code");
+ shutdown(StatusCodes::PROTOCOL_ERROR);
break;
}
- else
+
+ return true;
+ }
+
+ // Check data frames for errors
+ if (_inFragmentBlock)
+ {
+ if (code != WSOpCode::Continuation)
{
- LOG_ERR("#" << socket->getFD() << ": Clients should not send pings, only servers");
- doClose = true;
+ LOG_ERR("#" << socket->getFD() << ": A fragment that is not the first fragment of a message must have the opcode equal to 0.");
+ shutdown(StatusCodes::PROTOCOL_ERROR);
+ return true;
}
- break;
- case WSOpCode::Close:
- doClose = true;
- break;
- default:
- handleMessage(fin, code, _wsPayload);
- break;
+ }
+ else if (code == WSOpCode::Continuation)
+ {
+ LOG_ERR("#" << socket->getFD() << ": An unfragmented message or the first fragment of a fragmented message must have the opcode different than 0.");
+ shutdown(StatusCodes::PROTOCOL_ERROR);
+ return true;
}
+ //Process data frame
+ readPayload(data, payloadLen, mask, _wsPayload);
#else
- handleMessage(true, WSOpCode::Binary, _wsPayload);
-
+ unsigned char * const p = reinterpret_cast<unsigned char*>(&socket->getInBuffer()[0]);
+ _wsPayload.insert(_wsPayload.end(), p, p + len);
+ const size_t headerLen = 0;
+ const size_t payloadLen = len;
#endif
+ socket->getInBuffer().erase(socket->getInBuffer().begin(), socket->getInBuffer().begin() + headerLen + payloadLen);
+
#if !MOBILEAPP
- if (doClose)
+
+ LOG_TRC("#" << socket->getFD() << ": Incoming WebSocket frame code " << static_cast<unsigned>(code) <<
+ ", fin? " << fin << ", mask? " << hasMask << ", payload length: " << payloadLen <<
+ ", residual socket data: " << socket->getInBuffer().size() << " bytes.");
+
+ if (fin)
+ {
+ //If is final fragment then process the accumulated message.
+ handleMessage(fin, code, _wsPayload);
+ _inFragmentBlock = false;
+ }
+ else
{
- if (!_shuttingDown)
+ if (_isManualDefrag)
{
- // Peer-initiated shutdown must be echoed.
- // Otherwise, this is the echo to _our_ shutdown message, which we should ignore.
- const StatusCodes statusCode = static_cast<StatusCodes>((((uint64_t)(unsigned char)_wsPayload[0]) << 8) +
- (((uint64_t)(unsigned char)_wsPayload[1]) << 0));
- LOG_TRC("#" << socket->getFD() << ": Client initiated socket shutdown. Code: " << static_cast<int>(statusCode));
- if (_wsPayload.size() > 2)
- {
- const std::string message(&_wsPayload[2], &_wsPayload[2] + _wsPayload.size() - 2);
- shutdown(statusCode, message);
- }
- else
- {
- shutdown(statusCode);
- }
+ //If the user wants to process defragmentation on its own then let him process it.
+ handleMessage(fin, code, _wsPayload);
+ _inFragmentBlock = true;
}
else
{
- LOG_TRC("#" << socket->getFD() << ": Client responded to our shutdown.");
+ _inFragmentBlock = true;
+ //If is not final fragment then wait for next fragment.
+ return false;
}
-
- // TCP Close.
- socket->closeConnection();
}
+#else
+ handleMessage(true, WSOpCode::Binary, _wsPayload);
+
#endif
_wsPayload.clear();
@@ -332,7 +407,7 @@ public:
#endif
else
{
- while (handleOneIncomingMessage(socket))
+ while (handleTCPStream(socket))
; // might have multiple messages in the accumulated buffer.
}
}
@@ -516,6 +591,22 @@ private:
protected:
+ bool isControlFrame(WSOpCode code){ return code >= WSOpCode::Close; }
+
+ void readPayload(unsigned char *data, size_t dataLen, unsigned char* mask, std::vector<char>& payload)
+ {
+ if (mask)
+ {
+ size_t end = payload.size();
+ payload.resize(end + dataLen);
+ char* wsData = &payload[end];
+ for (size_t i = 0; i < dataLen; ++i)
+ *wsData++ = data[i] ^ mask[i % 4];
+ }
+ else
+ payload.insert(payload.end(), data, data + dataLen);
+ }
+
/// To be overriden to handle the websocket messages the way you need.
virtual void handleMessage(bool /*fin*/, WSOpCode /*code*/, std::vector<char> &/*data*/)
{
commit 204de0e1120360af0451dcac83159cc8490073e2
Author: Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Thu May 16 21:12:20 2019 +0100
Commit: Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu May 16 21:12:20 2019 +0100
debug: show WebSocketURI & a unique host id in help -> about.
Rather useful for debugging clustering issues.
Change-Id: I6d5f224bf8a3e4034c419137c8ad2b17fdf265ed
diff --git a/common/Util.cpp b/common/Util.cpp
index b0af5c6c6..6f2322c8f 100644
--- a/common/Util.cpp
+++ b/common/Util.cpp
@@ -44,6 +44,7 @@
#include <thread>
#include <Poco/Base64Encoder.h>
+#include <Poco/HexBinaryEncoder.h>
#include <Poco/ConsoleChannel.h>
#include <Poco/Exception.h>
#include <Poco/Format.h>
@@ -100,6 +101,15 @@ namespace Util
return v;
}
+ /// Generate a string of random characters.
+ std::string getHexString(const size_t length)
+ {
+ std::stringstream ss;
+ Poco::HexBinaryEncoder hex(ss);
+ hex.write(getBytes(length).data(), length);
+ return ss.str().substr(0, length);
+ }
+
/// Generates a random string in Base64.
/// Note: May contain '/' characters.
std::string getB64String(const size_t length)
diff --git a/common/Util.hpp b/common/Util.hpp
index a92f0c0cc..96e61d4e9 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -46,6 +46,9 @@ namespace Util
/// Generate an array of random characters.
std::vector<char> getBytes(const size_t length);
+ /// Generate a string of random characters.
+ std::string getHexString(const size_t length);
+
/// Generates a random string suitable for
/// file/directory names.
std::string getFilename(const size_t length);
diff --git a/loleaflet/html/loleaflet.html.m4 b/loleaflet/html/loleaflet.html.m4
index 367ed3fe6..1a44c00b6 100644
--- a/loleaflet/html/loleaflet.html.m4
+++ b/loleaflet/html/loleaflet.html.m4
@@ -156,6 +156,8 @@ ifelse(MOBILEAPP,[true],
<div id="loolwsd-version"></div>
<h3>LOKit</h3>
<div id="lokit-version"></div>
+ <h3>Id</h3>
+ <div id="loolwsd-id"></div>
<p>Copyright _YEAR_, Collabora Productivity Limited.</p>
</div>
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index 275ea8720..c57d0b691 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -50,6 +50,10 @@ L.Socket = L.Class.extend({
this._msgQueue = [];
},
+ getWebSocketBaseURI: function(map) {
+ return map.options.server + map.options.serviceRoot + '/lool/' + encodeURIComponent(map.options.doc + '?' + $.param(map.options.docParams)) + '/ws';
+ },
+
connect: function(socket) {
var map = this._map;
if (map.options.permission) {
@@ -70,8 +74,7 @@ L.Socket = L.Class.extend({
}
try {
- var websocketURI = map.options.server + map.options.serviceRoot + '/lool/' + encodeURIComponent(map.options.doc + '?' + $.param(map.options.docParams)) + '/ws' + wopiSrc;
- this.socket = new WebSocket(websocketURI);
+ this.socket = new WebSocket(this.getWebSocketBaseURI(map) + wopiSrc);
} catch (e) {
// On IE 11 there is a limitation on the number of WebSockets open to a single domain (6 by default and can go to 128).
// Detect this and hint the user.
@@ -284,6 +287,8 @@ L.Socket = L.Class.extend({
$('#loolwsd-version').text(loolwsdVersionObj.Version);
}
+ $('#loolwsd-id').html('<p>' + this.getWebSocketBaseURI(this._map) + '</p><p>' + loolwsdVersionObj.Id + '</p>');
+
// TODO: For now we expect perfect match in protocol versions
if (loolwsdVersionObj.Protocol !== this.ProtocolVersionNumber) {
this._map.fire('error', {msg: _('Unsupported server version.')});
diff --git a/wsd/Admin.cpp b/wsd/Admin.cpp
index 414427027..6dd699b09 100644
--- a/wsd/Admin.cpp
+++ b/wsd/Admin.cpp
@@ -122,12 +122,7 @@ void AdminSocketHandler::handleMessage(bool /* fin */, WSOpCode /* code */,
else if (tokens[0] == "version")
{
// Send LOOL version information
- std::string version, hash;
- Util::getVersionInfo(version, hash);
- std::string versionStr =
- "{ \"Version\": \"" + version + "\", " +
- "\"Hash\": \"" + hash + "\" }";
- sendTextFrame("loolserver " + versionStr);
+ sendTextFrame("loolserver " + LOOLWSD::getVersionJSON());
// Send LOKit version information
sendTextFrame("lokitversion " + LOOLWSD::LOKitVersion);
}
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index 3ba3580e7..f1ae9e897 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -112,13 +112,7 @@ bool ClientSession::_handleInput(const char *buffer, int length)
}
// Send LOOL version information
- std::string version, hash;
- Util::getVersionInfo(version, hash);
- std::string versionStr =
- "{ \"Version\": \"" + version + "\", " +
- "\"Hash\": \"" + hash + "\", " +
- "\"Protocol\": \"" + GetProtocolVersion() + "\" }";
- sendTextFrame("loolserver " + versionStr);
+ sendTextFrame("loolserver " + LOOLWSD::getVersionJSON());
// Send LOKit version information
sendTextFrame("lokitversion " + LOOLWSD::LOKitVersion);
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index f355e6b7b..9bdd7d434 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -686,6 +686,7 @@ std::string LOOLWSD::ServerName;
std::string LOOLWSD::FileServerRoot;
std::string LOOLWSD::ServiceRoot;
std::string LOOLWSD::LOKitVersion;
+std::string LOOLWSD::HostIdentifier;
std::string LOOLWSD::ConfigFile = LOOLWSD_CONFIGDIR "/loolwsd.xml";
std::string LOOLWSD::ConfigDir = LOOLWSD_CONFIGDIR "/conf.d";
std::string LOOLWSD::LogLevel = "trace";
@@ -3085,6 +3086,17 @@ private:
}
};
+std::string LOOLWSD::getVersionJSON()
+{
+ std::string version, hash;
+ Util::getVersionInfo(version, hash);
+ return
+ "{ \"Version\": \"" + version + "\", "
+ "\"Hash\": \"" + hash + "\", "
+ "\"Protocol\": \"" + GetProtocolVersion() + "\", "
+ "\"Id\": \"" + HostIdentifier + "\" }";
+}
+
static LOOLWSDServer srv;
int LOOLWSD::innerMain()
@@ -3100,11 +3112,12 @@ int LOOLWSD::innerMain()
Environment::set("LD_BIND_NOW", "1");
#if !MOBILEAPP
+ HostIdentifier = Util::rng::getHexString(8);
if (DisplayVersion)
{
std::string version, hash;
Util::getVersionInfo(version, hash);
- LOG_INF("Loolwsd version details: " << version << " - " << hash);
+ LOG_INF("Loolwsd version details: " << version << " - " << hash << " - id " << HostIdentifier);
}
#endif
#endif
diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp
index ce5f8d172..7cb03920f 100644
--- a/wsd/LOOLWSD.hpp
+++ b/wsd/LOOLWSD.hpp
@@ -63,6 +63,7 @@ public:
static std::string FileServerRoot;
static std::string ServiceRoot; ///< There are installations that need prefixing every page with some path.
static std::string LOKitVersion;
+ static std::string HostIdentifier; ///< A unique random hash that identifies this server
static std::string LogLevel;
static bool AnonymizeUserData;
static std::uint64_t AnonymizationSalt;
@@ -152,6 +153,8 @@ public:
return AnonymizeUserData ? Util::anonymize(username, AnonymizationSalt) : username;
}
+ static std::string getVersionJSON();
+
int innerMain();
protected:
commit b108a8997a01099a4120c6c5c3f01c61b086cebf
Author: Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Thu May 16 20:38:36 2019 +0100
Commit: Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu May 16 20:38:36 2019 +0100
debug: dump content of paste messages.
Problematic not to be able to see the content, helps hunt weirdness
in eg. pasted RTF.
Change-Id: I301bfe040a2424b6ca84ab94b8eee865439fb680
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 744d4ec87..d33337cc1 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -1738,6 +1738,9 @@ bool DocumentBroker::forwardToChild(const std::string& viewId, const std::string
LOG_TRC("Forwarding payload to child [" << viewId << "]: " << getAbbreviatedMessage(message));
+ if (Log::traceEnabled() && Util::startsWith(message, "paste "))
+ LOG_TRC("Logging paste payload (" << message.size() << " bytes) '" << message << "' end paste");
+
std::string msg = "child-" + viewId + ' ' + message;
const auto it = _sessions.find(viewId);
commit 1fb87c20a3ddb672c113524fb8e15dfdf47d344c
Author: Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Mon May 13 15:39:14 2019 +0100
Commit: Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu May 16 14:49:41 2019 +0100
test: use process groups as well to allow concurrent make checks.
Change-Id: Ib1a55f53c51835a8f9fb1c17146f30e887103906
diff --git a/test/test.cpp b/test/test.cpp
index 9745dda00..4f90ee1b5 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -164,11 +164,14 @@ bool runClientTests(bool standalone, bool verbose)
// Versions assuming a single user, on a single machine
#ifndef UNIT_CLIENT_TESTS
-std::vector<int> getProcPids(const char* exec_filename, bool ignoreZombies = true)
+std::vector<int> getProcPids(const char* exec_filename)
{
std::vector<int> pids;
- // Crash all lokit processes.
+ // Ensure we're in the same group.
+ int grp = getpgrp();
+
+ // Get all lokit processes.
for (auto it = Poco::DirectoryIterator(std::string("/proc")); it != Poco::DirectoryIterator(); ++it)
{
try
@@ -192,24 +195,24 @@ std::vector<int> getProcPids(const char* exec_filename, bool ignoreZombies = tru
std::string statString;
Poco::StreamCopier::copyToString(stat, statString);
Poco::StringTokenizer tokens(statString, " ");
- if (tokens.count() > 3 && tokens[1] == exec_filename)
+ if (tokens.count() > 6 && tokens[1] == exec_filename)
{
- if (ignoreZombies)
+ // We could have several make checks running at once.
+ int kidGrp = std::atoi(tokens[4].c_str());
+ if (kidGrp != grp)
+ continue;
+
+ switch (tokens[2].c_str()[0])
{
- switch (tokens[2].c_str()[0])
- {
- // Dead & zombie markers for old and new kernels.
- case 'x':
- case 'X':
- case 'Z':
- break;
- default:
- pids.push_back(pid);
- break;
- }
- }
- else
+ // Dead & zombie markers for old and new kernels.
+ case 'x':
+ case 'X':
+ case 'Z':
+ break;
+ default:
pids.push_back(pid);
+ break;
+ }
}
}
}
@@ -231,7 +234,7 @@ std::vector<int> getKitPids()
int getLoolKitProcessCount()
{
- return getProcPids("(loolkit)", true).size();
+ return getProcPids("(loolkit)").size();
}
std::vector<int> getForKitPids()
More information about the Libreoffice-commits
mailing list