[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-2-0' - wsd/LOOLWebSocket.hpp

Ashod Nakashian ashod.nakashian at collabora.co.uk
Mon Feb 13 15:03:51 UTC 2017


 wsd/LOOLWebSocket.hpp |   34 +++++++++++++++++++++++++++-------
 1 file changed, 27 insertions(+), 7 deletions(-)

New commits:
commit f7bbd9072db7a71ff28ba178d5ca9eebe6cf4397
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Sun Feb 12 23:47:43 2017 -0500

    wsd: use separate read/write locks in LOOLWebSocket
    
    When two sockets send data to each other in blocking
    mode, they can both wait until the other end-point's
    buffers are free enough to receive the data being
    sent. Since in LOOLWebSocket we lock both send and
    receive with the same lock, this prevents the
    reader thread from freeing the buffer while we try
    to send data. But since our peer is in the same
    dilemma, neither of us will make progress--deadlock.
    
    Since sockets are full-duplex, they are capable of
    handling two way communication concurrently. Poco
    seems to not share data between them either, so
    this seems safe.
    
    Change-Id: I1fd68cd4fb3b4250b93c8f94cd42e49ee78f6650
    Reviewed-on: https://gerrit.libreoffice.org/34194
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/34213
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Tested-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/wsd/LOOLWebSocket.hpp b/wsd/LOOLWebSocket.hpp
index 86dc659..22e2891 100644
--- a/wsd/LOOLWebSocket.hpp
+++ b/wsd/LOOLWebSocket.hpp
@@ -31,10 +31,11 @@
 class LOOLWebSocket : public Poco::Net::WebSocket
 {
 private:
-    std::mutex _mutex;
+    std::mutex _mutexRead;
+    std::mutex _mutexWrite;
 
 #if ENABLE_DEBUG
-    std::chrono::milliseconds getWebSocketDelay()
+    static std::chrono::milliseconds getWebSocketDelay()
     {
         unsigned long baseDelay = 0;
         unsigned long jitter = 0;
@@ -108,7 +109,10 @@ public:
 
         while (poll(waitTime, Poco::Net::Socket::SELECT_READ))
         {
+            std::unique_lock<std::mutex> lockRead(_mutexRead);
             const int n = Poco::Net::WebSocket::receiveFrame(buffer, length, flags);
+            lockRead.unlock();
+
             if (n <= 0)
             {
                 LOG_TRC("Got nothing (" << n << ")");
@@ -119,11 +123,17 @@ public:
             }
             if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PING)
             {
-                sendFrame(buffer, n, WebSocket::FRAME_FLAG_FIN | WebSocket::FRAME_OP_PONG);
+                // Echo back the ping message.
+                std::unique_lock<std::mutex> lock(_mutexWrite);
+                if (Poco::Net::WebSocket::sendFrame(buffer, n, static_cast<int>(WebSocket::FRAME_FLAG_FIN) | WebSocket::FRAME_OP_PONG) != n)
+                {
+                    LOG_WRN("Sending Pong failed.");
+                    return -1;
+                }
             }
             else if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PONG)
             {
-                // In case we do send pongs in the future.
+                // In case we do send pings in the future.
             }
             else
             {
@@ -131,6 +141,7 @@ public:
             }
         }
 
+        // Not ready for read.
         return -1;
     }
 
@@ -141,13 +152,22 @@ public:
         // Delay sending the frame
         std::this_thread::sleep_for(getWebSocketDelay());
 #endif
-        std::unique_lock<std::mutex> lock(_mutex);
+        std::unique_lock<std::mutex> lock(_mutexWrite);
 
         if (length >= LARGE_MESSAGE_SIZE)
         {
             const std::string nextmessage = "nextmessage: size=" + std::to_string(length);
-            Poco::Net::WebSocket::sendFrame(nextmessage.data(), nextmessage.size());
-            LOG_TRC("Message is long, sent " + nextmessage);
+            const int size = nextmessage.size();
+
+            if (Poco::Net::WebSocket::sendFrame(nextmessage.data(), size) == size)
+            {
+                LOG_TRC("Sent long message preample: " + nextmessage);
+            }
+            else
+            {
+                LOG_WRN("Failed to send long message preample.");
+                return -1;
+            }
         }
 
         const int result = Poco::Net::WebSocket::sendFrame(buffer, length, flags);


More information about the Libreoffice-commits mailing list