loleaflet/src/core/Socket.js |   46 +++++++++++++++++++------------------
 loleaflet/src/map/Map.js     |    8 +++---
 loolwsd/LOOLWSD.cpp          |   53 +++++++++++++++++++++++++++++++++++++++----
 loolwsd/UserMessages.hpp     |    3 +-
 loolwsd/test/helpers.hpp     |    2 -
 loolwsd/test/httpwserror.cpp |   33 +++++++++++---------------
 6 files changed, 94 insertions(+), 51 deletions(-)

New commits:
commit e766e82f3d118ef0c5f2d8dac9a14255232b2dd8
Author: Henry Castro <hcas...@collabora.com>
Date:   Thu Sep 29 13:48:08 2016 -0400

    loleaflet: fix undefined variables

diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index f456ce6..5110c60 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -754,7 +754,7 @@ L.Map = L.Evented.extend({
                        // A dialog is already dimming the screen and probably
                        // shows an error message. Leave it alone.
                        this._active = false;
-                       this._docLayer._onMessage('textselection:', null);
+                       this._docLayer && 
this._docLayer._onMessage('textselection:', null);
                        if (this._socket.connected()) {
                                this._socket.sendMessage('userinactive');
                        }
@@ -798,7 +798,7 @@ L.Map = L.Evented.extend({
                        $(options.appendLocation).append(options.$vex);
                        vex.setupBodyClassName(options.$vex);
 
-                       map._docLayer._onMessage('textselection:', null);
+                       map._doclayer && 
map._docLayer._onMessage('textselection:', null);
                        map._socket.sendMessage('userinactive');
 
                }, 30 * 1000); // Dim in 30 seconds.
@@ -808,7 +808,7 @@ L.Map = L.Evented.extend({
                if (!this._loaded) { return; }
 
                var doclayer = this._docLayer;
-               if (doclayer._isCursorVisible && 
doclayer._isCursorOverlayVisible) {
+               if (doclayer && doclayer._isCursorVisible && 
doclayer._isCursorOverlayVisible) {
                        doclayer._visibleCursorOnLostFocus = 
doclayer._visibleCursor;
                        doclayer._isCursorOverlayVisibleOnLostFocus = 
doclayer._isCursorVisibleOnLostFocus = true;
                        doclayer._isCursorOverlayVisible = false;
@@ -822,7 +822,7 @@ L.Map = L.Evented.extend({
                if (!this._loaded) { return; }
 
                var doclayer = this._docLayer;
-               if (doclayer._isCursorVisibleOnLostFocus && 
doclayer._isCursorOverlayVisibleOnLostFocus) {
+               if (doclayer && doclayer._isCursorVisibleOnLostFocus && 
doclayer._isCursorOverlayVisibleOnLostFocus) {
                        // we restore the old cursor position by a small delay, 
so that if the user clicks
                        // inside the document we skip to restore it, so that 
the user does not see the cursor
                        // jumping from the old position to the new one
commit 3fcde8be836da5b54a110f43f888030fd749b093
Author: Henry Castro <hcas...@collabora.com>
Date:   Thu Sep 29 09:50:00 2016 -0400

    loleaflet: fix show dialog error
    
    Conflicts:
        loleaflet/src/core/Socket.js

diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index d66c578..937af32 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -12,17 +12,17 @@ L.Socket = L.Class.extend({
                        if (map.options.permission) {
                                map.options.docParams['permission'] = 
map.options.permission;
                        }
-                       this.socket = new WebSocket(map.options.server + 
'/lool/' + encodeURIComponent(map.options.doc + '?' + 
$.param(map.options.docParams)) + '/ws');
+                       this.socket = new WebSocket(map.options.server + 
'/lool/ws/' + map.options.doc + '?' + $.param(map.options.docParams));
+                       this.socket.onerror = L.bind(this._onSocketError, this);
+                       this.socket.onclose = L.bind(this._onSocketClose, this);
+                       this.socket.onopen = L.bind(this._onSocketOpen, this);
+                       this.socket.onmessage = L.bind(this._onMessage, this);
+                       this.socket.binaryType = 'arraybuffer';
                } catch (e) {
-                       this.fire('error', {msg: _('Oops, there is a problem 
connecting to LibreOffice Online : ' + e), cmd: 'socket', kind: 'failed', id: 
3});
+                       this._map.fire('error', {msg: _('Oops, there is a 
problem connecting to LibreOffice Online : ' + e), cmd: 'socket', kind: 
'failed', id: 3});
                        return null;
                }
                this._msgQueue = [];
-               this.socket.onerror = L.bind(this._onSocketError, map);
-               this.socket.onclose = L.bind(this._onSocketClose, map);
-               this.socket.onopen = L.bind(this._onOpen, this);
-               this.socket.onmessage = L.bind(this._onMessage, this);
-               this.socket.binaryType = 'arraybuffer';
        },
 
        close: function () {
@@ -69,7 +69,7 @@ L.Socket = L.Class.extend({
                this.socket.send(msg);
        },
 
-       _onOpen: function () {
+       _onSocketOpen: function () {
                // Always send the protocol version number.
                // TODO: Move the version number somewhere sensible.
                this._doSend('loolclient ' + this.ProtocolVersionNumber);
@@ -134,7 +134,7 @@ L.Socket = L.Class.extend({
 
                        // TODO: For now we expect perfect match in protocol 
versions
                        if (loolwsdVersionObj.Protocol !== 
this.ProtocolVersionNumber) {
-                               this.fire('error', {msg: _('Unsupported server 
version.')});
+                               this._map.fire('error', {msg: _('Unsupported 
server version.')});
                        }
                }
                else if (textMsg.startsWith('lokitversion ')) {
@@ -186,7 +186,11 @@ L.Socket = L.Class.extend({
                        }
                }
                else if (textMsg.startsWith('error:') && !this._map._docLayer) {
-                       this.fail = true;
+                       textMsg = textMsg.substring(6);
+                       vex.dialog.alert({
+                               message: textMsg,
+                               css: {'font-size': 'small'}
+                       });
                }
                else if (textMsg === 'pong' && this._map._docLayer && 
this._map._docLayer._debug) {
                        var times = this._map._docLayer._debugTimePING;
@@ -301,26 +305,24 @@ L.Socket = L.Class.extend({
        },
 
        _onSocketError: function () {
-               this.hideBusy();
+               this._map.hideBusy();
                // Let onclose (_onSocketClose) report errors.
        },
 
-       _onSocketClose: function () {
-               this.hideBusy();
-               if (this) {
-                       this._active = false;
-               }
+       _onSocketClose: function (e) {
+               this._map.hideBusy();
+               this._map._active = false;
 
-               if (this._docLayer) {
-                       this._docLayer.removeAllViews();
+               if (this._map._docLayer) {
+                       this._map._docLayer.removeAllViews();
                }
-               if (this.fail) {
-                       this.fire('error', {msg: _('Well, this is embarrassing, 
we cannot connect to your document. Please try again.'), cmd: 'socket', kind: 
'closed', id: 4});
+
+               if (e.code && e.reason) {
+                       this._map.fire('error', {msg: e.reason});
                }
                else {
-                       this.fire('error', {msg: _('We are sorry, this is an 
unexpected connection error. Please try again.'), cmd: 'socket', kind: 
'closed', id: 4});
+                       this._map.fire('error', {msg: _('Well, this is 
embarrassing, we cannot connect to your document. Please try again.'), cmd: 
'socket', kind: 'closed', id: 4});
                }
-               this.fail = false;
        },
 
        parseServerCmd: function (msg) {
commit 6f7d67a20472f16a78c58e0dd8017195b0d4bb5d
Author: Henry Castro <hcas...@collabora.com>
Date:   Thu Sep 29 09:48:09 2016 -0400

    loolwsd: control frames must have a payload of 125 bytes

diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 460a6c9..146449c 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -180,6 +180,50 @@ static std::map<std::string, 
std::shared_ptr<PrisonerSession>> AvailableChildSes
 static int careerSpanSeconds = 0;
 #endif
 
+namespace {
+
+static inline
+void lcl_shutdownLimitReached(WebSocket& ws)
+{
+    const std::string msg = std::string("error: ") + 
Poco::format(PAYLOAD_UNAVALABLE_LIMIT_REACHED, MAX_DOCUMENTS, MAX_CONNECTIONS,
+        std::string(LOOLWSD_PRODUCT),
+        std::string(LOOLWSD_URL),
+        std::string(LOOLWSD_URL));
+
+    /* loleaflet sends loolclient, load and partrectangles message immediately
+       after web socket handshake, so closing web socket fails loading page in
+       some sensible browsers. Ignore handshake messages and gracefully
+       close in order to send error messages.
+    */
+    try
+    {
+        int flags = 0;
+        int handshake = 3;
+        std::vector<char> buffer(READ_BUFFER_SIZE * 100);
+
+        // 5 seconds timeout
+        ws.setReceiveTimeout(5000000);
+        do
+        {
+            // ignore loolclient, load and partpagerectangles
+            ws.receiveFrame(buffer.data(), buffer.capacity(), flags);
+            if (--handshake == 0)
+            {
+                ws.sendFrame(msg.data(), msg.size());
+                ws.shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY, 
Poco::format(SERVICE_UNAVALABLE_LIMIT_REACHED, MAX_DOCUMENTS, MAX_CONNECTIONS));
+            }
+        }
+        while ((flags & WebSocket::FRAME_OP_BITMASK) != 
WebSocket::FRAME_OP_CLOSE);
+    }
+    catch (Exception& e)
+    {
+        ws.sendFrame(msg.data(), msg.size());
+        ws.shutdown(WebSocket::WS_ENDPOINT_GOING_AWAY, 
Poco::format(SERVICE_UNAVALABLE_LIMIT_REACHED, MAX_DOCUMENTS, MAX_CONNECTIONS));
+    }
+}
+
+}
+
 static void forkChildren(const int number)
 {
     Util::assertIsLocked(newChildrenMutex);
@@ -657,7 +701,8 @@ private:
             {
                 --LOOLWSD::NumDocBrokers;
                 Log::error("Maximum number of open documents reached.");
-                throw 
WebSocketErrorMessageException(Poco::format(SERVICE_UNAVALABLE_LIMIT_REACHED, 
MAX_DOCUMENTS, MAX_CONNECTIONS, std::string(LOOLWSD_PRODUCT), 
std::string(LOOLWSD_URL), std::string(LOOLWSD_URL)));
+                lcl_shutdownLimitReached(*ws);
+                return;
             }
 #endif
 
@@ -882,9 +927,9 @@ public:
         {
             --LOOLWSD::NumConnections;
             Log::error("Maximum number of connections reached.");
-            response.setStatusAndReason(HTTPResponse::HTTP_NOT_ACCEPTABLE, 
Poco::format(SERVICE_UNAVALABLE_LIMIT_REACHED, MAX_DOCUMENTS, MAX_CONNECTIONS, 
std::string(LOOLWSD_PRODUCT), std::string(LOOLWSD_URL), 
std::string(LOOLWSD_URL)));
-            response.setContentLength(0);
-            response.send();
+            // accept hand shake
+            WebSocket ws(request, response);
+            lcl_shutdownLimitReached(ws);
             return;
         }
 #endif
diff --git a/loolwsd/UserMessages.hpp b/loolwsd/UserMessages.hpp
index 8d1dee7..7aa7aa4 100644
--- a/loolwsd/UserMessages.hpp
+++ b/loolwsd/UserMessages.hpp
@@ -15,7 +15,8 @@
 //NOTE: For whatever reason Poco seems to trim the first character.
 
 constexpr auto SERVICE_UNAVALABLE_INTERNAL_ERROR = " Service is unavailable. 
Please try again later and report to your administrator if the issue persists.";
-constexpr auto SERVICE_UNAVALABLE_LIMIT_REACHED = "This development build is 
limited to %d documents, and %d connections - to avoid the impression that it 
is suitable for deployment in large enterprises. To find out more about 
deploying and scaling %s checkout - <a href=\"%s\">%s</a>.";
+constexpr auto SERVICE_UNAVALABLE_LIMIT_REACHED = "This development build is 
limited to %d documents, and %d connections";
+constexpr auto PAYLOAD_UNAVALABLE_LIMIT_REACHED = "This development build is 
limited to %d documents, and %d connections - to avoid the impression that it 
is suitable for deployment in large enterprises. To find out more about 
deploying and scaling %s checkout: <br/><a href=\"%s\">%s</a>.";
 
 #endif
 
diff --git a/loolwsd/test/helpers.hpp b/loolwsd/test/helpers.hpp
index fd9c572..01922e3 100644
--- a/loolwsd/test/helpers.hpp
+++ b/loolwsd/test/helpers.hpp
@@ -198,7 +198,7 @@ int getErrorCode(Poco::Net::WebSocket& ws, std::string& 
message)
     Poco::Buffer<char> buffer(READ_BUFFER_SIZE);
 
     message.clear();
-    Poco::Timespan timeout(250000);
+    Poco::Timespan timeout(5000000);
     ws.setReceiveTimeout(timeout);
     do
     {
diff --git a/loolwsd/test/httpwserror.cpp b/loolwsd/test/httpwserror.cpp
index b8b8afb..a7f8385 100644
--- a/loolwsd/test/httpwserror.cpp
+++ b/loolwsd/test/httpwserror.cpp
@@ -97,6 +97,10 @@ void HTTPWSError::testMaxDocuments()
         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);
+        // send loolclient, load and partpagerectangles
+        sendTextFrame(socket, "loolclient ");
+        sendTextFrame(socket, "load ");
+        sendTextFrame(socket, "partpagerectangles ");
         statusCode = getErrorCode(socket, message);
         
CPPUNIT_ASSERT_EQUAL(static_cast<Poco::UInt16>(Poco::Net::WebSocket::WS_ENDPOINT_GOING_AWAY),
 statusCode);
         CPPUNIT_ASSERT_MESSAGE("Wrong error message ", message.find("This 
development build") != std::string::npos);
@@ -117,6 +121,7 @@ void HTTPWSError::testMaxConnections()
         std::string docPath;
         std::string docURL;
         std::string message;
+        Poco::UInt16 statusCode;
         std::vector<std::shared_ptr<Poco::Net::WebSocket>> views;
 
         getDocumentPathAndURL("empty.odt", docPath, docURL);
@@ -125,31 +130,21 @@ void HTTPWSError::testMaxConnections()
 
         for(int it = 1; it < MAX_CONNECTIONS; it++)
         {
-            std::cerr << it << std::endl;
             std::unique_ptr<Poco::Net::HTTPClientSession> 
session(createSession(_uri));
             auto ws = std::make_shared<Poco::Net::WebSocket>(*session, 
request, _response);
             views.emplace_back(ws);
         }
 
         // try to connect MAX_CONNECTIONS + 1
-        {
-            // Load a document and get its status.
-            const std::string documentURL = "lool/ws/file:///fake.doc";
-
-            Poco::Net::HTTPResponse response;
-            Poco::Net::HTTPRequest requestN(Poco::Net::HTTPRequest::HTTP_GET, 
documentURL);
-            std::unique_ptr<Poco::Net::HTTPClientSession> 
session(helpers::createSession(_uri));
-            requestN.set("Connection", "Upgrade");
-            requestN.set("Upgrade", "websocket");
-            requestN.set("Sec-WebSocket-Version", "13");
-            requestN.set("Sec-WebSocket-Key", "");
-            requestN.setChunkedTransferEncoding(false);
-            session->setKeepAlive(true);
-            session->sendRequest(requestN);
-            session->receiveResponse(response);
-            
CPPUNIT_ASSERT_EQUAL(Poco::Net::HTTPResponse::HTTPResponse::HTTP_NOT_ACCEPTABLE,
 response.getStatus());
-            CPPUNIT_ASSERT_MESSAGE("Wrong error message ", 
response.getReason().find("This development build") != std::string::npos);
-        }
+        std::unique_ptr<Poco::Net::HTTPClientSession> 
session(createSession(_uri));
+        auto socketN = std::make_shared<Poco::Net::WebSocket>(*session, 
request, _response);
+        // send loolclient, load and partpagerectangles
+        sendTextFrame(socketN, "loolclient ");
+        sendTextFrame(socketN, "load ");
+        sendTextFrame(socketN, "partpagerectangles ");
+        statusCode = getErrorCode(*socketN, message);
+        
CPPUNIT_ASSERT_EQUAL(static_cast<Poco::UInt16>(Poco::Net::WebSocket::WS_ENDPOINT_GOING_AWAY),
 statusCode);
+        CPPUNIT_ASSERT_MESSAGE("Wrong error message ", message.find("This 
development build") != std::string::npos);
     }
     catch (const Poco::Exception& exc)
     {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to