summaryrefslogtreecommitdiff
path: root/wsd
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2020-05-09 19:41:40 +0100
committerMichael Meeks <michael.meeks@collabora.com>2020-05-13 00:53:36 +0200
commit99d6282dde64b9528eec54bcd960ea547823571a (patch)
tree5f4b3c3492267b64f1727d677db78c4b87689e21 /wsd
parent34fc7fb6b726dcdf0c40f19ed402c3728581d1a2 (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.hpp4
-rw-r--r--wsd/LOOLWSD.cpp19
-rw-r--r--wsd/ProxyProtocol.cpp41
-rw-r--r--wsd/ProxyProtocol.hpp9
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);