diff --git a/loleaflet/dist/errormessages.js b/loleaflet/dist/errormessages.js index fa6a99979..edda0764e 100644 --- a/loleaflet/dist/errormessages.js +++ b/loleaflet/dist/errormessages.js @@ -1,6 +1,6 @@ exports.diskfull = _('No disk space left on server, please contact the server administrator to continue.'); exports.emptyhosturl = _('The host URL is empty. The loolwsd server is probably misconfigured, please contact the administrator.'); -exports.limitreached = _('This development build is limited to %0 documents, and %1 connections - to avoid the impression that it is suitable for deployment in large enterprises. To find out more about deploying and scaling %2 check out:
%3.'); +exports.limitreached = _('This is an unsupported version of {productname}. To avoid the impression that it is suitable for deployment in enterprises, this version is limited to {docs} documents, and {connections} connections.
{a}More information and support{/a}'); exports.limitreachedprod = _('This service is limited to %0 documents, and %1 connections total by the admin. This limit has been reached. Please try again later.'); exports.serviceunavailable = _('Service is unavailable. Please try again later and report to your administrator if the issue persists.'); exports.unauthorized = _('Unauthorized WOPI host. Please try again later and report to your administrator if the issue persists.'); diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js index 9cb99c236..3e33a88de 100644 --- a/loleaflet/src/core/Socket.js +++ b/loleaflet/src/core/Socket.js @@ -7,6 +7,7 @@ L.Socket = L.Class.extend({ ProtocolVersionNumber: '0.1', ReconnectCount: 0, + WasShownLimitDialog: false, getParameterValue: function (s) { var i = s.indexOf('='); @@ -550,31 +551,34 @@ L.Socket = L.Class.extend({ } else if (textMsg.startsWith('error:') && !this._map._docLayer) { textMsg = textMsg.substring(6); - if (command.errorKind === 'limitreached') { - this._map._fatal = true; - this._map._active = false; // Practically disconnected. + if (command.errorKind === 'hardlimitreached') { - // Servers configured for 50 documents are not demo/development. - if (parseInt(command.params[0]) >= 50) { - textMsg = errorMessages.limitreachedprod; - textMsg = textMsg.replace(/%0/g, command.params[0]); - textMsg = textMsg.replace(/%1/g, command.params[1]); - } - else { - textMsg = errorMessages.limitreached; - textMsg = textMsg.replace(/%0/g, command.params[0]); - textMsg = textMsg.replace(/%1/g, command.params[1]); - textMsg = textMsg.replace(/%2/g, (typeof brandProductName !== 'undefined' ? brandProductName : 'LibreOffice Online')); - textMsg = textMsg.replace(/%3/g, (typeof brandProductFAQURL !== 'undefined' ? brandProductFAQURL : 'https://wiki.documentfoundation.org/Development/LibreOffice_Online')); - } + textMsg = errorMessages.limitreachedprod; + textMsg = textMsg.replace(/%0/g, command.params[0]); + textMsg = textMsg.replace(/%1/g, command.params[1]); } else if (command.errorKind === 'serviceunavailable') { - this._map._fatal = true; - this._map._active = false; // Practically disconnected. textMsg = errorMessages.serviceunavailable; } + this._map._fatal = true; + this._map._active = false; // Practically disconnected. this._map.fire('error', {msg: textMsg}); } + else if (textMsg.startsWith('info:') && command.errorCmd === 'socket') { + if (command.errorKind === 'limitreached' && !this.WasShownLimitDialog) { + this.WasShownLimitDialog = true; + textMsg = errorMessages.limitreached; + textMsg = textMsg.replace(/{docs}/g, command.params[0]); + textMsg = textMsg.replace(/{connections}/g, command.params[1]); + textMsg = textMsg.replace(/{productname}/g, (typeof brandProductName !== 'undefined' ? + brandProductName : 'LibreOffice Online')); + brandProductFAQURL = (typeof brandProductFAQURL !== 'undefined') ? + brandProductFAQURL : 'https://hub.libreoffice.org/professional-online-support'; + textMsg = textMsg.replace(/{a}/g, ''); + textMsg = textMsg.replace(/{\/a}/g, ''); + this._map.fire('error', {msg: textMsg}); + } + } else if (textMsg.startsWith('pong ') && this._map._docLayer && this._map._docLayer._debug) { var times = this._map._docLayer._debugTimePING; var timeText = this._map._docLayer._debugSetTimes(times, +new Date() - this._map._docLayer._debugPINGQueue.shift()); diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp index e27266e45..24b5a4aa9 100644 --- a/wsd/LOOLWSD.cpp +++ b/wsd/LOOLWSD.cpp @@ -196,7 +196,7 @@ namespace inline void shutdownLimitReached(WebSocketHandler& ws) { const std::string error = Poco::format(PAYLOAD_UNAVAILABLE_LIMIT_REACHED, LOOLWSD::MaxDocuments, LOOLWSD::MaxConnections); - LOG_INF("Sending client limit-reached message: " << error); + LOG_INF("Sending client 'hardlimitreached' message: " << error); try { @@ -212,6 +212,22 @@ inline void shutdownLimitReached(WebSocketHandler& ws) } } +inline void infoLimitReached() +{ + const std::string info = Poco::format(PAYLOAD_INFO_LIMIT_REACHED, LOOLWSD::MaxDocuments, LOOLWSD::MaxConnections); + LOG_INF("Sending client 'limitreached' message: " << info); + + try + { + Util::alertAllUsers(info); + } + catch (const std::exception& ex) + { + LOG_ERR("Error while shuting down socket on reaching limit: " << ex.what()); + } +} + + /// Internal implementation to alert all clients /// connected to any document. void alertAllUsersInternal(const std::string& msg) @@ -1454,9 +1470,11 @@ static std::shared_ptr findOrCreateDocBroker(WebSocketHandler& w if (DocBrokers.size() + 1 > LOOLWSD::MaxDocuments) { - LOG_ERR("Maximum number of open documents of " << LOOLWSD::MaxDocuments << " reached."); + LOG_INF("Maximum number of open documents of " << LOOLWSD::MaxDocuments << " reached."); +#if ENABLE_SUPPORT_KEY shutdownLimitReached(ws); return nullptr; +#endif } // Set the one we just created. @@ -1486,6 +1504,13 @@ static std::shared_ptr createNewClientSession(const WebSocketHand // Alert all other existing sessions also Util::alertAllUsers(diskfullMsg); } +#if !ENABLE_SUPPORT_KEY + // Users of development versions get just an info when reaching max documents or connections + if (DocBrokers.size() + 1 > LOOLWSD::MaxDocuments || LOOLWSD::NumConnections >= LOOLWSD::MaxConnections) + { + infoLimitReached(); + } +#endif // Now we have a DocumentBroker and we're ready to process client commands. if (ws) @@ -2257,9 +2282,11 @@ private: { if (LOOLWSD::NumConnections >= LOOLWSD::MaxConnections) { - LOG_ERR("Limit on maximum number of connections of " << LOOLWSD::MaxConnections << " reached."); + LOG_INF("Limit on maximum number of connections of " << LOOLWSD::MaxConnections << " reached."); +#if ENABLE_SUPPORT_KEY shutdownLimitReached(ws); return; +#endif } LOG_INF("Starting GET request handler for session [" << _id << "] on url [" << url << "]."); diff --git a/wsd/UserMessages.hpp b/wsd/UserMessages.hpp index 3efbdf8d9..00ad7875b 100644 --- a/wsd/UserMessages.hpp +++ b/wsd/UserMessages.hpp @@ -13,7 +13,8 @@ #define INCLUDED_USERMESSAGES_HPP constexpr const char* SERVICE_UNAVAILABLE_INTERNAL_ERROR = "error: cmd=socket kind=serviceunavailable"; -constexpr const char* PAYLOAD_UNAVAILABLE_LIMIT_REACHED = "error: cmd=socket kind=limitreached params=%u,%u"; +constexpr const char* PAYLOAD_UNAVAILABLE_LIMIT_REACHED = "error: cmd=socket kind=hardlimitreached params=%u,%u"; +constexpr const char* PAYLOAD_INFO_LIMIT_REACHED = "info: cmd=socket kind=limitreached params=%u,%u"; #endif