[Libreoffice-commits] online.git: wsd/LOOLWebSocket.hpp

Ashod Nakashian ashod.nakashian at collabora.co.uk
Tue Dec 13 04:36:46 UTC 2016


 wsd/LOOLWebSocket.hpp |   53 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 11 deletions(-)

New commits:
commit aa1d721444c757e84db6c64a1082773483bdf2a1
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Mon Dec 12 23:08:01 2016 -0500

    loolwsd: harden against socket errors and lock while receiving
    
    Change-Id: I402d387272e0e30d2fe035842c50f40c3806e20d
    Reviewed-on: https://gerrit.libreoffice.org/31933
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/LOOLWebSocket.hpp b/wsd/LOOLWebSocket.hpp
index d29d429..3f86acd 100644
--- a/wsd/LOOLWebSocket.hpp
+++ b/wsd/LOOLWebSocket.hpp
@@ -32,7 +32,7 @@ private:
     std::mutex _mutex;
 
 #if ENABLE_DEBUG
-    std::chrono::milliseconds getWebSocketDelay()
+    static std::chrono::milliseconds getWebSocketDelay()
     {
         unsigned long baseDelay = 0;
         unsigned long jitter = 0;
@@ -89,20 +89,33 @@ public:
         // Delay receiving the frame
         std::this_thread::sleep_for(getWebSocketDelay());
 #endif
-        // Timeout given is in microseconds.
-        static const Poco::Timespan waitTime(POLL_TIMEOUT_MS * 1000);
+        // Timeout is in microseconds. We don't need this, except to yield the cpu.
+        static const Poco::Timespan waitTime(POLL_TIMEOUT_MS * 1000 / 10);
+        static const Poco::Timespan waitZero(0);
+        std::unique_lock<std::mutex> lock(_mutex);
 
         while (poll(waitTime, Poco::Net::Socket::SELECT_READ))
         {
             const int n = Poco::Net::WebSocket::receiveFrame(buffer, length, flags);
+
             LOG_TRC("Got frame: " << LOOLProtocol::getAbbreviatedFrameDump(buffer, n, flags));
-            if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PING)
+
+            if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PING &&
+                (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
             {
-                sendFrame(buffer, n, WebSocket::FRAME_FLAG_FIN | WebSocket::FRAME_OP_PONG);
+                // Echo back the ping message.
+                if (poll(waitZero, Socket::SelectMode::SELECT_ERROR) ||
+                    !poll(waitZero, Socket::SelectMode::SELECT_WRITE) ||
+                    Poco::Net::WebSocket::sendFrame(buffer, n, 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)
+            else if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PONG &&
+                     (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
             {
-                // In case we do send pongs in the future.
+                // In case we do send pings in the future.
             }
             else
             {
@@ -110,6 +123,7 @@ public:
             }
         }
 
+        // Not ready for read.
         return -1;
     }
 
@@ -120,23 +134,40 @@ public:
         // Delay sending the frame
         std::this_thread::sleep_for(getWebSocketDelay());
 #endif
+        static const Poco::Timespan waitZero(0);
         std::unique_lock<std::mutex> lock(_mutex);
 
         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 (!poll(waitZero, Socket::SelectMode::SELECT_ERROR) &&
+                poll(waitZero, Socket::SelectMode::SELECT_WRITE) &&
+                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);
+        int result = -1;
+        if (!poll(waitZero, Socket::SelectMode::SELECT_ERROR) &&
+            poll(waitZero, Socket::SelectMode::SELECT_WRITE))
+        {
+            result = Poco::Net::WebSocket::sendFrame(buffer, length, flags);
+        }
 
         lock.unlock();
 
         if (result != length)
         {
             LOG_ERR("Sent incomplete message, expected " << length << " bytes but sent " << result <<
-                    " while sending: " << LOOLProtocol::getAbbreviatedFrameDump(buffer, length, flags));
+                    " for: " << LOOLProtocol::getAbbreviatedFrameDump(buffer, length, flags));
         }
         else
         {


More information about the Libreoffice-commits mailing list