[Libreoffice-commits] online.git: 3 commits - loleaflet/src loolwsd/LOOLWSD.cpp loolwsd/test loolwsd/UserMessages.hpp

Henry Castro hcastro at collabora.com
Thu Sep 29 21:45:10 UTC 2016


 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 <hcastro at 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 <hcastro at 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 <hcastro at 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)
     {


More information about the Libreoffice-commits mailing list