[Libreoffice-commits] online.git: loolwsd/Admin.cpp loolwsd/Admin.hpp loolwsd/AdminModel.cpp loolwsd/AdminModel.hpp loolwsd/ClientSession.cpp loolwsd/ClientSession.hpp loolwsd/Connect.cpp loolwsd/DocumentBroker.hpp loolwsd/Exceptions.hpp loolwsd/IoUtil.cpp loolwsd/IoUtil.hpp loolwsd/LOOLKit.cpp loolwsd/LOOLProtocol.hpp loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/LOOLStress.cpp loolwsd/LOOLWebSocket.hpp loolwsd/LOOLWSD.cpp loolwsd/Makefile.am loolwsd/test loolwsd/Unit.hpp loolwsd/UnitHTTP.cpp loolwsd/UnitHTTP.hpp loolwsd/Util.hpp

Jan Holesovsky kendy at collabora.com
Thu Nov 10 09:47:22 UTC 2016


 loolwsd/Admin.cpp               |    5 --
 loolwsd/Admin.hpp               |    4 -
 loolwsd/AdminModel.cpp          |    4 -
 loolwsd/AdminModel.hpp          |   11 ++---
 loolwsd/ClientSession.cpp       |    2 
 loolwsd/ClientSession.hpp       |    2 
 loolwsd/Connect.cpp             |   10 ++--
 loolwsd/DocumentBroker.hpp      |    8 +--
 loolwsd/Exceptions.hpp          |    2 
 loolwsd/IoUtil.cpp              |   31 ++------------
 loolwsd/IoUtil.hpp              |   26 ++++--------
 loolwsd/LOOLKit.cpp             |   18 ++++----
 loolwsd/LOOLProtocol.hpp        |    5 +-
 loolwsd/LOOLSession.cpp         |   10 ++--
 loolwsd/LOOLSession.hpp         |    8 +--
 loolwsd/LOOLStress.cpp          |    6 +-
 loolwsd/LOOLWSD.cpp             |   16 +++----
 loolwsd/LOOLWebSocket.hpp       |   86 ++++++++++++++++++++++++++++++++++++++++
 loolwsd/Makefile.am             |    3 -
 loolwsd/Unit.hpp                |    6 +-
 loolwsd/UnitHTTP.cpp            |    2 
 loolwsd/UnitHTTP.hpp            |    4 -
 loolwsd/Util.hpp                |    1 
 loolwsd/test/TileCacheTests.cpp |   56 +++++++++++++-------------
 loolwsd/test/UnitAdmin.cpp      |   20 ++++-----
 loolwsd/test/UnitFonts.cpp      |   10 ++--
 loolwsd/test/UnitFuzz.cpp       |    4 -
 loolwsd/test/UnitPrefork.cpp    |    8 +--
 loolwsd/test/helpers.hpp        |   40 +++++++++---------
 loolwsd/test/httpcrashtest.cpp  |   12 ++---
 loolwsd/test/httpwserror.cpp    |   12 ++---
 loolwsd/test/httpwstest.cpp     |   78 ++++++++++++++++++------------------
 32 files changed, 285 insertions(+), 225 deletions(-)

New commits:
commit 0674e87831ecf035f6880b9e68d3b9fdd51c1f31
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Thu Nov 10 09:47:25 2016 +0100

    Implement a thread-safe websocket inherited from Poco::Net::WebSocket.
    
    sendFrame() implemented in LOOLWebSocket is thread safe, and also deals with
    large messages - sends the "nextmessage: size=..." frame before the actual
    large frame.
    
    The problem this is attempting to solve was that when sending a large frame,
    it was split to multiple packets.  During that, another frame was sent from a
    different thread; which lead to confusion, and the resulting frame was
    corrupted (because it ended up composed from unrelated packets).
    
    Change-Id: Ie85952e431b1cad2fdc6e3c64df8a444ea0ae971

diff --git a/loolwsd/Admin.cpp b/loolwsd/Admin.cpp
index 04d479b..12b4c50 100644
--- a/loolwsd/Admin.cpp
+++ b/loolwsd/Admin.cpp
@@ -21,7 +21,6 @@
 #include <Poco/Net/HTTPServerResponse.h>
 #include <Poco/Net/NetException.h>
 #include <Poco/Net/SecureServerSocket.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/StringTokenizer.h>
 #include <Poco/Util/ServerApplication.h>
 #include <Poco/Util/Timer.h>
@@ -33,6 +32,7 @@
 #include "FileServer.hpp"
 #include "IoUtil.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "LOOLWSD.hpp"
 #include "Log.hpp"
 #include "Storage.hpp"
@@ -47,7 +47,6 @@ using Poco::Net::HTTPRequestHandler;
 using Poco::Net::HTTPResponse;
 using Poco::Net::HTTPServerRequest;
 using Poco::Net::HTTPServerResponse;
-using Poco::Net::WebSocket;
 using Poco::Util::Application;
 
 bool AdminRequestHandler::adminCommandHandler(const std::vector<char>& payload)
@@ -207,7 +206,7 @@ bool AdminRequestHandler::adminCommandHandler(const std::vector<char>& payload)
 /// Handle admin requests.
 void AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServerResponse& response, int sessionId)
 {
-    _adminWs = std::make_shared<WebSocket>(request, response);
+    _adminWs = std::make_shared<LOOLWebSocket>(request, response);
 
     {
         std::unique_lock<std::mutex> modelLock(_admin->getLock());
diff --git a/loolwsd/Admin.hpp b/loolwsd/Admin.hpp
index e82775d..cb5d83f 100644
--- a/loolwsd/Admin.hpp
+++ b/loolwsd/Admin.hpp
@@ -15,7 +15,6 @@
 #include <Poco/Net/HTTPRequest.h>
 #include <Poco/Net/HTTPRequestHandler.h>
 #include <Poco/Net/HTTPServer.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Runnable.h>
 #include <Poco/Types.h>
 #include <Poco/Util/Timer.h>
@@ -23,6 +22,7 @@
 
 #include "AdminModel.hpp"
 #include "Log.hpp"
+#include <LOOLWebSocket.hpp>
 
 class Admin;
 
@@ -43,7 +43,7 @@ private:
 
 private:
     Admin* _admin;
-    std::shared_ptr<Poco::Net::WebSocket> _adminWs;
+    std::shared_ptr<LOOLWebSocket> _adminWs;
     int _sessionId;
     bool _isAuthenticated;
 };
diff --git a/loolwsd/AdminModel.cpp b/loolwsd/AdminModel.cpp
index d460e53..62d4ab7 100644
--- a/loolwsd/AdminModel.cpp
+++ b/loolwsd/AdminModel.cpp
@@ -15,12 +15,12 @@
 #include <sstream>
 #include <string>
 
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Process.h>
 #include <Poco/StringTokenizer.h>
 #include <Poco/URI.h>
 
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Log.hpp"
 #include "Unit.hpp"
 #include "Util.hpp"
@@ -147,7 +147,7 @@ unsigned AdminModel::getTotalMemoryUsage()
     return totalMem;
 }
 
-void AdminModel::subscribe(int nSessionId, std::shared_ptr<Poco::Net::WebSocket>& ws)
+void AdminModel::subscribe(int nSessionId, std::shared_ptr<LOOLWebSocket>& ws)
 {
     const auto ret = _subscribers.emplace(nSessionId, Subscriber(nSessionId, ws));
     if (!ret.second)
diff --git a/loolwsd/AdminModel.hpp b/loolwsd/AdminModel.hpp
index a1c4812..b24776e 100644
--- a/loolwsd/AdminModel.hpp
+++ b/loolwsd/AdminModel.hpp
@@ -14,10 +14,10 @@
 #include <set>
 #include <string>
 
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Process.h>
 
 #include "Log.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Util.hpp"
 
 /// A client view in Admin controller.
@@ -91,7 +91,7 @@ private:
 class Subscriber
 {
 public:
-    Subscriber(int sessionId, std::shared_ptr<Poco::Net::WebSocket>& ws)
+    Subscriber(int sessionId, std::shared_ptr<LOOLWebSocket>& ws)
         : _sessionId(sessionId),
           _ws(ws),
           _start(std::time(nullptr))
@@ -117,8 +117,9 @@ public:
 private:
     /// Admin session Id
     int _sessionId;
-    /// WebSocket to use to send messages to session
-    std::weak_ptr<Poco::Net::WebSocket> _ws;
+
+    /// LOOLWebSocket to use to send messages to session
+    std::weak_ptr<LOOLWebSocket> _ws;
 
     std::set<std::string> _subscriptions;
 
@@ -145,7 +146,7 @@ public:
     /// Returns memory consumed by all active loolkit processes
     unsigned getTotalMemoryUsage();
 
-    void subscribe(int sessionId, std::shared_ptr<Poco::Net::WebSocket>& ws);
+    void subscribe(int sessionId, std::shared_ptr<LOOLWebSocket>& ws);
     void subscribe(int sessionId, const std::string& command);
 
     void unsubscribe(int sessionId, const std::string& command);
diff --git a/loolwsd/ClientSession.cpp b/loolwsd/ClientSession.cpp
index c186619..24b53c5 100644
--- a/loolwsd/ClientSession.cpp
+++ b/loolwsd/ClientSession.cpp
@@ -35,7 +35,7 @@ using namespace LOOLProtocol;
 using Poco::StringTokenizer;
 
 ClientSession::ClientSession(const std::string& id,
-                             const std::shared_ptr<Poco::Net::WebSocket>& ws,
+                             const std::shared_ptr<LOOLWebSocket>& ws,
                              const std::shared_ptr<DocumentBroker>& docBroker,
                              const Poco::URI& uriPublic,
                              const bool readOnly) :
diff --git a/loolwsd/ClientSession.hpp b/loolwsd/ClientSession.hpp
index 77ddcfa..4340f46 100644
--- a/loolwsd/ClientSession.hpp
+++ b/loolwsd/ClientSession.hpp
@@ -23,7 +23,7 @@ class ClientSession final : public LOOLSession, public std::enable_shared_from_t
 {
 public:
     ClientSession(const std::string& id,
-                  const std::shared_ptr<Poco::Net::WebSocket>& ws,
+                  const std::shared_ptr<LOOLWebSocket>& ws,
                   const std::shared_ptr<DocumentBroker>& docBroker,
                   const Poco::URI& uriPublic,
                   const bool isReadOnly = false);
diff --git a/loolwsd/Connect.cpp b/loolwsd/Connect.cpp
index 3c14b22..5b550dd 100644
--- a/loolwsd/Connect.cpp
+++ b/loolwsd/Connect.cpp
@@ -31,7 +31,6 @@
 #include <Poco/Net/TCPServer.h>
 #include <Poco/Net/TCPServerConnection.h>
 #include <Poco/Net/TCPServerConnectionFactory.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Process.h>
 #include <Poco/SharedPtr.h>
 #include <Poco/StringTokenizer.h>
@@ -43,6 +42,7 @@
 
 #include "Common.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Log.hpp"
 #include "Util.hpp"
 
@@ -72,11 +72,11 @@ using Poco::Util::Application;
 static bool closeExpected = false;
 static std::mutex coutMutex;
 
-/// Prints incoming data from a WebSocket.
+/// Prints incoming data from a LOOLWebSocket.
 class Output : public Runnable
 {
 public:
-    Output(WebSocket& ws) :
+    Output(LOOLWebSocket& ws) :
         _ws(ws)
     {
     }
@@ -131,7 +131,7 @@ public:
         }
     }
 
-    WebSocket& _ws;
+    LOOLWebSocket& _ws;
 };
 
 /// Program for interactive or scripted testing of a lool server.
@@ -179,7 +179,7 @@ protected:
         URI::encode(args[0], ":/?", encodedUri);
         HTTPRequest request(HTTPRequest::HTTP_GET, "/lool/" + encodedUri + "/ws");
         HTTPResponse response;
-        WebSocket ws(cs, request, response);
+        LOOLWebSocket ws(cs, request, response);
 
         ws.setReceiveTimeout(0);
 
diff --git a/loolwsd/DocumentBroker.hpp b/loolwsd/DocumentBroker.hpp
index 3212715..fc035f7 100644
--- a/loolwsd/DocumentBroker.hpp
+++ b/loolwsd/DocumentBroker.hpp
@@ -21,11 +21,11 @@
 #include <string>
 #include <thread>
 
-#include <Poco/Net/WebSocket.h>
 #include <Poco/URI.h>
 
 #include "IoUtil.hpp"
 #include "Log.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Storage.hpp"
 #include "TileCache.hpp"
 #include "Util.hpp"
@@ -39,8 +39,8 @@ class ChildProcess
 {
 public:
     /// @param pid is the process ID of the child.
-    /// @param ws is the control WebSocket to the child.
-    ChildProcess(const Poco::Process::PID pid, const std::shared_ptr<Poco::Net::WebSocket>& ws) :
+    /// @param ws is the control LOOLWebSocket to the child.
+    ChildProcess(const Poco::Process::PID pid, const std::shared_ptr<LOOLWebSocket>& ws) :
         _pid(pid),
         _ws(ws),
         _stop(false)
@@ -163,7 +163,7 @@ private:
 
 private:
     Poco::Process::PID _pid;
-    std::shared_ptr<Poco::Net::WebSocket> _ws;
+    std::shared_ptr<LOOLWebSocket> _ws;
     std::weak_ptr<DocumentBroker> _docBroker;
     std::thread _thread;
     std::atomic<bool> _stop;
diff --git a/loolwsd/Exceptions.hpp b/loolwsd/Exceptions.hpp
index ae2d1a6..b05d98d 100644
--- a/loolwsd/Exceptions.hpp
+++ b/loolwsd/Exceptions.hpp
@@ -59,7 +59,7 @@ public:
 };
 
 /// An generic error-message exception meant to
-/// propagate via a valid WebSocket to the client.
+/// propagate via a valid LOOLWebSocket to the client.
 /// The contents of what() will be displayed on screen.
 class WebSocketErrorMessageException : public LoolException
 {
diff --git a/loolwsd/IoUtil.cpp b/loolwsd/IoUtil.cpp
index 04a6ed5..75b7026 100644
--- a/loolwsd/IoUtil.cpp
+++ b/loolwsd/IoUtil.cpp
@@ -22,13 +22,13 @@
 
 #include <Poco/Net/NetException.h>
 #include <Poco/Net/Socket.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/StringTokenizer.h>
 #include <Poco/Thread.h>
 #include <Poco/URI.h>
 
 #include "Common.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Log.hpp"
 #include "Util.hpp"
 
@@ -38,7 +38,7 @@ using Poco::Net::WebSocket;
 namespace IoUtil
 {
 
-int receiveFrame(WebSocket& socket, void* buffer, int length, int& flags)
+int receiveFrame(LOOLWebSocket& socket, void* buffer, int length, int& flags)
 {
     while (!TerminationFlag)
     {
@@ -60,9 +60,9 @@ int receiveFrame(WebSocket& socket, void* buffer, int length, int& flags)
     return -1;
 }
 
-// Synchronously process WebSocket requests and dispatch to handler.
+// Synchronously process LOOLWebSocket requests and dispatch to handler.
 // Handler returns false to end.
-void SocketProcessor(const std::shared_ptr<WebSocket>& ws,
+void SocketProcessor(const std::shared_ptr<LOOLWebSocket>& ws,
                      const std::function<bool(const std::vector<char>&)>& handler,
                      const std::function<void()>& closeFrame,
                      const std::function<bool()>& stopPredicate)
@@ -197,11 +197,11 @@ void SocketProcessor(const std::shared_ptr<WebSocket>& ws,
     LOG_INF("SocketProcessor finished.");
 }
 
-void shutdownWebSocket(const std::shared_ptr<Poco::Net::WebSocket>& ws)
+void shutdownWebSocket(const std::shared_ptr<LOOLWebSocket>& ws)
 {
     try
     {
-        // Calling WebSocket::shutdown, in case of error, would try to send a 'close' frame
+        // Calling LOOLWebSocket::shutdown, in case of error, would try to send a 'close' frame
         // which won't work in case of broken pipe or timeout from peer. Just close the
         // socket in that case preventing 'close' frame from being sent.
         if (ws && ws->poll(Poco::Timespan(0), Socket::SelectMode::SELECT_ERROR))
@@ -258,25 +258,6 @@ ssize_t readFromPipe(int pipe, char* buffer, ssize_t size)
     return bytes;
 }
 
-void sendLargeFrame(const std::shared_ptr<Poco::Net::WebSocket>& ws, const char *message, int length, int flags)
-{
-    // Size after which messages will be sent preceded with
-    // 'nextmessage' frame to let the receiver know in advance
-    // the size of larger coming message. All messages up to this
-    // size are considered small messages.
-    constexpr int SMALL_MESSAGE_SIZE = READ_BUFFER_SIZE / 2;
-
-    if (length > SMALL_MESSAGE_SIZE)
-    {
-        const std::string nextmessage = "nextmessage: size=" + std::to_string(length);
-        ws->sendFrame(nextmessage.data(), nextmessage.size());
-        LOG_DBG("Message is long, sent " << nextmessage);
-    }
-
-    ws->sendFrame(message, length, flags);
-    LOG_DBG("Sent frame: " << LOOLProtocol::getAbbreviatedMessage(std::string(message, length)));
-}
-
 /// Reads a single line from a pipe.
 /// Returns 0 for timeout, <0 for error, and >0 on success.
 /// On success, line will contain the read message.
diff --git a/loolwsd/IoUtil.hpp b/loolwsd/IoUtil.hpp
index e0068b0..dba0aa7 100644
--- a/loolwsd/IoUtil.hpp
+++ b/loolwsd/IoUtil.hpp
@@ -14,24 +14,26 @@
 #include <memory>
 #include <string>
 
-#include <Poco/Net/WebSocket.h>
+#include <LOOLWebSocket.hpp>
 
 namespace IoUtil
 {
-    // Wrapper for WebSocket::receiveFrame() that handles PING frames (by replying with a
+    // Wrapper for LOOLWebSocket::receiveFrame() that handles PING frames (by replying with a
     // PONG frame) and PONG frames. PONG frames are ignored.
     // Should we also factor out the handling of non-final and continuation frames into this?
-    int receiveFrame(Poco::Net::WebSocket& socket, void* buffer, int length, int& flags);
+    // TODO: move this to LOOLWebSocket directly
+    int receiveFrame(LOOLWebSocket& socket, void* buffer, int length, int& flags);
 
-    /// Synchronously process WebSocket requests and dispatch to handler.
+    /// Synchronously process LOOLWebSocket requests and dispatch to handler.
     /// Handler returns false to end.
-    void SocketProcessor(const std::shared_ptr<Poco::Net::WebSocket>& ws,
+    void SocketProcessor(const std::shared_ptr<LOOLWebSocket>& ws,
                          const std::function<bool(const std::vector<char>&)>& handler,
                          const std::function<void()>& closeFrame,
                          const std::function<bool()>& stopPredicate);
 
-    /// Call WebSocket::shutdown() ignoring Poco::IOException.
-    void shutdownWebSocket(const std::shared_ptr<Poco::Net::WebSocket>& ws);
+    /// Call LOOLWebSocket::shutdown() ignoring Poco::IOException.
+    /// TODO: consider moving this directly to LOOLWebSocket
+    void shutdownWebSocket(const std::shared_ptr<LOOLWebSocket>& ws);
 
     ssize_t writeToPipe(int pipe, const char* buffer, ssize_t size);
     inline ssize_t writeToPipe(int pipe, const std::string& message)
@@ -41,16 +43,6 @@ namespace IoUtil
 
     ssize_t readFromPipe(int pipe, char* buffer, ssize_t size);
 
-    /// Send frame.  If it is too long, send a 'nextmessage:' before the real
-    /// frame.
-    void sendLargeFrame(const std::shared_ptr<Poco::Net::WebSocket>& ws, const char *message, int length, int flags = Poco::Net::WebSocket::FRAME_TEXT);
-
-    /// Send frame as above, the std::string variant.
-    inline void sendLargeFrame(const std::shared_ptr<Poco::Net::WebSocket>& ws, const std::vector<char> &message, int flags = Poco::Net::WebSocket::FRAME_TEXT)
-    {
-        sendLargeFrame(ws, message.data(), message.size(), flags);
-    }
-
     /// Helper class to handle reading from a pipe.
     class PipeReader
     {
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index f228be9..397dcc5 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -40,7 +40,6 @@
 #include <Poco/Net/HTTPResponse.h>
 #include <Poco/Net/NetException.h>
 #include <Poco/Net/Socket.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/NotificationQueue.h>
 #include <Poco/Process.h>
 #include <Poco/Runnable.h>
@@ -55,6 +54,7 @@
 #include "LOKitHelper.hpp"
 #include "LOOLKit.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "LibreOfficeKit.hpp"
 #include "Log.hpp"
 #include "Png.hpp"
@@ -280,7 +280,7 @@ public:
              const std::string& docKey,
              const std::string& url,
              std::shared_ptr<TileQueue> tileQueue,
-             const std::shared_ptr<WebSocket>& ws)
+             const std::shared_ptr<LOOLWebSocket>& ws)
       : _loKit(loKit),
         _jailId(jailId),
         _docKey(docKey),
@@ -450,7 +450,7 @@ public:
         LOG_INF("setDocumentPassword returned");
     }
 
-    void renderTile(StringTokenizer& tokens, const std::shared_ptr<Poco::Net::WebSocket>& ws)
+    void renderTile(StringTokenizer& tokens, const std::shared_ptr<LOOLWebSocket>& ws)
     {
         assert(ws && "Expected a non-null websocket.");
         auto tile = TileDesc::parse(tokens);
@@ -505,10 +505,10 @@ public:
         }
 
         LOG_TRC("Sending render-tile response (" + std::to_string(output.size()) + " bytes) for: " + response);
-        IoUtil::sendLargeFrame(ws, output, WebSocket::FRAME_BINARY);
+        ws->sendFrame(output.data(), output.size(), WebSocket::FRAME_BINARY);
     }
 
-    void renderCombinedTiles(StringTokenizer& tokens, const std::shared_ptr<Poco::Net::WebSocket>& ws)
+    void renderCombinedTiles(StringTokenizer& tokens, const std::shared_ptr<LOOLWebSocket>& ws)
     {
         assert(ws && "Expected a non-null websocket.");
         auto tileCombined = TileCombined::parse(tokens);
@@ -605,7 +605,7 @@ public:
         std::copy(tileMsg.begin(), tileMsg.end(), response.begin());
         std::copy(output.begin(), output.end(), response.begin() + tileMsg.size());
 
-        IoUtil::sendLargeFrame(ws, response, WebSocket::FRAME_BINARY);
+        ws->sendFrame(response.data(), response.size(), WebSocket::FRAME_BINARY);
     }
 
     bool sendTextFrame(const std::string& message) override
@@ -618,7 +618,7 @@ public:
                 return false;
             }
 
-            IoUtil::sendLargeFrame(_ws, message.data(), message.size());
+            _ws->sendFrame(message.data(), message.size());
             return true;
         }
         catch (const Exception& exc)
@@ -1244,7 +1244,7 @@ private:
 
     std::shared_ptr<lok::Document> _loKitDocument;
     std::shared_ptr<TileQueue> _tileQueue;
-    std::shared_ptr<WebSocket> _ws;
+    std::shared_ptr<LOOLWebSocket> _ws;
 
     // Document password provided
     std::string _docPassword;
@@ -1462,7 +1462,7 @@ void lokit_main(const std::string& childRoot,
 
         HTTPRequest request(HTTPRequest::HTTP_GET, requestUrl);
         HTTPResponse response;
-        auto ws = std::make_shared<WebSocket>(cs, request, response);
+        auto ws = std::make_shared<LOOLWebSocket>(cs, request, response);
         ws->setReceiveTimeout(0);
 
         auto queue = std::make_shared<TileQueue>();
diff --git a/loolwsd/LOOLProtocol.hpp b/loolwsd/LOOLProtocol.hpp
index fe11f2e..2c158ff 100644
--- a/loolwsd/LOOLProtocol.hpp
+++ b/loolwsd/LOOLProtocol.hpp
@@ -16,9 +16,10 @@
 #include <string>
 
 #include <Poco/Format.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/StringTokenizer.h>
 
+#include <LOOLWebSocket.hpp>
+
 #define LOK_USE_UNSTABLE_API
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 
@@ -189,7 +190,7 @@ namespace LOOLProtocol
         return getAbbreviatedMessage(message.data(), message.size());
     }
 
-    // Return a string dump of a WebSocket frame: Its opcode, length, first line (if present),
+    // Return a string dump of a LOOLWebSocket frame: Its opcode, length, first line (if present),
     // flags.  For human-readable logging purposes. Format not guaranteed to be stable. Not to be
     // inspected programmatically.
     inline
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index db091f5..97ae19e 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -27,7 +27,6 @@
 
 #include <Poco/Exception.h>
 #include <Poco/Net/Socket.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Path.h>
 #include <Poco/String.h>
 #include <Poco/StringTokenizer.h>
@@ -36,6 +35,7 @@
 #include "Common.hpp"
 #include "IoUtil.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Log.hpp"
 #include "TileCache.hpp"
 #include "Util.hpp"
@@ -49,7 +49,7 @@ using Poco::Net::WebSocket;
 using Poco::StringTokenizer;
 
 LOOLSession::LOOLSession(const std::string& id, const Kind kind,
-                         std::shared_ptr<WebSocket> ws) :
+                         std::shared_ptr<LOOLWebSocket> ws) :
     _id(id),
     _kind(kind),
     _kindString(kind == Kind::ToClient ? "ToClient" :
@@ -84,7 +84,7 @@ bool LOOLSession::sendTextFrame(const char* buffer, const int length)
             return false;
         }
 
-        IoUtil::sendLargeFrame(_ws, buffer, length);
+        _ws->sendFrame(buffer, length);
         return true;
     }
     catch (const Exception& exc)
@@ -109,7 +109,7 @@ bool LOOLSession::sendBinaryFrame(const char *buffer, int length)
             return false;
         }
 
-        IoUtil::sendLargeFrame(_ws, buffer, length, WebSocket::FRAME_BINARY);
+        _ws->sendFrame(buffer, length, WebSocket::FRAME_BINARY);
         return true;
     }
     catch (const Exception& exc)
@@ -213,7 +213,7 @@ void LOOLSession::shutdown(Poco::UInt16 statusCode, const std::string& statusMes
         }
         catch (const Poco::Exception &exc)
         {
-            LOG_WRN("LOOLSession::shutdown WebSocket: Exception: " <<
+            LOG_WRN("LOOLSession::shutdown LOOLWebSocket: Exception: " <<
                     exc.displayText() << (exc.nested() ? " (" + exc.nested()->displayText() + ")" : ""));
         }
     }
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index cd6b9fe..736e63d 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -17,18 +17,18 @@
 #include <ostream>
 
 #include <Poco/Buffer.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Path.h>
 #include <Poco/Process.h>
 #include <Poco/StringTokenizer.h>
 #include <Poco/Types.h>
 
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Log.hpp"
 #include "MessageQueue.hpp"
 #include "TileCache.hpp"
 
-/// Base class of a WebSocket session.
+/// Base class of a LOOLWebSocket session.
 class LOOLSession
 {
 public:
@@ -83,7 +83,7 @@ public:
 
 protected:
     LOOLSession(const std::string& id, const Kind kind,
-                std::shared_ptr<Poco::Net::WebSocket> ws);
+                std::shared_ptr<LOOLWebSocket> ws);
     virtual ~LOOLSession();
 
     /// Parses the options of the "load" command, shared between MasterProcessSession::loadDocument() and ChildProcessSession::loadDocument().
@@ -146,7 +146,7 @@ private:
 
     // In the master process, the websocket to the LOOL client or the jailed child process. In a
     // jailed process, the websocket to the parent.
-    std::shared_ptr<Poco::Net::WebSocket> _ws;
+    std::shared_ptr<LOOLWebSocket> _ws;
 
     /// True if we have been disconnected.
     std::atomic<bool> _disconnected;
diff --git a/loolwsd/LOOLStress.cpp b/loolwsd/LOOLStress.cpp
index 484d3fb..7dbe7a6 100644
--- a/loolwsd/LOOLStress.cpp
+++ b/loolwsd/LOOLStress.cpp
@@ -121,7 +121,7 @@ public:
     }
 
     const std::string& getName() const { return _name; }
-    std::shared_ptr<Poco::Net::WebSocket> getWS() const { return _ws; };
+    std::shared_ptr<LOOLWebSocket> getWS() const { return _ws; };
 
     /// Send a command to the server.
     void send(const std::string& data) const
@@ -143,7 +143,7 @@ public:
     }
 
 private:
-    Connection(const std::string& documentURL, const std::string& sessionId, std::shared_ptr<Poco::Net::WebSocket>& ws) :
+    Connection(const std::string& documentURL, const std::string& sessionId, std::shared_ptr<LOOLWebSocket>& ws) :
         _documentURL(documentURL),
         _sessionId(sessionId),
         _name(sessionId + ' '),
@@ -155,7 +155,7 @@ private:
     const std::string _documentURL;
     const std::string _sessionId;
     const std::string _name;
-    std::shared_ptr<Poco::Net::WebSocket> _ws;
+    std::shared_ptr<LOOLWebSocket> _ws;
     static std::mutex Mutex;
 };
 
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 40876de..87cf4a6 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -77,7 +77,6 @@
 #include <Poco/Net/SecureServerSocket.h>
 #include <Poco/Net/ServerSocket.h>
 #include <Poco/Net/SocketAddress.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Path.h>
 #include <Poco/Pipe.h>
 #include <Poco/Process.h>
@@ -103,6 +102,7 @@
 #include "IoUtil.hpp"
 #include "LOOLProtocol.hpp"
 #include "LOOLSession.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Log.hpp"
 #include "PrisonerSession.hpp"
 #include "QueueHandler.hpp"
@@ -180,7 +180,7 @@ namespace
 {
 
 static inline
-void shutdownLimitReached(WebSocket& ws)
+void shutdownLimitReached(LOOLWebSocket& ws)
 {
     const std::string error = Poco::format(PAYLOAD_UNAVAILABLE_LIMIT_REACHED, MAX_DOCUMENTS, MAX_CONNECTIONS);
 
@@ -519,7 +519,7 @@ private:
                     DocBrokers.emplace(docKey, docBroker);
 
                     // Load the document.
-                    std::shared_ptr<WebSocket> ws;
+                    std::shared_ptr<LOOLWebSocket> ws;
                     auto session = std::make_shared<ClientSession>(id, ws, docBroker, uriPublic);
 
                     auto sessionsCount = docBroker->addSession(session);
@@ -704,7 +704,7 @@ private:
     }
 
     /// Handle GET requests.
-    static void handleGetRequest(const std::string& uri, std::shared_ptr<WebSocket>& ws, const std::string& id)
+    static void handleGetRequest(const std::string& uri, std::shared_ptr<LOOLWebSocket>& ws, const std::string& id)
     {
         LOG_INF("Starting GET request handler for session [" << id << "].");
 
@@ -1049,7 +1049,7 @@ public:
             --LOOLWSD::NumConnections;
             LOG_ERR("Limit on maximum number of connections of " << MAX_CONNECTIONS << " reached.");
             // accept hand shake
-            WebSocket ws(request, response);
+            LOOLWebSocket ws(request, response);
             shutdownLimitReached(ws);
             return;
         }
@@ -1118,7 +1118,7 @@ public:
             }
             else if (reqPathTokens.count() > 2 && reqPathTokens[0] == "lool" && reqPathTokens[2] == "ws")
             {
-                auto ws = std::make_shared<WebSocket>(request, response);
+                auto ws = std::make_shared<LOOLWebSocket>(request, response);
                 responded = true; // After upgrading to WS we should not set HTTP response.
                 try
                 {
@@ -1233,7 +1233,7 @@ public:
         }
 
         LOG_INF("New child [" << pid << "].");
-        auto ws = std::make_shared<WebSocket>(request, response);
+        auto ws = std::make_shared<LOOLWebSocket>(request, response);
         UnitWSD::get().newChild(ws);
 
         addNewChild(std::make_shared<ChildProcess>(pid, ws));
@@ -1276,7 +1276,7 @@ public:
         {
             requestHandler = FileServer::createRequestHandler();
         }
-        // Admin WebSocket Connections
+        // Admin LOOLWebSocket Connections
         else if (reqPathSegs.size() >= 2 && reqPathSegs[0] == "lool" && reqPathSegs[1] == "adminws")
         {
             requestHandler = Admin::createRequestHandler();
diff --git a/loolwsd/LOOLWebSocket.hpp b/loolwsd/LOOLWebSocket.hpp
new file mode 100644
index 0000000..ffd4887
--- /dev/null
+++ b/loolwsd/LOOLWebSocket.hpp
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_LOOLWEBSOCKET_HPP
+#define INCLUDED_LOOLWEBSOCKET_HPP
+
+#include <mutex>
+
+#include <Poco/Net/WebSocket.h>
+
+#include <Common.hpp>
+#include <LOOLProtocol.hpp>
+#include <Log.hpp>
+
+/// WebSocket that is thread safe, and handles large frames transparently.
+class LOOLWebSocket : public Poco::Net::WebSocket
+{
+    std::mutex _mutex;
+
+public:
+    LOOLWebSocket(const Socket & socket) :
+        Poco::Net::WebSocket(socket),
+        _mutex()
+    {
+    }
+
+    LOOLWebSocket(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) :
+        Poco::Net::WebSocket(request, response),
+        _mutex()
+    {
+    }
+
+    LOOLWebSocket(Poco::Net::HTTPClientSession & cs, Poco::Net::HTTPRequest & request, Poco::Net::HTTPResponse & response) :
+        Poco::Net::WebSocket(cs, request, response),
+        _mutex()
+    {
+    }
+
+    LOOLWebSocket(Poco::Net::HTTPClientSession & cs, Poco::Net::HTTPRequest & request, Poco::Net::HTTPResponse & response, Poco::Net::HTTPCredentials & credentials) :
+        Poco::Net::WebSocket(cs, request, response, credentials),
+        _mutex()
+    {
+    }
+
+    /// Careful - sendFrame is _not_ virtual, we need to make sure that we use
+    /// LOOLWebSocket all over the place
+    /// It would be a kind of more natural to encapsulate Poco::Net::WebSocket
+    /// instead of inheriting (from that reason), but that would requite much
+    /// larger code changes.
+    int sendFrame(const void * buffer, int length, int flags = FRAME_TEXT)
+    {
+        std::lock_guard<std::mutex> lock(_mutex);
+
+        // Size after which messages will be sent preceded with
+        // 'nextmessage' frame to let the receiver know in advance
+        // the size of larger coming message. All messages up to this
+        // size are considered small messages.
+        constexpr int SMALL_MESSAGE_SIZE = READ_BUFFER_SIZE / 2;
+
+        if (length > SMALL_MESSAGE_SIZE)
+        {
+            const std::string nextmessage = "nextmessage: size=" + std::to_string(length);
+            Poco::Net::WebSocket::sendFrame(nextmessage.data(), nextmessage.size());
+            Log::debug("Message is long, sent " + nextmessage);
+        }
+
+        int result = Poco::Net::WebSocket::sendFrame(buffer, length, flags);
+        // FIXME we want an abbreviated message here, but we'd have a circular
+        // dependency with LOOLProtocol, so use the full message here before
+        // we move getAbbreviatedMessage() to Log (where it belongs anyway).
+        //Log::debug("Sent frame: " + LOOLProtocol::getAbbreviatedMessage(static_cast<const char*>(buffer), length));
+        Log::debug("Sent frame: " + std::string(static_cast<const char*>(buffer), length));
+
+        return result;
+    }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index 1f47750..cb4a7a9 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -82,7 +82,8 @@ looltool_SOURCES = LOOLTool.cpp
 
 loolstress_CPPFLAGS = -DTDOC=\"$(abs_top_srcdir)/test/data\"
 loolstress_SOURCES = LOOLStress.cpp \
-                     LOOLProtocol.cpp
+                     LOOLProtocol.cpp \
+		     Log.cpp
 
 noinst_HEADERS = Admin.hpp \
                  AdminModel.hpp \
diff --git a/loolwsd/Unit.hpp b/loolwsd/Unit.hpp
index 97b7103..7b6c6f8 100644
--- a/loolwsd/Unit.hpp
+++ b/loolwsd/Unit.hpp
@@ -14,7 +14,7 @@
 #include <memory>
 #include <string>
 
-#include <Poco/Net/WebSocket.h>
+#include <LOOLWebSocket.hpp>
 
 class UnitBase;
 class UnitWSD;
@@ -139,7 +139,7 @@ public:
     /// Tweak the count of pre-spawned kits.
     virtual void preSpawnCount(int& /* numPrefork */) {}
     /// When a new child kit process reports
-    virtual void newChild(const std::shared_ptr<Poco::Net::WebSocket>& /* socket */) {}
+    virtual void newChild(const std::shared_ptr<LOOLWebSocket>& /* socket */) {}
     /// Intercept createStorage
     virtual bool createStorage(const Poco::URI& /* uri */,
                                const std::string& /* jailRoot */,
@@ -221,7 +221,7 @@ public:
     virtual void postFork() {}
 
     /// Kit got a message
-    virtual bool filterKitMessage(const std::shared_ptr<Poco::Net::WebSocket>& /* ws */,
+    virtual bool filterKitMessage(const std::shared_ptr<LOOLWebSocket>& /* ws */,
                                   std::string& /* message */)
     {
         return false;
diff --git a/loolwsd/UnitHTTP.cpp b/loolwsd/UnitHTTP.cpp
index d42aea0..6775695 100644
--- a/loolwsd/UnitHTTP.cpp
+++ b/loolwsd/UnitHTTP.cpp
@@ -26,7 +26,7 @@ UnitWebSocket::UnitWebSocket(const std::string &docURL)
         _session = UnitHTTP::createSession();
 
         // FIXME: leaking the session - hey ho ... do we need a UnitSocket ?
-        _socket = new Poco::Net::WebSocket(*_session, request, response);
+        _socket = new LOOLWebSocket(*_session, request, response);
     } catch (const Poco::Exception &ex) {
         std::cerr << "Exception creating websocket " << ex.displayText() << std::endl;
         throw;
diff --git a/loolwsd/UnitHTTP.hpp b/loolwsd/UnitHTTP.hpp
index 3c28613..7765e47 100644
--- a/loolwsd/UnitHTTP.hpp
+++ b/loolwsd/UnitHTTP.hpp
@@ -18,10 +18,10 @@
 #include <Poco/Net/HTTPServerRequest.h>
 #include <Poco/Net/HTTPServerResponse.h>
 #include <Poco/Net/SocketAddress.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Version.h>
 
 #include "Common.hpp"
+#include <LOOLWebSocket.hpp>
 
 using Poco::Net::SocketAddress;
 using Poco::Net::HTTPServerParams;
@@ -121,7 +121,7 @@ namespace UnitHTTP
 class UnitWebSocket
 {
     Poco::Net::HTTPClientSession* _session;
-    Poco::Net::WebSocket* _socket;
+    LOOLWebSocket* _socket;
 
 public:
     /// Get a websocket connected for a given URL
diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp
index cde7828..ae4c3cd 100644
--- a/loolwsd/Util.hpp
+++ b/loolwsd/Util.hpp
@@ -20,7 +20,6 @@
 #include <string>
 
 #include <Poco/File.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Path.h>
 #include <Poco/Process.h>
 #include <Poco/RegularExpression.h>
diff --git a/loolwsd/test/TileCacheTests.cpp b/loolwsd/test/TileCacheTests.cpp
index ade2ae0..5343092 100644
--- a/loolwsd/test/TileCacheTests.cpp
+++ b/loolwsd/test/TileCacheTests.cpp
@@ -9,11 +9,11 @@
 
 #include "config.h"
 
-#include <Poco/Net/WebSocket.h>
 #include <cppunit/extensions/HelperMacros.h>
 
 #include "Common.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "MessageQueue.hpp"
 #include "Png.hpp"
 #include "TileCache.hpp"
@@ -94,17 +94,17 @@ class TileCacheTests : public CPPUNIT_NS::TestFixture
 
     void tileInvalidatePart(const std::string& filename, const std::string& testname);
 
-    void checkTiles(Poco::Net::WebSocket& socket,
+    void checkTiles(std::shared_ptr<LOOLWebSocket>& socket,
                     const std::string& type,
                     const std::string& name = "checkTiles ");
 
-    void requestTiles(Poco::Net::WebSocket& socket,
+    void requestTiles(std::shared_ptr<LOOLWebSocket>& socket,
                       const int part,
                       const int docWidth,
                       const int docHeight,
                       const std::string& name = "requestTiles ");
 
-    void checkBlackTiles(Poco::Net::WebSocket& socket,
+    void checkBlackTiles(std::shared_ptr<LOOLWebSocket>& socket,
                          const int part,
                          const int docWidth,
                          const int docHeight,
@@ -212,7 +212,7 @@ void TileCacheTests::testSimpleCombine()
 
 void TileCacheTests::testPerformance()
 {
-    auto socket = *loadDocAndGetSocket("hello.odt", _uri, "performance ");
+    auto socket = loadDocAndGetSocket("hello.odt", _uri, "performance ");
 
     Poco::Timestamp timestamp;
     for (auto x = 0; x < 5; ++x)
@@ -230,13 +230,13 @@ void TileCacheTests::testPerformance()
               << " ms. Per-tile: " << timestamp.elapsed() / (1000. * 5 * 8) << "ms."
               << std::endl;
 
-    socket.shutdown();
+    socket->shutdown();
 }
 
 void TileCacheTests::testCancelTiles()
 {
     const auto testName = "cancelTiles ";
-    auto socket = *loadDocAndGetSocket("setclientpart.ods", _uri, testName);
+    auto socket = loadDocAndGetSocket("setclientpart.ods", _uri, testName);
 
     // Request a huge tile, and cancel immediately.
     sendTextFrame(socket, "tilecombine part=0 width=2560 height=2560 tileposx=0 tileposy=0 tilewidth=38400 tileheight=38400");
@@ -322,10 +322,10 @@ void TileCacheTests::testImpressTiles()
     try
     {
         const std::string testName = "impressTiles ";
-        auto socket = *loadDocAndGetSocket("setclientpart.odp", _uri, testName);
+        auto socket = loadDocAndGetSocket("setclientpart.odp", _uri, testName);
 
         sendTextFrame(socket, "tile part=0 width=180 height=135 tileposx=0 tileposy=0 tilewidth=15875 tileheight=11906 id=0", testName);
-        getTileMessage(socket, testName);
+        getTileMessage(*socket, testName);
     }
     catch (const Poco::Exception& exc)
     {
@@ -338,11 +338,11 @@ void TileCacheTests::testClientPartImpress()
     try
     {
         const std::string testName = "clientPartImpress ";
-        auto socket = *loadDocAndGetSocket("setclientpart.odp", _uri, testName);
+        auto socket = loadDocAndGetSocket("setclientpart.odp", _uri, testName);
 
         checkTiles(socket, "presentation", testName);
 
-        socket.shutdown();
+        socket->shutdown();
     }
     catch (const Poco::Exception& exc)
     {
@@ -355,11 +355,11 @@ void TileCacheTests::testClientPartCalc()
     try
     {
         const std::string testName = "clientPartCalc ";
-        auto socket = *loadDocAndGetSocket("setclientpart.ods", _uri, testName);
+        auto socket = loadDocAndGetSocket("setclientpart.ods", _uri, testName);
 
         checkTiles(socket, "spreadsheet", testName);
 
-        socket.shutdown();
+        socket->shutdown();
     }
     catch (const Poco::Exception& exc)
     {
@@ -371,7 +371,7 @@ void TileCacheTests::testTilesRenderedJustOnce()
 {
     const auto testname = "tilesRenderdJustOnce ";
 
-    auto socket = *loadDocAndGetSocket("with_comment.odt", _uri, testname);
+    auto socket = loadDocAndGetSocket("with_comment.odt", _uri, testname);
 
     assertResponseString(socket, "statechanged: .uno:AcceptTrackedChange=", testname);
 
@@ -439,13 +439,13 @@ void TileCacheTests::testTilesRenderedJustOnceMultiClient()
     getDocumentPathAndURL("with_comment.odt", documentPath, documentURL);
 
     std::cerr << "Connecting first client." << std::endl;
-    auto socket = *loadDocAndGetSocket(_uri, documentURL, testname1);
+    auto socket = loadDocAndGetSocket(_uri, documentURL, testname1);
     std::cerr << "Connecting second client." << std::endl;
-    auto socket2 = *loadDocAndGetSocket(_uri, documentURL, testname2);
+    auto socket2 = loadDocAndGetSocket(_uri, documentURL, testname2);
     std::cerr << "Connecting third client." << std::endl;
-    auto socket3 = *loadDocAndGetSocket(_uri, documentURL, testname3);
+    auto socket3 = loadDocAndGetSocket(_uri, documentURL, testname3);
     std::cerr << "Connecting fourth client." << std::endl;
-    auto socket4 = *loadDocAndGetSocket(_uri, documentURL, "tilesRenderdJustOnce-4 ");
+    auto socket4 = loadDocAndGetSocket(_uri, documentURL, "tilesRenderdJustOnce-4 ");
 
     for (int i = 0; i < 10; ++i)
     {
@@ -562,7 +562,7 @@ void TileCacheTests::testLoad12ods()
     try
     {
         const auto testName = "load12ods ";
-        auto socket = *loadDocAndGetSocket("load12.ods", _uri, testName);
+        auto socket = loadDocAndGetSocket("load12.ods", _uri, testName);
 
         int docSheet = -1;
         int docSheets = 0;
@@ -616,7 +616,7 @@ void TileCacheTests::checkBlackTile(std::stringstream& tile)
     CPPUNIT_ASSERT_MESSAGE("The tile is 90% black", (black * 100) / (height * width) < 90);
 }
 
-void TileCacheTests::checkBlackTiles(Poco::Net::WebSocket& socket, const int /*part*/, const int /*docWidth*/, const int /*docHeight*/, const std::string& name)
+void TileCacheTests::checkBlackTiles(std::shared_ptr<LOOLWebSocket>& socket, const int /*part*/, const int /*docWidth*/, const int /*docHeight*/, const std::string& name)
 {
     // Check the last row of tiles to verify that the tiles
     // render correctly and there are no black tiles.
@@ -645,7 +645,7 @@ void TileCacheTests::testTileInvalidateWriter()
     getDocumentPathAndURL("empty.odt", documentPath, documentURL);
     Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
 
-    auto socket = *loadDocAndGetSocket(_uri, documentURL);
+    auto socket = loadDocAndGetSocket(_uri, documentURL);
 
     std::string text = "Test. Now go 3 \"Enters\":\n\n\nNow after the enters, goes this text";
     for (char ch : text)
@@ -682,7 +682,7 @@ void TileCacheTests::testTileInvalidateWriterPage()
     getDocumentPathAndURL("empty.odt", documentPath, documentURL);
     Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
 
-    auto socket = *loadDocAndGetSocket(_uri, documentURL, testname);
+    auto socket = loadDocAndGetSocket(_uri, documentURL, testname);
 
     sendChar(socket, '\n', skCtrl, testname); // Send Ctrl+Enter (page break).
     assertResponseString(socket, "invalidatetiles:", testname);
@@ -703,7 +703,7 @@ void TileCacheTests::testWriterAnyKey()
     getDocumentPathAndURL("empty.odt", documentPath, documentURL);
     Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
 
-    auto socket = *loadDocAndGetSocket(_uri, documentURL);
+    auto socket = loadDocAndGetSocket(_uri, documentURL);
 
     // Now test "usual" keycodes (TODO: whole 32-bit range)
     for (int i=0; i<0x1000; ++i)
@@ -783,7 +783,7 @@ void TileCacheTests::testWriterAnyKey()
 void TileCacheTests::testTileInvalidateCalc()
 {
     const std::string testname = "tileInvalidateCalc ";
-    auto socket = *loadDocAndGetSocket("empty.ods", _uri, testname);
+    auto socket = loadDocAndGetSocket("empty.ods", _uri, testname);
 
     std::string text = "Test. Now go 3 \"Enters\": Now after the enters, goes this text";
     for (char ch : text)
@@ -815,13 +815,13 @@ void TileCacheTests::tileInvalidatePart(const std::string& filename, const std::
 
     std::string documentPath, documentURL;
     getDocumentPathAndURL(filename, documentPath, documentURL);
-    auto socket1 = *loadDocAndGetSocket(_uri, documentURL);
+    auto socket1 = loadDocAndGetSocket(_uri, documentURL);
 
     sendTextFrame(socket1, "setclientpart part=2", testname1);
     assertResponseString(socket1, "setpart:", testname1);
     sendTextFrame(socket1, "mouse type=buttondown x=7886 y=8929 count=1 buttons=1 modifier=0", testname1);
 
-    auto socket2 = *loadDocAndGetSocket(_uri, documentURL);
+    auto socket2 = loadDocAndGetSocket(_uri, documentURL);
     sendTextFrame(socket2, "setclientpart part=5", testname2);
     assertResponseString(socket2, "setpart:", testname2);
     sendTextFrame(socket2, "mouse type=buttondown x=7886 y=8929 count=1 buttons=1 modifier=0", testname2);
@@ -855,7 +855,7 @@ void TileCacheTests::testTileInvalidatePartImpress()
     tileInvalidatePart("setclientpart.odp", "tileInvalidatePartImpress");
 }
 
-void TileCacheTests::checkTiles(Poco::Net::WebSocket& socket, const std::string& docType, const std::string& name)
+void TileCacheTests::checkTiles(std::shared_ptr<LOOLWebSocket>& socket, const std::string& docType, const std::string& name)
 {
     const std::string current = "current=";
     const std::string height = "height=";
@@ -922,7 +922,7 @@ void TileCacheTests::checkTiles(Poco::Net::WebSocket& socket, const std::string&
     }
 }
 
-void TileCacheTests::requestTiles(Poco::Net::WebSocket& socket, const int part, const int docWidth, const int docHeight, const std::string& name)
+void TileCacheTests::requestTiles(std::shared_ptr<LOOLWebSocket>& socket, const int part, const int docWidth, const int docHeight, const std::string& name)
 {
     // twips
     const int tileSize = 3840;
diff --git a/loolwsd/test/UnitAdmin.cpp b/loolwsd/test/UnitAdmin.cpp
index 9f704c1..96ccee8 100644
--- a/loolwsd/test/UnitAdmin.cpp
+++ b/loolwsd/test/UnitAdmin.cpp
@@ -45,14 +45,14 @@ private:
     std::string _jwtCookie;
     bool _isTestRunning = false;
     const Poco::URI _uri;
-    std::shared_ptr<Poco::Net::WebSocket> _adminWs;
+    std::shared_ptr<LOOLWebSocket> _adminWs;
 
     typedef TestResult (UnitAdmin::*AdminTest)(void);
     std::vector<AdminTest> _tests;
 
-    std::shared_ptr<Poco::Net::WebSocket> _docWs1;
-    std::shared_ptr<Poco::Net::WebSocket> _docWs2;
-    std::shared_ptr<Poco::Net::WebSocket> _docWs3;
+    std::shared_ptr<LOOLWebSocket> _docWs1;
+    std::shared_ptr<LOOLWebSocket> _docWs2;
+    std::shared_ptr<LOOLWebSocket> _docWs3;
     int _docPid1;
     int _docPid2;
     int _docPid3;
@@ -131,7 +131,7 @@ private:
         HTTPRequest request(HTTPRequest::HTTP_GET, "/lool/adminws/");
         std::unique_ptr<HTTPClientSession> session(UnitHTTP::createSession());
 
-        _adminWs = std::make_shared<Poco::Net::WebSocket>(*session, request, response);
+        _adminWs = std::make_shared<LOOLWebSocket>(*session, request, response);
         const std::string testMessage = "documents";
         std::unique_lock<std::mutex> lock(_messageReceivedMutex);
         _messageReceived.clear();
@@ -162,7 +162,7 @@ private:
         HTTPRequest request(HTTPRequest::HTTP_GET, "/lool/adminws/");
         std::unique_ptr<HTTPClientSession> session(UnitHTTP::createSession());
 
-        _adminWs = std::make_shared<Poco::Net::WebSocket>(*session, request, response);
+        _adminWs = std::make_shared<LOOLWebSocket>(*session, request, response);
         const std::string testMessage = "auth jwt=incorrectJWT";
         std::unique_lock<std::mutex> lock(_messageReceivedMutex);
         _messageReceived.clear();
@@ -193,7 +193,7 @@ private:
         HTTPRequest request(HTTPRequest::HTTP_GET, "/lool/adminws/");
         std::unique_ptr<HTTPClientSession> session(UnitHTTP::createSession());
 
-        _adminWs = std::make_shared<Poco::Net::WebSocket>(*session, request, response);
+        _adminWs = std::make_shared<LOOLWebSocket>(*session, request, response);
         const std::string authMessage = "auth jwt=" + _jwtCookie;
         _adminWs->sendFrame(authMessage.data(), authMessage.size());
 
@@ -216,7 +216,7 @@ private:
 
         std::unique_lock<std::mutex> lock(_messageReceivedMutex);
         _messageReceived.clear();
-        _docWs1 = std::make_shared<Poco::Net::WebSocket>(*session1, request1, response1);
+        _docWs1 = std::make_shared<LOOLWebSocket>(*session1, request1, response1);
         _docWs1->sendFrame(loadMessage1.data(), loadMessage1.size());
         if (_messageReceivedCV.wait_for(lock, std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == std::cv_status::timeout)
         {
@@ -244,7 +244,7 @@ private:
         // Open another view of same document
         lock.lock(); // lock _messageReceivedMutex
         _messageReceived.clear();
-        _docWs2 = std::make_shared<Poco::Net::WebSocket>(*session2, request1, response1);
+        _docWs2 = std::make_shared<LOOLWebSocket>(*session2, request1, response1);
         _docWs2->sendFrame(loadMessage1.data(), loadMessage1.size());
         if (_messageReceivedCV.wait_for(lock, std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == std::cv_status::timeout)
         {
@@ -279,7 +279,7 @@ private:
 
         lock.lock(); // lock _messageReceivedMutex
         _messageReceived.clear();
-        _docWs3 = std::make_shared<Poco::Net::WebSocket>(*session3, request2, response2);
+        _docWs3 = std::make_shared<LOOLWebSocket>(*session3, request2, response2);
         _docWs3->sendFrame(loadMessage2.data(), loadMessage2.size());
         if (_messageReceivedCV.wait_for(lock, std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == std::cv_status::timeout)
         {
diff --git a/loolwsd/test/UnitFonts.cpp b/loolwsd/test/UnitFonts.cpp
index c82dcbb..60312d4 100644
--- a/loolwsd/test/UnitFonts.cpp
+++ b/loolwsd/test/UnitFonts.cpp
@@ -41,7 +41,7 @@ namespace {
             return std::string("can't find unit_online_get_fonts hook");
     }
 
-    std::string readFontList(const std::shared_ptr< Poco::Net::WebSocket > &socket)
+    std::string readFontList(const std::shared_ptr<LOOLWebSocket> &socket)
     {
         int flags;
         char buffer[100 * 1000];
@@ -89,7 +89,7 @@ public:
         }
     }
 
-    virtual void newChild(const std::shared_ptr<Poco::Net::WebSocket> &socket) override
+    virtual void newChild(const std::shared_ptr<LOOLWebSocket> &socket) override
     {
         Log::info("Fetching font list from kit");
         socket->sendFrame("unit-getfontlist: \n",
@@ -106,7 +106,7 @@ public:
         if (type == UnitWSD::TestRequest::TEST_REQ_PRISONER &&
             request.getURI().find(UNIT_URI) == 0)
         {
-            auto ws = std::make_shared<Poco::Net::WebSocket>(request, response);
+            auto ws = std::make_shared<LOOLWebSocket>(request, response);
             _fontsBroker = readFontList(ws);
             check();
             return true;
@@ -133,7 +133,7 @@ public:
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET,
                                        std::string(UNIT_URI));
         Poco::Net::HTTPResponse response;
-        auto ws = std::make_shared<Poco::Net::WebSocket>(cs, request, response);
+        auto ws = std::make_shared<LOOLWebSocket>(cs, request, response);
         ws->setReceiveTimeout(0);
         Log::info("Fetching font list from forkit");
         std::string fontListMsg = getFontList() + "\n";
@@ -141,7 +141,7 @@ public:
     }
 
     // Called from WSD and handled inside the kit.
-    virtual bool filterKitMessage(const std::shared_ptr<Poco::Net::WebSocket> &ws,
+    virtual bool filterKitMessage(const std::shared_ptr<LOOLWebSocket> &ws,
                                   std::string &message) override
     {
         const std::string token = LOOLProtocol::getFirstToken(message);
diff --git a/loolwsd/test/UnitFuzz.cpp b/loolwsd/test/UnitFuzz.cpp
index 57622b3..7454aa4 100644
--- a/loolwsd/test/UnitFuzz.cpp
+++ b/loolwsd/test/UnitFuzz.cpp
@@ -17,12 +17,12 @@
 #include "Common.hpp"
 #include "IoUtil.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Unit.hpp"
 #include "Util.hpp"
 
 #include <Poco/Timestamp.h>
 #include <Poco/StringTokenizer.h>
-#include <Poco/Net/WebSocket.h>
 
 // Inside the WSD process
 class UnitFuzz : public UnitWSD
@@ -55,7 +55,7 @@ public:
     {
     }
 
-    virtual bool filterKitMessage(const std::shared_ptr<Poco::Net::WebSocket> & /* ws */,
+    virtual bool filterKitMessage(const std::shared_ptr<LOOLWebSocket> & /* ws */,
                                   std::string & /* message */) override
     {
         return false;
diff --git a/loolwsd/test/UnitPrefork.cpp b/loolwsd/test/UnitPrefork.cpp
index e6837f5..9f5463b 100644
--- a/loolwsd/test/UnitPrefork.cpp
+++ b/loolwsd/test/UnitPrefork.cpp
@@ -21,11 +21,11 @@
 
 #include <Poco/Timestamp.h>
 #include <Poco/StringTokenizer.h>
-#include <Poco/Net/WebSocket.h>
 
 #include "Common.hpp"
 #include "IoUtil.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Log.hpp"
 #include "Unit.hpp"
 #include "Util.hpp"
@@ -41,7 +41,7 @@ class UnitPrefork : public UnitWSD
     size_t _childDirty;
     std::mutex _mutex;
     std::condition_variable _cv;
-    std::vector< std::shared_ptr<Poco::Net::WebSocket> > _childSockets;
+    std::vector< std::shared_ptr<LOOLWebSocket> > _childSockets;
 
 public:
     UnitPrefork()
@@ -81,7 +81,7 @@ public:
         return true;
     }
 
-    virtual void newChild(const std::shared_ptr<Poco::Net::WebSocket> &socket) override
+    virtual void newChild(const std::shared_ptr<LOOLWebSocket> &socket) override
     {
         std::unique_lock<std::mutex> lock(_mutex);
 
@@ -286,7 +286,7 @@ public:
         }
     }
 
-    virtual bool filterKitMessage(const std::shared_ptr<Poco::Net::WebSocket> &ws,
+    virtual bool filterKitMessage(const std::shared_ptr<LOOLWebSocket> &ws,
                                   std::string &message) override
     {
         const auto token = LOOLProtocol::getFirstToken(message);
diff --git a/loolwsd/test/helpers.hpp b/loolwsd/test/helpers.hpp
index b6d6d78..4f12c2e 100644
--- a/loolwsd/test/helpers.hpp
+++ b/loolwsd/test/helpers.hpp
@@ -32,7 +32,6 @@
 #include <Poco/Net/PrivateKeyPassphraseHandler.h>
 #include <Poco/Net/SSLManager.h>
 #include <Poco/Net/Socket.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Path.h>
 #include <Poco/StreamCopier.h>
 #include <Poco/StringTokenizer.h>
@@ -42,6 +41,7 @@
 
 #include <Common.hpp>
 #include <LOOLProtocol.hpp>
+#include <LOOLWebSocket.hpp>
 #include <UserMessages.hpp>
 #include <Util.hpp>
 
@@ -121,14 +121,14 @@ void getDocumentPathAndURL(const std::string& docFilename, std::string& document
 }
 
 inline
-void sendTextFrame(Poco::Net::WebSocket& socket, const std::string& string, const std::string& name = "")
+void sendTextFrame(LOOLWebSocket& socket, const std::string& string, const std::string& name = "")
 {
     std::cerr << name << "Sending " << string.size() << " bytes: " << LOOLProtocol::getAbbreviatedMessage(string) << std::endl;
     socket.sendFrame(string.data(), string.size());
 }
 
 inline
-void sendTextFrame(const std::shared_ptr<Poco::Net::WebSocket>& socket, const std::string& string, const std::string& name = "")
+void sendTextFrame(const std::shared_ptr<LOOLWebSocket>& socket, const std::string& string, const std::string& name = "")
 {
     sendTextFrame(*socket, string, name);
 }
@@ -160,7 +160,7 @@ std::string getTestServerURI()
 }
 
 inline
-int getErrorCode(Poco::Net::WebSocket& ws, std::string& message)
+int getErrorCode(LOOLWebSocket& ws, std::string& message)
 {
     int flags = 0;
     int bytes = 0;
@@ -187,7 +187,7 @@ int getErrorCode(Poco::Net::WebSocket& ws, std::string& message)
 }
 
 inline
-std::vector<char> getResponseMessage(Poco::Net::WebSocket& ws, const std::string& prefix, std::string name = "", const size_t timeoutMs = 10000)
+std::vector<char> getResponseMessage(LOOLWebSocket& ws, const std::string& prefix, std::string name = "", const size_t timeoutMs = 10000)
 {
     name = name + '[' + prefix + "] ";
     try
@@ -289,7 +289,7 @@ std::vector<char> getResponseMessage(Poco::Net::WebSocket& ws, const std::string
 }
 
 inline
-std::vector<char> getResponseMessage(const std::shared_ptr<Poco::Net::WebSocket>& ws, const std::string& prefix, const std::string& name = "", const size_t timeoutMs = 10000)
+std::vector<char> getResponseMessage(const std::shared_ptr<LOOLWebSocket>& ws, const std::string& prefix, const std::string& name = "", const size_t timeoutMs = 10000)
 {
     return getResponseMessage(*ws, prefix, name, timeoutMs);
 }
@@ -319,7 +319,7 @@ std::string assertNotInResponse(T& ws, const std::string& prefix, const std::str
 }
 
 inline
-bool isDocumentLoaded(Poco::Net::WebSocket& ws, const std::string& name = "", bool isView = true)
+bool isDocumentLoaded(LOOLWebSocket& ws, const std::string& name = "", bool isView = true)
 {
     const std::string prefix = isView ? "status:" : "statusindicatorfinish:";
     const auto message = getResponseString(ws, prefix, name);
@@ -327,7 +327,7 @@ bool isDocumentLoaded(Poco::Net::WebSocket& ws, const std::string& name = "", bo
 }
 
 inline
-bool isDocumentLoaded(std::shared_ptr<Poco::Net::WebSocket>& ws, const std::string& name = "", bool isView = true)
+bool isDocumentLoaded(std::shared_ptr<LOOLWebSocket>& ws, const std::string& name = "", bool isView = true)
 {
     return isDocumentLoaded(*ws, name, isView);
 }
@@ -337,7 +337,7 @@ bool isDocumentLoaded(std::shared_ptr<Poco::Net::WebSocket>& ws, const std::stri
 // The result, it is mostly time outs to get messages in the unit test and it could fail.
 // connectLOKit ensures the websocket is connected to a kit process.
 inline
-std::shared_ptr<Poco::Net::WebSocket>
+std::shared_ptr<LOOLWebSocket>
 connectLOKit(const Poco::URI& uri,
              Poco::Net::HTTPRequest& request,
              Poco::Net::HTTPResponse& response,
@@ -349,7 +349,7 @@ connectLOKit(const Poco::URI& uri,
         std::unique_ptr<Poco::Net::HTTPClientSession> session(createSession(uri));
 
         std::cerr << name << "Connecting... " << std::endl;
-        auto ws = std::make_shared<Poco::Net::WebSocket>(*session, request, response);
+        auto ws = std::make_shared<LOOLWebSocket>(*session, request, response);
         getResponseMessage(ws, "statusindicator: ready", name);
 
         return ws;
@@ -360,7 +360,7 @@ connectLOKit(const Poco::URI& uri,
 }
 
 inline
-std::shared_ptr<Poco::Net::WebSocket> loadDocAndGetSocket(const Poco::URI& uri, const std::string& documentURL, const std::string& name = "", bool isView = true)
+std::shared_ptr<LOOLWebSocket> loadDocAndGetSocket(const Poco::URI& uri, const std::string& documentURL, const std::string& name = "", bool isView = true)
 {
     try
     {
@@ -385,7 +385,7 @@ std::shared_ptr<Poco::Net::WebSocket> loadDocAndGetSocket(const Poco::URI& uri,
 }
 
 inline
-std::shared_ptr<Poco::Net::WebSocket> loadDocAndGetSocket(const std::string& docFilename, const Poco::URI& uri, const std::string& name = "", bool isView = true)
+std::shared_ptr<LOOLWebSocket> loadDocAndGetSocket(const std::string& docFilename, const Poco::URI& uri, const std::string& name = "", bool isView = true)
 {
     try
     {
@@ -404,7 +404,7 @@ std::shared_ptr<Poco::Net::WebSocket> loadDocAndGetSocket(const std::string& doc
 
 inline
 void SocketProcessor(const std::string& name,
-                     const std::shared_ptr<Poco::Net::WebSocket>& socket,
+                     const std::shared_ptr<LOOLWebSocket>& socket,
                      const std::function<bool(const std::string& msg)>& handler,
                      const size_t timeoutMs = 10000)
 {
@@ -457,13 +457,13 @@ void parseDocSize(const std::string& message, const std::string& type,
 }
 
 inline
-std::vector<char> getTileMessage(Poco::Net::WebSocket& ws, const std::string& name = "")
+std::vector<char> getTileMessage(LOOLWebSocket& ws, const std::string& name = "")
 {
     return getResponseMessage(ws, "tile", name);
 }
 
 inline
-std::vector<char> assertTileMessage(Poco::Net::WebSocket& ws, const std::string& name = "")
+std::vector<char> assertTileMessage(LOOLWebSocket& ws, const std::string& name = "")
 {
     const auto response = getTileMessage(ws, name);
 
@@ -482,7 +482,7 @@ std::vector<char> assertTileMessage(Poco::Net::WebSocket& ws, const std::string&
 }
 
 inline
-std::vector<char> assertTileMessage(const std::shared_ptr<Poco::Net::WebSocket>& ws, const std::string& name = "")
+std::vector<char> assertTileMessage(const std::shared_ptr<LOOLWebSocket>& ws, const std::string& name = "")
 {
     return assertTileMessage(*ws, name);
 }
@@ -521,25 +521,25 @@ inline int getCharKey(char ch, SpecialKey specialKeys)
     return result | specialKeys;
 }
 
-inline void sendKeyEvent(Poco::Net::WebSocket& socket, const char* type, int chr, int key, const std::string& testname = "")
+inline void sendKeyEvent(std::shared_ptr<LOOLWebSocket>& socket, const char* type, int chr, int key, const std::string& testname = "")
 {
     std::ostringstream ssIn;
     ssIn << "key type=" << type << " char=" << chr << " key=" << key;
     sendTextFrame(socket, ssIn.str(), testname);
 }
 
-inline void sendKeyPress(Poco::Net::WebSocket& socket, int chr, int key, const std::string& testname)
+inline void sendKeyPress(std::shared_ptr<LOOLWebSocket>& socket, int chr, int key, const std::string& testname)
 {
     sendKeyEvent(socket, "input", chr, key, testname);
     sendKeyEvent(socket, "up", chr, key, testname);
 }
 
-inline void sendChar(Poco::Net::WebSocket& socket, char ch, SpecialKey specialKeys=skNone, const std::string& testname = "")
+inline void sendChar(std::shared_ptr<LOOLWebSocket>& socket, char ch, SpecialKey specialKeys=skNone, const std::string& testname = "")
 {
     sendKeyPress(socket, getCharChar(ch, specialKeys), getCharKey(ch, specialKeys), testname);
 }
 
-inline void sendText(Poco::Net::WebSocket& socket, const std::string& text, const std::string& testname = "")
+inline void sendText(std::shared_ptr<LOOLWebSocket>& socket, const std::string& text, const std::string& testname = "")
 {
     for (char ch : text)
     {
diff --git a/loolwsd/test/httpcrashtest.cpp b/loolwsd/test/httpcrashtest.cpp
index ecaf4af..3bd4bcd 100644
--- a/loolwsd/test/httpcrashtest.cpp
+++ b/loolwsd/test/httpcrashtest.cpp
@@ -30,7 +30,6 @@
 #include <Poco/Net/PrivateKeyPassphraseHandler.h>
 #include <Poco/Net/SSLManager.h>
 #include <Poco/Net/Socket.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Path.h>
 #include <Poco/StreamCopier.h>
 #include <Poco/StringTokenizer.h>
@@ -42,6 +41,7 @@
 #include <UserMessages.hpp>
 #include <Util.hpp>
 #include <LOOLProtocol.hpp>
+#include <LOOLWebSocket.hpp>
 #include "helpers.hpp"
 #include "countloolkits.hpp"
 
@@ -144,7 +144,7 @@ void HTTPCrashTest::testCrashKit()
     const auto testname = "crashKit ";
     try
     {
-        auto socket = *loadDocAndGetSocket("empty.odt", _uri, testname);
+        auto socket = loadDocAndGetSocket("empty.odt", _uri, testname);
 
         killLoKitProcesses();
 
@@ -156,7 +156,7 @@ void HTTPCrashTest::testCrashKit()
         getResponseMessage(socket, "", testname, 1000);
 
         // 5 seconds timeout
-        socket.setReceiveTimeout(5000000);
+        socket->setReceiveTimeout(5000000);
 
         // receive close frame handshake
         int bytes;
@@ -164,16 +164,16 @@ void HTTPCrashTest::testCrashKit()
         char buffer[READ_BUFFER_SIZE];
         do
         {
-            bytes = socket.receiveFrame(buffer, sizeof(buffer), flags);
+            bytes = socket->receiveFrame(buffer, sizeof(buffer), flags);
             std::cerr << testname << "Got " << LOOLProtocol::getAbbreviatedFrameDump(buffer, bytes, flags) << std::endl;
         }
         while ((flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);
 
         // respond close frame
-        socket.shutdown();
+        socket->shutdown();
 
         // no more messages is received.
-        bytes = socket.receiveFrame(buffer, sizeof(buffer), flags);
+        bytes = socket->receiveFrame(buffer, sizeof(buffer), flags);
         CPPUNIT_ASSERT_MESSAGE("Expected no more data", bytes <= 2); // The 2-byte marker is ok.
         CPPUNIT_ASSERT_EQUAL(0x88, flags);
     }
diff --git a/loolwsd/test/httpwserror.cpp b/loolwsd/test/httpwserror.cpp
index 1d686e4..0bd8b65 100644
--- a/loolwsd/test/httpwserror.cpp
+++ b/loolwsd/test/httpwserror.cpp
@@ -17,13 +17,13 @@
 #include <Poco/Net/HTTPResponse.h>
 #include <Poco/Net/HTTPSClientSession.h>
 #include <Poco/Net/NetException.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/URI.h>
 
 #include <cppunit/extensions/HelperMacros.h>
 
 #include "Common.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "helpers.hpp"
 #include "countloolkits.hpp"
 
@@ -101,7 +101,7 @@ void HTTPWSError::testMaxDocuments()
     try
     {
         // Load a document.
-        std::vector<std::shared_ptr<Poco::Net::WebSocket>> docs;
+        std::vector<std::shared_ptr<LOOLWebSocket>> docs;
 
         std::cerr << "Loading max number of documents: " << MAX_DOCUMENTS << std::endl;
         for (int it = 1; it <= MAX_DOCUMENTS; ++it)
@@ -118,7 +118,7 @@ void HTTPWSError::testMaxDocuments()
         getDocumentPathAndURL("empty.odt", docPath, docURL);
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, docURL);
         std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
-        Poco::Net::WebSocket socket(*session, request, _response);
+        LOOLWebSocket socket(*session, request, _response);
 
         // send loolclient, load and partpagerectangles
         sendTextFrame(socket, "loolclient ", testname);
@@ -157,11 +157,11 @@ void HTTPWSError::testMaxConnections()
         auto socket = loadDocAndGetSocket(_uri, docURL, testname);
         std::cerr << "Opened connect #1 of " << MAX_CONNECTIONS << std::endl;
 
-        std::vector<std::shared_ptr<Poco::Net::WebSocket>> views;
+        std::vector<std::shared_ptr<LOOLWebSocket>> views;
         for(int it = 1; it < MAX_CONNECTIONS; it++)
         {
             std::unique_ptr<Poco::Net::HTTPClientSession> session(createSession(_uri));
-            auto ws = std::make_shared<Poco::Net::WebSocket>(*session, request, _response);
+            auto ws = std::make_shared<LOOLWebSocket>(*session, request, _response);
             views.emplace_back(ws);
             std::cerr << "Opened connect #" << (it+1) << " of " << MAX_CONNECTIONS << std::endl;
         }
@@ -170,7 +170,7 @@ void HTTPWSError::testMaxConnections()
 
         // try to connect MAX_CONNECTIONS + 1
         std::unique_ptr<Poco::Net::HTTPClientSession> session(createSession(_uri));
-        Poco::Net::WebSocket socketN(*session, request, _response);
+        LOOLWebSocket socketN(*session, request, _response);
 
         // send loolclient, load and partpagerectangles
         sendTextFrame(socketN, "loolclient ", testname);
diff --git a/loolwsd/test/httpwstest.cpp b/loolwsd/test/httpwstest.cpp
index bbb4d61..93a024b 100644
--- a/loolwsd/test/httpwstest.cpp
+++ b/loolwsd/test/httpwstest.cpp
@@ -30,7 +30,6 @@
 #include <Poco/Net/PrivateKeyPassphraseHandler.h>
 #include <Poco/Net/SSLManager.h>
 #include <Poco/Net/Socket.h>
-#include <Poco/Net/WebSocket.h>
 #include <Poco/Path.h>
 #include <Poco/RegularExpression.h>
 #include <Poco/StreamCopier.h>
@@ -42,6 +41,7 @@
 
 #include "Common.hpp"
 #include "LOOLProtocol.hpp"
+#include <LOOLWebSocket.hpp>
 #include "Png.hpp"
 #include "UserMessages.hpp"
 #include "Util.hpp"
@@ -154,7 +154,7 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture
                    int& cursorWidth,
                    int& cursorHeight);
 
-    void limitCursor(std::function<void(const std::shared_ptr<Poco::Net::WebSocket>& socket,
+    void limitCursor(std::function<void(const std::shared_ptr<LOOLWebSocket>& socket,
                                         int cursorX, int cursorY,
                                         int cursorWidth, int cursorHeight,
                                         int docWidth, int docHeight)> keyhandler,
@@ -165,7 +165,7 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture
     std::string getFontList(const std::string& message);
     void testStateChanged(const std::string& filename, std::vector<std::string>& vecComands);
     double getColRowSize(const std::string& property, const std::string& message, int index);
-    double getColRowSize(const std::shared_ptr<Poco::Net::WebSocket>& socket, const std::string& item, int index);
+    double getColRowSize(const std::shared_ptr<LOOLWebSocket>& socket, const std::string& item, int index);
     void testEachView(const std::string& doc, const std::string& type, const std::string& protocol, const std::string& view, const std::string& testname);
 
 public:
@@ -249,7 +249,7 @@ void HTTPWSTest::testHandShake()
         Poco::Net::HTTPResponse response;
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
         std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(_uri));
-        Poco::Net::WebSocket socket(*session, request, response);
+        LOOLWebSocket socket(*session, request, response);
         socket.setReceiveTimeout(0);
 
         int flags = 0;
@@ -298,13 +298,13 @@ void HTTPWSTest::testCloseAfterClose()
     const auto testname = "closeAfterClose ";
     try
     {
-        auto socket = *loadDocAndGetSocket("hello.odt", _uri, testname);
+        auto socket = loadDocAndGetSocket("hello.odt", _uri, testname);
 
         // send normal socket shutdown
-        socket.shutdown();
+        socket->shutdown();
 
         // 5 seconds timeout
-        socket.setReceiveTimeout(5000000);
+        socket->setReceiveTimeout(5000000);
 
         // receive close frame handshake
         int bytes;
@@ -312,12 +312,12 @@ void HTTPWSTest::testCloseAfterClose()
         char buffer[READ_BUFFER_SIZE];
         do
         {
-            bytes = socket.receiveFrame(buffer, sizeof(buffer), flags);
+            bytes = socket->receiveFrame(buffer, sizeof(buffer), flags);
         }
         while (bytes && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);
 
         // no more messages is received.
-        bytes = socket.receiveFrame(buffer, sizeof(buffer), flags);
+        bytes = socket->receiveFrame(buffer, sizeof(buffer), flags);
         std::cout << "Received " << bytes << " bytes, flags: "<< std::hex << flags << std::dec << std::endl;
         CPPUNIT_ASSERT_EQUAL(0, bytes);
         CPPUNIT_ASSERT_EQUAL(0, flags);
@@ -387,7 +387,7 @@ void HTTPWSTest::testBadLoad()
         getDocumentPathAndURL("hello.odt", documentPath, documentURL);
 
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
-        Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response);
+        auto socket = connectLOKit(_uri, request, _response);
 
         // Before loading request status.
         sendTextFrame(socket, "status");
@@ -419,8 +419,8 @@ void HTTPWSTest::testGetTextSelection()
         std::string documentPath, documentURL;
         getDocumentPathAndURL("hello.odt", documentPath, documentURL);
 
-        auto socket = *loadDocAndGetSocket(_uri, documentURL, testname);
-        auto socket2 = *loadDocAndGetSocket(_uri, documentURL, testname);
+        auto socket = loadDocAndGetSocket(_uri, documentURL, testname);
+        auto socket2 = loadDocAndGetSocket(_uri, documentURL, testname);
 
         sendTextFrame(socket, "uno .uno:SelectAll", testname);
         sendTextFrame(socket, "gettextselection mimetype=text/plain;charset=utf-8", testname);
@@ -446,9 +446,9 @@ void HTTPWSTest::testSaveOnDisconnect()
     int kitcount = -1;
     try
     {
-        auto socket = *loadDocAndGetSocket(_uri, documentURL, testname);
+        auto socket = loadDocAndGetSocket(_uri, documentURL, testname);
 
-        auto socket2 = *loadDocAndGetSocket(_uri, documentURL, testname);
+        auto socket2 = loadDocAndGetSocket(_uri, documentURL, testname);
         sendTextFrame(socket2, "userinactive");
 
         sendTextFrame(socket, "uno .uno:SelectAll", testname);
@@ -470,8 +470,8 @@ void HTTPWSTest::testSaveOnDisconnect()
 
         // Shutdown abruptly.
         std::cerr << "Closing connection after pasting." << std::endl;
-        socket.shutdown();
-        socket2.shutdown();
+        socket->shutdown();
+        socket2->shutdown();
     }
     catch (const Poco::Exception& exc)
     {
@@ -484,7 +484,7 @@ void HTTPWSTest::testSaveOnDisconnect()
     try
     {
         // Load the same document and check that the last changes (pasted text) is saved.
-        auto socket = *loadDocAndGetSocket(_uri, documentURL, testname);
+        auto socket = loadDocAndGetSocket(_uri, documentURL, testname);
 
         // Should have no new instances.
         CPPUNIT_ASSERT_EQUAL(kitcount, countLoolKitProcesses(kitcount));
@@ -509,7 +509,7 @@ void HTTPWSTest::testReloadWhileDisconnecting()
         std::string documentPath, documentURL;
         getDocumentPathAndURL("hello.odt", documentPath, documentURL);
 
-        auto socket = *loadDocAndGetSocket(_uri, documentURL, testname);
+        auto socket = loadDocAndGetSocket(_uri, documentURL, testname);
 
         sendTextFrame(socket, "uno .uno:SelectAll", testname);
         sendTextFrame(socket, "uno .uno:Delete", testname);
@@ -524,11 +524,11 @@ void HTTPWSTest::testReloadWhileDisconnecting()
 
         // Shutdown abruptly.
         std::cerr << "Closing connection after pasting." << std::endl;
-        socket.shutdown();
+        socket->shutdown();
 
         // Load the same document and check that the last changes (pasted text) is saved.
         std::cout << "Loading again." << std::endl;
-        socket = *loadDocAndGetSocket(_uri, documentURL, testname);
+        socket = loadDocAndGetSocket(_uri, documentURL, testname);
 
         // Should have no new instances.
         CPPUNIT_ASSERT_EQUAL(kitcount, countLoolKitProcesses(kitcount));
@@ -639,7 +639,7 @@ void HTTPWSTest::testRenderingOptions()
         const std::string options = "{\"rendering\":{\".uno:HideWhitespace\":{\"type\":\"boolean\",\"value\":\"true\"}}}";
 
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
-        Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response);
+        auto socket = connectLOKit(_uri, request, _response);
 
         sendTextFrame(socket, "load url=" + documentURL + " options=" + options);
         sendTextFrame(socket, "status");
@@ -671,7 +671,7 @@ void HTTPWSTest::testPasswordProtectedDocumentWithoutPassword()
         getDocumentPathAndURL("password-protected.ods", documentPath, documentURL);
 
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
-        Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response);
+        auto socket = connectLOKit(_uri, request, _response);
 
         // Send a load request without password first
         sendTextFrame(socket, "load url=" + documentURL);
@@ -702,7 +702,7 @@ void HTTPWSTest::testPasswordProtectedDocumentWithWrongPassword()
         getDocumentPathAndURL("password-protected.ods", documentPath, documentURL);
 
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
-        Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response);
+        auto socket = connectLOKit(_uri, request, _response);
 
         // Send a load request with incorrect password
         sendTextFrame(socket, "load url=" + documentURL + " password=2");
@@ -732,7 +732,7 @@ void HTTPWSTest::testPasswordProtectedDocumentWithCorrectPassword()
         getDocumentPathAndURL("password-protected.ods", documentPath, documentURL);
 
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
-        Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response);
+        auto socket = connectLOKit(_uri, request, _response);
 
         // Send a load request with correct password
         sendTextFrame(socket, "load url=" + documentURL + " password=1");
@@ -762,7 +762,7 @@ void HTTPWSTest::testInsertDelete()
         getDocumentPathAndURL("insert-delete.odp", documentPath, documentURL);
 
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
-        Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response);
+        auto socket = connectLOKit(_uri, request, _response);
 
         sendTextFrame(socket, "load url=" + documentURL);
         CPPUNIT_ASSERT_MESSAGE("cannot load the document " + documentURL, isDocumentLoaded(socket));
@@ -857,7 +857,7 @@ void HTTPWSTest::testSlideShow()
         getDocumentPathAndURL("setclientpart.odp", documentPath, documentURL);
 
         Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
-        Poco::Net::WebSocket socket = *connectLOKit(_uri, request, _response);
+        auto socket = connectLOKit(_uri, request, _response);
 
         sendTextFrame(socket, "load url=" + documentURL, testname);
         CPPUNIT_ASSERT_MESSAGE("cannot load the document " + documentURL, isDocumentLoaded(socket));
@@ -957,7 +957,7 @@ void HTTPWSTest::testMaxColumn()
     {
         limitCursor(
             // move cursor to last column
-            [](const std::shared_ptr<Poco::Net::WebSocket>& socket,
+            [](const std::shared_ptr<LOOLWebSocket>& socket,
                int cursorX, int cursorY, int cursorWidth, int cursorHeight,
                int docWidth, int docHeight)
             {
@@ -996,7 +996,7 @@ void HTTPWSTest::testMaxRow()
     {
         limitCursor(
             // move cursor to last row
-            [](const std::shared_ptr<Poco::Net::WebSocket>& socket,
+            [](const std::shared_ptr<LOOLWebSocket>& socket,
                int cursorX, int cursorY, int cursorWidth, int cursorHeight,
                int docWidth, int docHeight)
             {
@@ -1100,7 +1100,7 @@ void HTTPWSTest::getCursor(const std::string& message,
     CPPUNIT_ASSERT(cursorHeight >= 0);
 }
 
-void HTTPWSTest::limitCursor(std::function<void(const std::shared_ptr<Poco::Net::WebSocket>& socket,
+void HTTPWSTest::limitCursor(std::function<void(const std::shared_ptr<LOOLWebSocket>& socket,
                                                 int cursorX, int cursorY,
                                                 int cursorWidth, int cursorHeight,
                                                 int docWidth, int docHeight)> keyhandler,
@@ -1421,7 +1421,7 @@ void HTTPWSTest::testFontList()
     try
     {
         // Load a document
-        auto socket = *loadDocAndGetSocket("setclientpart.odp", _uri, testname);
+        auto socket = loadDocAndGetSocket("setclientpart.odp", _uri, testname);
 
         sendTextFrame(socket, "commandvalues command=.uno:CharFontName", testname);
         const auto response = getResponseMessage(socket, "commandvalues:", testname);
@@ -1664,7 +1664,7 @@ double HTTPWSTest::getColRowSize(const std::string& property, const std::string&
     return item->getValue<double>("size");
 }
 
-double HTTPWSTest::getColRowSize(const std::shared_ptr<Poco::Net::WebSocket>& socket, const std::string& item, int index)
+double HTTPWSTest::getColRowSize(const std::shared_ptr<LOOLWebSocket>& socket, const std::string& item, int index)
 {
     std::vector<char> response;
     response = getResponseMessage(socket, "commandvalues:", "testColumnRowResize ");
@@ -1879,7 +1879,7 @@ void HTTPWSTest::testEachView(const std::string& doc, const std::string& type,
         getDocumentPathAndURL(doc, documentPath, documentURL);
 
         int itView = 0;
-        auto socket = *loadDocAndGetSocket(_uri, documentURL, Poco::format(view, itView));
+        auto socket = loadDocAndGetSocket(_uri, documentURL, Poco::format(view, itView));
 
         // Check document size
         sendTextFrame(socket, "status", Poco::format(view, itView));
@@ -1904,7 +1904,7 @@ void HTTPWSTest::testEachView(const std::string& doc, const std::string& type,
         CPPUNIT_ASSERT_MESSAGE(Poco::format(error, itView, protocol), !response.empty());
 
         // Connect and load 0..N Views, where N<=limit
-        std::vector<std::shared_ptr<Poco::Net::WebSocket>> views;
+        std::vector<std::shared_ptr<LOOLWebSocket>> views;
 #if MAX_DOCUMENTS > 0
         const auto limit = std::min(5, MAX_DOCUMENTS - 1); // +1 connection above
 #else
@@ -1960,7 +1960,7 @@ void HTTPWSTest::testGraphicInvalidate()
     try
     {
         // Load a document.
-        auto socket = *loadDocAndGetSocket("shape.ods", _uri, testname);
+        auto socket = loadDocAndGetSocket("shape.ods", _uri, testname);
 
         // Send click message
         sendTextFrame(socket, "mouse type=buttondown x=1035 y=400 count=1 buttons=1 modifier=0", testname);
@@ -1993,7 +1993,7 @@ void HTTPWSTest::testCursorPosition()
         std::string response;
 
         getDocumentPathAndURL("Example.odt", docPath, docURL);
-        auto socket0 = *loadDocAndGetSocket(_uri, docURL, testname);
+        auto socket0 = loadDocAndGetSocket(_uri, docURL, testname);
 
         // receive cursor position
         response = getResponseString(socket0, "invalidatecursor:", testname);
@@ -2001,7 +2001,7 @@ void HTTPWSTest::testCursorPosition()
         CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), cursorTokens.count());
 
         // Create second view
-        auto socket1 = *loadDocAndGetSocket(_uri, docURL, testname);
+        auto socket1 = loadDocAndGetSocket(_uri, docURL, testname);
 
         //receive view cursor position
         response = getResponseString(socket1, "invalidateviewcursor:", testname);
@@ -2044,7 +2044,7 @@ void HTTPWSTest::testAlertAllUsers()
         for (int i = 0; i < 2; i++)
             request[i] = new Poco::Net::HTTPRequest(Poco::Net::HTTPRequest::HTTP_GET, docURL[i]);
 
-        std::shared_ptr<Poco::Net::WebSocket> socket[4];
+        std::shared_ptr<LOOLWebSocket> socket[4];
         for (int i = 0; i < 4; i++)
         {
             socket[i] = connectLOKit(_uri, *(request[i/2]), _response);
@@ -2082,8 +2082,8 @@ void HTTPWSTest::testViewInfoMsg()
     getDocumentPathAndURL("hello.odt", docPath, docURL);
 
     Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, docURL);
-    Poco::Net::WebSocket socket0 = *connectLOKit(_uri, request, _response);
-    Poco::Net::WebSocket socket1 = *connectLOKit(_uri, request, _response);
+    auto socket0 = connectLOKit(_uri, request, _response);
+    auto socket1 = connectLOKit(_uri, request, _response);
 
     std::string response;
     int part, parts, width, height;


More information about the Libreoffice-commits mailing list