diff options
author | Michael Meeks <michael.meeks@collabora.com> | 2020-05-09 19:41:40 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2020-05-13 00:53:36 +0200 |
commit | 99d6282dde64b9528eec54bcd960ea547823571a (patch) | |
tree | 5f4b3c3492267b64f1727d677db78c4b87689e21 /wsd | |
parent | 34fc7fb6b726dcdf0c40f19ed402c3728581d1a2 (diff) |
Proxy: re-arrange URL structure & document it better.
Also implement 'close' during browser unload.
Change-Id: Ie2072c14cf863876c633b3371b86016367ad4992
Reviewed-on: https://gerrit.libreoffice.org/c/online/+/94089
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Diffstat (limited to 'wsd')
-rw-r--r-- | wsd/DocumentBroker.hpp | 4 | ||||
-rw-r--r-- | wsd/LOOLWSD.cpp | 19 | ||||
-rw-r--r-- | wsd/ProxyProtocol.cpp | 41 | ||||
-rw-r--r-- | wsd/ProxyProtocol.hpp | 9 |
4 files changed, 46 insertions, 27 deletions
diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp index 939743fe4..17300d0cb 100644 --- a/wsd/DocumentBroker.hpp +++ b/wsd/DocumentBroker.hpp @@ -158,13 +158,11 @@ public: /// Find or create a new client session for the PHP proxy void handleProxyRequest( - const std::string& sessionId, const std::string& id, const Poco::URI& uriPublic, const bool isReadOnly, const RequestDetails &requestDetails, - const std::shared_ptr<StreamSocket> &socket, - bool isWaiting); + const std::shared_ptr<StreamSocket> &socket); /// Thread safe termination of this broker if it has a lingering thread void joinThread(); diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp index 600c1e369..b03574724 100644 --- a/wsd/LOOLWSD.cpp +++ b/wsd/LOOLWSD.cpp @@ -2909,11 +2909,7 @@ private: Poco::MemoryInputStream& message, SocketDisposition &disposition) { - if (!request.has("SessionId")) - throw BadRequestException("No session id header on proxied request"); - std::string url = requestDetails.getDocumentURI(); - std::string sessionId = request.get("SessionId"); LOG_INF("URL [" << url << "]."); const auto uriPublic = DocumentBroker::sanitizeURI(url); @@ -2943,15 +2939,12 @@ private: // Request a kit process for this doc. std::shared_ptr<DocumentBroker> docBroker = findOrCreateDocBroker( none, DocumentBroker::ChildType::Interactive, url, docKey, _id, uriPublic); - - std::string fullURL = request.getURI(); - std::string ending = "/ws/wait"; - bool isWaiting = fullURL.find(ending) != std::string::npos; if (docBroker) { // need to move into the DocumentBroker context before doing session lookup / creation etc. std::string id = _id; - disposition.setMove([docBroker, id, uriPublic, isReadOnly, requestDetails, sessionId, isWaiting] + disposition.setMove([docBroker, id, uriPublic, + isReadOnly, requestDetails] (const std::shared_ptr<Socket> &moveSocket) { LOG_TRC("Setting up docbroker thread for " << docBroker->getDocKey()); @@ -2961,8 +2954,8 @@ private: // We no longer own this socket. moveSocket->setThreadOwner(std::thread::id()); - docBroker->addCallback([docBroker, id, uriPublic, isReadOnly, requestDetails, - sessionId, moveSocket, isWaiting]() + docBroker->addCallback([docBroker, id, uriPublic, isReadOnly, + requestDetails, moveSocket]() { // Now inside the document broker thread ... LOG_TRC("In the docbroker thread for " << docBroker->getDocKey()); @@ -2971,8 +2964,8 @@ private: try { docBroker->handleProxyRequest( - sessionId, id, uriPublic, isReadOnly, - requestDetails, streamSocket, isWaiting); + id, uriPublic, isReadOnly, + requestDetails, streamSocket); return; } catch (const UnauthorizedRequestException& exc) diff --git a/wsd/ProxyProtocol.cpp b/wsd/ProxyProtocol.cpp index 8784c39b1..7a5ef1b4c 100644 --- a/wsd/ProxyProtocol.cpp +++ b/wsd/ProxyProtocol.cpp @@ -7,6 +7,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * The ProxyProtocol creates a web-socket like connection over HTTP + * requests. URLs are formed like this: + * 0 1 2 3 4 5 + * /lool/<encoded-document-url>/ws/<session-id>/<command>/<serial> + * <session-id> can be 'unknown' + * <command> can be 'open', 'write', 'wait', or 'close' + */ + #include <config.h> #include "DocumentBroker.hpp" @@ -20,18 +29,18 @@ #include <cassert> void DocumentBroker::handleProxyRequest( - const std::string& sessionId, const std::string& id, const Poco::URI& uriPublic, const bool isReadOnly, const RequestDetails &requestDetails, - const std::shared_ptr<StreamSocket> &socket, - bool isWaiting) + const std::shared_ptr<StreamSocket> &socket) { - std::shared_ptr<ClientSession> clientSession; - + const size_t session = 3; + const size_t command = 4; + const size_t serial = 5; - if (sessionId == "fetchsession") + std::shared_ptr<ClientSession> clientSession; + if (requestDetails.equals(command, "open")) { bool isLocal = socket->isLocal(); LOG_TRC("proxy: validate that socket is from localhost: " << isLocal); @@ -64,6 +73,7 @@ void DocumentBroker::handleProxyRequest( } else { + std::string sessionId = requestDetails[session]; LOG_TRC("proxy: find session for " << _docKey << " with id " << sessionId); for (const auto &it : _sessions) { @@ -87,9 +97,16 @@ void DocumentBroker::handleProxyRequest( // this DocumentBroker's poll handles reading & writing addSocketToPoll(socket); - auto proxy = std::static_pointer_cast<ProxyProtocolHandler>( - protocol); + auto proxy = std::static_pointer_cast<ProxyProtocolHandler>(protocol); + if (requestDetails.equals(command, "close")) + { + LOG_TRC("Close session"); + proxy->notifyDisconnected(); + return; + } + (void)serial; // in URL for logging, debugging, and uniqueness. + bool isWaiting = requestDetails.equals(command, "wait"); proxy->handleRequest(isWaiting, socket); } @@ -98,9 +115,11 @@ bool ProxyProtocolHandler::parseEmitIncoming( { std::vector<char> &in = socket->getInBuffer(); +#if 0 // protocol debugging. std::stringstream oss; socket->dumpState(oss); LOG_TRC("Parse message:\n" << oss.str()); +#endif while (in.size() > 0) { @@ -219,6 +238,12 @@ void ProxyProtocolHandler::handleIncomingMessage(SocketDisposition &disposition) LOG_ERR("If you got here, it means we failed to parse this properly in handleRequest: " << oss.str()); } +void ProxyProtocolHandler::notifyDisconnected() +{ + if (_msgHandler) + _msgHandler->onDisconnect(); +} + int ProxyProtocolHandler::sendMessage(const char *msg, const size_t len, bool text, bool flush) { _writeQueue.push_back(std::make_shared<Message>(msg, len, text, _outSerial++)); diff --git a/wsd/ProxyProtocol.hpp b/wsd/ProxyProtocol.hpp index 7bca66600..4a890d8f6 100644 --- a/wsd/ProxyProtocol.hpp +++ b/wsd/ProxyProtocol.hpp @@ -30,9 +30,7 @@ public: virtual ~ProxyProtocolHandler() { } /// Will be called exactly once by setHandler - void onConnect(const std::shared_ptr<StreamSocket>& /* socket */) override - { - } + void onConnect(const std::shared_ptr<StreamSocket>& /* socket */) override {} /// Called after successful socket reads. void handleIncomingMessage(SocketDisposition &/* disposition */) override; @@ -61,10 +59,15 @@ public: void getIOStats(uint64_t &sent, uint64_t &recv) override; void dumpState(std::ostream& os) override; bool parseEmitIncoming(const std::shared_ptr<StreamSocket> &socket); + void handleRequest(bool isWaiting, const std::shared_ptr<Socket> &socket); + /// tell our handler we've received a close. + void notifyDisconnected(); + private: std::shared_ptr<StreamSocket> popOutSocket(); + /// can we find anything to send back if we try ? bool slurpHasMessages(); int sendMessage(const char *msg, const size_t len, bool text, bool flush); bool flushQueueTo(const std::shared_ptr<StreamSocket> &socket); |