[Libreoffice-commits] online.git: loolwsd/ClientSession.cpp loolwsd/ClientSession.hpp loolwsd/LOOLWSD.cpp loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp loolwsd/PrisonerSession.cpp loolwsd/PrisonerSession.hpp

Ashod Nakashian ashod.nakashian at collabora.co.uk
Tue May 17 03:14:24 UTC 2016


 loolwsd/ClientSession.cpp        |  145 +++++++++++++
 loolwsd/ClientSession.hpp        |   41 ++-
 loolwsd/LOOLWSD.cpp              |    2 
 loolwsd/MasterProcessSession.cpp |  313 -----------------------------
 loolwsd/MasterProcessSession.hpp |   12 -
 loolwsd/PrisonerSession.cpp      |  411 ++++++++++++++-------------------------
 loolwsd/PrisonerSession.hpp      |   23 --
 7 files changed, 326 insertions(+), 621 deletions(-)

New commits:
commit 2cecb669981b91513431f5ebdd9743c056806487
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Mon May 16 19:05:22 2016 -0400

    loolwsd: MasterProcessSession splitting: moved message handler
    
    Change-Id: Ibc0c4f3f37213461a66fba7fb27a5996d0914776
    Reviewed-on: https://gerrit.libreoffice.org/25040
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/loolwsd/ClientSession.cpp b/loolwsd/ClientSession.cpp
index b266e9d..36e3185 100644
--- a/loolwsd/ClientSession.cpp
+++ b/loolwsd/ClientSession.cpp
@@ -20,6 +20,7 @@
 #include "LOOLSession.hpp"
 #include "LOOLWSD.hpp"
 #include "ClientSession.hpp"
+#include "PrisonerSession.hpp"
 #include "MasterProcessSession.hpp"
 #include "Rectangle.hpp"
 #include "Storage.hpp"
@@ -27,6 +28,150 @@
 #include "IoUtil.hpp"
 #include "Util.hpp"
 
+using namespace LOOLProtocol;
+
+using Poco::Path;
+using Poco::StringTokenizer;
+
+ClientSession::~ClientSession()
+{
+    Log::info("~PrisonerSession dtor [" + getName() + "].");
+
+    // Release the save-as queue.
+    _saveAsQueue.put("");
+}
+
+bool ClientSession::_handleInput(const char *buffer, int length)
+{
+    const std::string firstLine = getFirstLine(buffer, length);
+    StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+    Log::trace(getName() + ": handling [" + firstLine + "].");
+
+    if (LOOLProtocol::tokenIndicatesUserInteraction(tokens[0]))
+    {
+        // Keep track of timestamps of incoming client messages that indicate user activity.
+        updateLastActivityTime();
+    }
+
+    if (tokens[0] == "loolclient")
+    {
+        const auto versionTuple = ParseVersion(tokens[1]);
+        if (std::get<0>(versionTuple) != ProtocolMajorVersionNumber ||
+            std::get<1>(versionTuple) != ProtocolMinorVersionNumber)
+        {
+            sendTextFrame("error: cmd=loolclient kind=badversion");
+            return false;
+        }
+
+        sendTextFrame("loolserver " + GetProtocolVersion());
+        return true;
+    }
+
+    if (tokens[0] == "takeedit")
+    {
+        _docBroker->takeEditLock(getId());
+        return true;
+    }
+    else if (tokens[0] == "load")
+    {
+        if (_docURL != "")
+        {
+            sendTextFrame("error: cmd=load kind=docalreadyloaded");
+            return false;
+        }
+        return loadDocument(buffer, length, tokens);
+    }
+    else if (tokens[0] != "canceltiles" &&
+             tokens[0] != "clientzoom" &&
+             tokens[0] != "clientvisiblearea" &&
+             tokens[0] != "commandvalues" &&
+             tokens[0] != "downloadas" &&
+             tokens[0] != "getchildid" &&
+             tokens[0] != "gettextselection" &&
+             tokens[0] != "paste" &&
+             tokens[0] != "insertfile" &&
+             tokens[0] != "key" &&
+             tokens[0] != "mouse" &&
+             tokens[0] != "partpagerectangles" &&
+             tokens[0] != "renderfont" &&
+             tokens[0] != "requestloksession" &&
+             tokens[0] != "resetselection" &&
+             tokens[0] != "saveas" &&
+             tokens[0] != "selectgraphic" &&
+             tokens[0] != "selecttext" &&
+             tokens[0] != "setclientpart" &&
+             tokens[0] != "setpage" &&
+             tokens[0] != "status" &&
+             tokens[0] != "tile" &&
+             tokens[0] != "tilecombine" &&
+             tokens[0] != "uno" &&
+             tokens[0] != "useractive" &&
+             tokens[0] != "userinactive")
+    {
+        sendTextFrame("error: cmd=" + tokens[0] + " kind=unknown");
+        return false;
+    }
+    else if (_docURL == "")
+    {
+        sendTextFrame("error: cmd=" + tokens[0] + " kind=nodocloaded");
+        return false;
+    }
+    else if (tokens[0] == "canceltiles")
+    {
+        if (!_peer.expired())
+            forwardToPeer(buffer, length);
+    }
+    else if (tokens[0] == "commandvalues")
+    {
+        return getCommandValues(buffer, length, tokens);
+    }
+    else if (tokens[0] == "partpagerectangles")
+    {
+        return getPartPageRectangles(buffer, length);
+    }
+    else if (tokens[0] == "renderfont")
+    {
+        sendFontRendering(buffer, length, tokens);
+    }
+    else if (tokens[0] == "status")
+    {
+        return getStatus(buffer, length);
+    }
+    else if (tokens[0] == "tile")
+    {
+        sendTile(buffer, length, tokens);
+    }
+    else if (tokens[0] == "tilecombine")
+    {
+        sendCombinedTiles(buffer, length, tokens);
+    }
+    else
+    {
+        // All other commands are such that they always require a
+        // LibreOfficeKitDocument session, i.e. need to be handled in
+        // a child process.
+
+        if (_peer.expired())
+        {
+            Log::trace("Dispatching child to handle [" + tokens[0] + "].");
+            dispatchChild();
+        }
+
+        // Allow 'downloadas' for all kinds of views irrespective of editlock
+        if (!isEditLocked() && tokens[0] != "downloadas" &&
+            tokens[0] != "userinactive" && tokens[0] != "useractive")
+        {
+            std::string dummyFrame = "dummymsg";
+            forwardToPeer(dummyFrame.c_str(), dummyFrame.size());
+        }
+        else if (tokens[0] != "requestloksession")
+        {
+            forwardToPeer(buffer, length);
+        }
+    }
+    return true;
+}
+
 /*
 void ClientSession::setEditLock(const bool value)
 {
diff --git a/loolwsd/ClientSession.hpp b/loolwsd/ClientSession.hpp
index 8cc0b6a..980b26f 100644
--- a/loolwsd/ClientSession.hpp
+++ b/loolwsd/ClientSession.hpp
@@ -26,12 +26,32 @@ class ClientSession final : public MasterProcessSession//, public std::enable_sh
 public:
     using MasterProcessSession::MasterProcessSession;
 
+    virtual ~ClientSession();
+
     //void setEditLock(const bool value);
     //void markEditLock(const bool value) { _bEditLock = value; }
     //bool isEditLocked() const { return _bEditLock; }
 
+    void setPeer(const std::shared_ptr<PrisonerSession>& peer) { MasterProcessSession::_peer = _peer = peer; }
 
-    //void setPeer(const std::shared_ptr<PrisonerSession>& peer) { _peer = peer; }
+    /**
+     * Return the URL of the saved-as document when it's ready. If called
+     * before it's ready, the call blocks till then.
+     */
+    std::string getSaveAsUrl()
+    {
+        const auto payload = _saveAsQueue.get();
+        return std::string(payload.data(), payload.size());
+    }
+
+    void setSaveAsUrl(const std::string& url)
+    {
+        _saveAsQueue.put(url);
+    }
+
+private:
+
+    virtual bool _handleInput(const char *buffer, int length) override;
 
 private:
 
@@ -39,8 +59,10 @@ private:
     // An edit lock will only allow the current session to make edits,
     // while other session opening the same document can only see
     bool _bEditLock = false;
-    //std::weak_ptr<PrisonerSession> _peer;
+    std::weak_ptr<PrisonerSession> _peer;
 
+    /// Store URLs of completed 'save as' documents.
+    MessageQueue _saveAsQueue;
 #if 0
  public:
     MasterProcessSession(const std::string& id,
@@ -66,8 +88,6 @@ private:
 
     std::shared_ptr<BasicTileQueue> getQueue() const { return _queue; }
 
-    void setPeer(const std::shared_ptr<MasterProcessSession>& peer) { _peer = peer; }
-
     bool shutdownPeer(Poco::UInt16 statusCode, const std::string& message);
 
 public:
@@ -87,21 +107,8 @@ public:
     void dispatchChild();
     void forwardToPeer(const char *buffer, int length);
 
-    // If _kind==ToPrisoner and the child process has started and completed its handshake with the
-    // parent process: Points to the WebSocketSession for the child process handling the document in
-    // question, if any.
-
-    // In the session to the child process, points to the LOOLSession for the LOOL client. This will
-    // obvious have to be rethought when we add collaboration and there can be several LOOL clients
-    // per document being edited (i.e., per child process).
-    std::weak_ptr<MasterProcessSession> _peer;
-
-    virtual bool _handleInput(const char *buffer, int length) override;
-
     int _curPart;
     int _loadPart;
-    /// Kind::ToClient instances store URLs of completed 'save as' documents.
-    MessageQueue _saveAsQueue;
     std::shared_ptr<DocumentBroker> _docBroker;
     std::shared_ptr<BasicTileQueue> _queue;
 #endif
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index f6a6fe6..0c923eb 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -414,7 +414,7 @@ private:
 
                     // Send it back to the client.
                     //TODO: Should have timeout to avoid waiting forever.
-                    Poco::URI resultURL(session->getSaveAs());
+                    Poco::URI resultURL(session->getSaveAsUrl());
                     if (!resultURL.getPath().empty())
                     {
                         const std::string mimeType = "application/octet-stream";
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index afc864d..91c0997 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -47,313 +47,6 @@ MasterProcessSession::MasterProcessSession(const std::string& id,
 
 MasterProcessSession::~MasterProcessSession()
 {
-    Log::info("~MasterProcessSession dtor [" + getName() + "].");
-
-    // Release the save-as queue.
-    _saveAsQueue.put("");
-}
-
-bool MasterProcessSession::_handleInput(const char *buffer, int length)
-{
-    const std::string firstLine = getFirstLine(buffer, length);
-    StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-    Log::trace(getName() + ": handling [" + firstLine + "].");
-
-    if (LOOLProtocol::tokenIndicatesUserInteraction(tokens[0]))
-    {
-        // Keep track of timestamps of incoming client messages that indicate user activity.
-        updateLastActivityTime();
-    }
-
-    if (tokens[0] == "loolclient")
-    {
-        const auto versionTuple = ParseVersion(tokens[1]);
-        if (std::get<0>(versionTuple) != ProtocolMajorVersionNumber ||
-            std::get<1>(versionTuple) != ProtocolMinorVersionNumber)
-        {
-            sendTextFrame("error: cmd=loolclient kind=badversion");
-            return false;
-        }
-
-        sendTextFrame("loolserver " + GetProtocolVersion());
-        return true;
-    }
-
-    if (_kind == Kind::ToPrisoner)
-    {
-        // Note that this handles both forwarding requests from the client to the child process, and
-        // forwarding replies from the child process to the client. Or does it?
-
-        // Snoop at some messages and manipulate tile cache information as needed
-        auto peer = _peer.lock();
-
-        {
-            if (!peer)
-            {
-                throw Poco::ProtocolException("The session has not been assigned a peer.");
-            }
-
-            if (tokens[0] == "unocommandresult:")
-            {
-                const std::string stringMsg(buffer, length);
-                Log::info(getName() + "Command: " + stringMsg);
-                const auto index = stringMsg.find_first_of('{');
-                if (index != std::string::npos)
-                {
-                    const std::string stringJSON = stringMsg.substr(index);
-                    Poco::JSON::Parser parser;
-                    const auto result = parser.parse(stringJSON);
-                    const auto& object = result.extract<Poco::JSON::Object::Ptr>();
-                    if (object->get("commandName").toString() == ".uno:Save" &&
-                        object->get("success").toString() == "true")
-                    {
-                        _docBroker->save();
-                        return true;
-                    }
-                }
-            }
-
-            if (tokens[0] == "error:")
-            {
-                std::string errorCommand;
-                std::string errorKind;
-                if (getTokenString(tokens[1], "cmd", errorCommand) &&
-                    getTokenString(tokens[2], "kind", errorKind) )
-                {
-                    if (errorCommand == "load")
-                    {
-                        if (errorKind == "passwordrequired:to-view" ||
-                            errorKind == "passwordrequired:to-modify" ||
-                            errorKind == "wrongpassword")
-                        {
-                            forwardToPeer(buffer, length);
-                            peer->_bLoadError = true;
-                            return false;
-                        }
-                    }
-                }
-            }
-
-            if (tokens[0] == "curpart:" &&
-                tokens.count() == 2 &&
-                getTokenInteger(tokens[1], "part", _curPart))
-            {
-                return true;
-            }
-
-            if (tokens.count() == 2 && tokens[0] == "saveas:")
-            {
-                std::string url;
-                if (!getTokenString(tokens[1], "url", url))
-                    return true;
-
-                if (peer)
-                {
-                    // Save as completed, inform the other (Kind::ToClient)
-                    // MasterProcessSession about it.
-
-                    const std::string filePrefix("file:///");
-                    if (url.find(filePrefix) == 0)
-                    {
-                        // Rewrite file:// URLs, as they are visible to the outside world.
-                        const Path path(_docBroker->getJailRoot(), url.substr(filePrefix.length()));
-                        url = filePrefix + path.toString().substr(1);
-                    }
-                    peer->_saveAsQueue.put(url);
-                }
-
-                return true;
-            }
-            else if (tokens.count() == 2 && tokens[0] == "statechanged:")
-            {
-                StringTokenizer stateTokens(tokens[1], "=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-                if (stateTokens.count() == 2 && stateTokens[0] == ".uno:ModifiedStatus")
-                {
-                    if (_docBroker)
-                    {
-                        _docBroker->setModified(stateTokens[1] == "true");
-                    }
-                }
-            }
-        }
-
-        if (peer && !_isDocPasswordProtected)
-        {
-            if (tokens[0] == "tile:")
-            {
-                assert(!"Tile traffic should go through the DocumentBroker-LoKit WS.");
-            }
-            else if (tokens[0] == "status:")
-            {
-                _docBroker->setLoaded();
-                _docBroker->tileCache().saveTextFile(std::string(buffer, length), "status.txt");
-
-                // Forward the status response to the client.
-                forwardToPeer(buffer, length);
-
-                // And let clients know if they hold the edit lock.
-                std::string message = "editlock: ";
-                message += std::to_string(peer->isEditLocked());
-                Log::debug("Forwarding [" + message + "] in response to status.");
-                forwardToPeer(message.c_str(), message.size());
-                return true;
-            }
-            else if (tokens[0] == "commandvalues:")
-            {
-                const std::string stringMsg(buffer, length);
-                const auto index = stringMsg.find_first_of('{');
-                if (index != std::string::npos)
-                {
-                    const std::string stringJSON = stringMsg.substr(index);
-                    Poco::JSON::Parser parser;
-                    const auto result = parser.parse(stringJSON);
-                    const auto& object = result.extract<Poco::JSON::Object::Ptr>();
-                    const std::string commandName = object->get("commandName").toString();
-                    if (commandName.find(".uno:CharFontName") != std::string::npos ||
-                        commandName.find(".uno:StyleApply") != std::string::npos)
-                    {
-                        // other commands should not be cached
-                        _docBroker->tileCache().saveTextFile(stringMsg, "cmdValues" + commandName + ".txt");
-                    }
-                }
-            }
-            else if (tokens[0] == "partpagerectangles:")
-            {
-                if (tokens.count() > 1 && !tokens[1].empty())
-                    _docBroker->tileCache().saveTextFile(std::string(buffer, length), "partpagerectangles.txt");
-            }
-            else if (tokens[0] == "invalidatetiles:")
-            {
-                assert(firstLine.size() == static_cast<std::string::size_type>(length));
-                _docBroker->tileCache().invalidateTiles(firstLine);
-            }
-            else if (tokens[0] == "renderfont:")
-            {
-                std::string font;
-                if (tokens.count() < 2 ||
-                    !getTokenString(tokens[1], "font", font))
-                    assert(false);
-
-                assert(firstLine.size() < static_cast<std::string::size_type>(length));
-                _docBroker->tileCache().saveRendering(font, "font", buffer + firstLine.size() + 1, length - firstLine.size() - 1);
-            }
-        }
-
-        forwardToPeer(buffer, length);
-        return true;
-    }
-
-    if (_kind == Kind::ToPrisoner)
-    {
-        // Message from child process to be forwarded to client.
-
-        // I think we should never get here
-        Log::error(getName() + ": Unexpected request [" + tokens[0] + "].");
-        assert(false);
-    }
-    else if (tokens[0] == "takeedit")
-    {
-        _docBroker->takeEditLock(getId());
-        return true;
-    }
-    else if (tokens[0] == "load")
-    {
-        if (_docURL != "")
-        {
-            sendTextFrame("error: cmd=load kind=docalreadyloaded");
-            return false;
-        }
-        return loadDocument(buffer, length, tokens);
-    }
-    else if (tokens[0] != "canceltiles" &&
-             tokens[0] != "clientzoom" &&
-             tokens[0] != "clientvisiblearea" &&
-             tokens[0] != "commandvalues" &&
-             tokens[0] != "downloadas" &&
-             tokens[0] != "getchildid" &&
-             tokens[0] != "gettextselection" &&
-             tokens[0] != "paste" &&
-             tokens[0] != "insertfile" &&
-             tokens[0] != "key" &&
-             tokens[0] != "mouse" &&
-             tokens[0] != "partpagerectangles" &&
-             tokens[0] != "renderfont" &&
-             tokens[0] != "requestloksession" &&
-             tokens[0] != "resetselection" &&
-             tokens[0] != "saveas" &&
-             tokens[0] != "selectgraphic" &&
-             tokens[0] != "selecttext" &&
-             tokens[0] != "setclientpart" &&
-             tokens[0] != "setpage" &&
-             tokens[0] != "status" &&
-             tokens[0] != "tile" &&
-             tokens[0] != "tilecombine" &&
-             tokens[0] != "uno" &&
-             tokens[0] != "useractive" &&
-             tokens[0] != "userinactive")
-    {
-        sendTextFrame("error: cmd=" + tokens[0] + " kind=unknown");
-        return false;
-    }
-    else if (_docURL == "")
-    {
-        sendTextFrame("error: cmd=" + tokens[0] + " kind=nodocloaded");
-        return false;
-    }
-    else if (tokens[0] == "canceltiles")
-    {
-        if (!_peer.expired())
-            forwardToPeer(buffer, length);
-    }
-    else if (tokens[0] == "commandvalues")
-    {
-        return getCommandValues(buffer, length, tokens);
-    }
-    else if (tokens[0] == "partpagerectangles")
-    {
-        return getPartPageRectangles(buffer, length);
-    }
-    else if (tokens[0] == "renderfont")
-    {
-        sendFontRendering(buffer, length, tokens);
-    }
-    else if (tokens[0] == "status")
-    {
-        return getStatus(buffer, length);
-    }
-    else if (tokens[0] == "tile")
-    {
-        sendTile(buffer, length, tokens);
-    }
-    else if (tokens[0] == "tilecombine")
-    {
-        sendCombinedTiles(buffer, length, tokens);
-    }
-    else
-    {
-        // All other commands are such that they always require a
-        // LibreOfficeKitDocument session, i.e. need to be handled in
-        // a child process.
-
-        if (_peer.expired())
-        {
-            Log::trace("Dispatching child to handle [" + tokens[0] + "].");
-            dispatchChild();
-        }
-
-        // Allow 'downloadas' for all kinds of views irrespective of editlock
-        if (_kind == Kind::ToClient && !isEditLocked() && tokens[0] != "downloadas" &&
-            tokens[0] != "userinactive" && tokens[0] != "useractive")
-        {
-            std::string dummyFrame = "dummymsg";
-            forwardToPeer(dummyFrame.c_str(), dummyFrame.size());
-        }
-        else if (tokens[0] != "requestloksession")
-        {
-            forwardToPeer(buffer, length);
-        }
-    }
-    return true;
 }
 
 bool MasterProcessSession::loadDocument(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
@@ -455,12 +148,6 @@ bool MasterProcessSession::getPartPageRectangles(const char *buffer, int length)
     return true;
 }
 
-std::string MasterProcessSession::getSaveAs()
-{
-    const auto payload = _saveAsQueue.get();
-    return std::string(payload.data(), payload.size());
-}
-
 void MasterProcessSession::sendFontRendering(const char *buffer, int length, StringTokenizer& tokens)
 {
     std::string font;
diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp
index fbdc41f..5dc3b46 100644
--- a/loolwsd/MasterProcessSession.hpp
+++ b/loolwsd/MasterProcessSession.hpp
@@ -35,18 +35,10 @@ class MasterProcessSession : public LOOLSession, public std::enable_shared_from_
 
     virtual bool getPartPageRectangles(const char *buffer, int length) override;
 
-    /**
-     * Return the URL of the saved-as document when it's ready. If called
-     * before it's ready, the call blocks till then.
-     */
-    std::string getSaveAs();
-
     std::shared_ptr<DocumentBroker> getDocumentBroker() const { return _docBroker; }
 
     std::shared_ptr<BasicTileQueue> getQueue() const { return _queue; }
 
-    void setPeer(const std::shared_ptr<MasterProcessSession>& peer) { _peer = peer; }
-
     void setEditLock(const bool value);
     void markEditLock(const bool value) { _bEditLock = value; }
     bool isEditLocked() const { return _bEditLock; }
@@ -78,12 +70,8 @@ public:
     // per document being edited (i.e., per child process).
     std::weak_ptr<MasterProcessSession> _peer;
 
-    virtual bool _handleInput(const char *buffer, int length) override;
-
     int _curPart;
     int _loadPart;
-    /// Kind::ToClient instances store URLs of completed 'save as' documents.
-    MessageQueue _saveAsQueue;
     std::shared_ptr<DocumentBroker> _docBroker;
     std::shared_ptr<BasicTileQueue> _queue;
 
diff --git a/loolwsd/PrisonerSession.cpp b/loolwsd/PrisonerSession.cpp
index 6da51ec..9257616 100644
--- a/loolwsd/PrisonerSession.cpp
+++ b/loolwsd/PrisonerSession.cpp
@@ -19,41 +19,26 @@
 #include "LOOLProtocol.hpp"
 #include "LOOLSession.hpp"
 #include "LOOLWSD.hpp"
+#include "ClientSession.hpp"
+#include "PrisonerSession.hpp"
 #include "MasterProcessSession.hpp"
 #include "Rectangle.hpp"
 #include "Storage.hpp"
 #include "TileCache.hpp"
 #include "IoUtil.hpp"
 #include "Util.hpp"
-#if 0
+
 using namespace LOOLProtocol;
 
 using Poco::Path;
 using Poco::StringTokenizer;
 
-MasterProcessSession::MasterProcessSession(const std::string& id,
-                                           const Kind kind,
-                                           std::shared_ptr<Poco::Net::WebSocket> ws,
-                                           std::shared_ptr<DocumentBroker> docBroker,
-                                           std::shared_ptr<BasicTileQueue> queue) :
-    LOOLSession(id, kind, ws),
-    _curPart(0),
-    _loadPart(-1),
-    _docBroker(docBroker),
-    _queue(queue)
+PrisonerSession::~PrisonerSession()
 {
-    Log::info("MasterProcessSession ctor [" + getName() + "].");
+    Log::info("~PrisonerSession dtor [" + getName() + "].");
 }
 
-MasterProcessSession::~MasterProcessSession()
-{
-    Log::info("~MasterProcessSession dtor [" + getName() + "].");
-
-    // Release the save-as queue.
-    _saveAsQueue.put("");
-}
-
-bool MasterProcessSession::_handleInput(const char *buffer, int length)
+bool PrisonerSession::_handleInput(const char *buffer, int length)
 {
     const std::string firstLine = getFirstLine(buffer, length);
     StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
@@ -65,297 +50,197 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
         updateLastActivityTime();
     }
 
-    if (tokens[0] == "loolclient")
-    {
-        const auto versionTuple = ParseVersion(tokens[1]);
-        if (std::get<0>(versionTuple) != ProtocolMajorVersionNumber ||
-            std::get<1>(versionTuple) != ProtocolMinorVersionNumber)
-        {
-            sendTextFrame("error: cmd=loolclient kind=badversion");
-            return false;
-        }
+    // Note that this handles both forwarding requests from the client to the child process, and
+    // forwarding replies from the child process to the client. Or does it?
 
-        sendTextFrame("loolserver " + GetProtocolVersion());
-        return true;
-    }
+    // Snoop at some messages and manipulate tile cache information as needed
+    auto peer = _peer.lock();
 
-    if (_kind == Kind::ToPrisoner)
     {
-        // Note that this handles both forwarding requests from the client to the child process, and
-        // forwarding replies from the child process to the client. Or does it?
-
-        // Snoop at some messages and manipulate tile cache information as needed
-        auto peer = _peer.lock();
-
+        if (!peer)
         {
-            if (!peer)
-            {
-                throw Poco::ProtocolException("The session has not been assigned a peer.");
-            }
+            throw Poco::ProtocolException("The session has not been assigned a peer.");
+        }
 
-            if (tokens[0] == "unocommandresult:")
+        if (tokens[0] == "unocommandresult:")
+        {
+            const std::string stringMsg(buffer, length);
+            Log::info(getName() + "Command: " + stringMsg);
+            const auto index = stringMsg.find_first_of('{');
+            if (index != std::string::npos)
             {
-                const std::string stringMsg(buffer, length);
-                Log::info(getName() + "Command: " + stringMsg);
-                const auto index = stringMsg.find_first_of('{');
-                if (index != std::string::npos)
+                const std::string stringJSON = stringMsg.substr(index);
+                Poco::JSON::Parser parser;
+                const auto result = parser.parse(stringJSON);
+                const auto& object = result.extract<Poco::JSON::Object::Ptr>();
+                if (object->get("commandName").toString() == ".uno:Save" &&
+                    object->get("success").toString() == "true")
                 {
-                    const std::string stringJSON = stringMsg.substr(index);
-                    Poco::JSON::Parser parser;
-                    const auto result = parser.parse(stringJSON);
-                    const auto& object = result.extract<Poco::JSON::Object::Ptr>();
-                    if (object->get("commandName").toString() == ".uno:Save" &&
-                        object->get("success").toString() == "true")
-                    {
-                        _docBroker->save();
-                        return true;
-                    }
+                    _docBroker->save();
+                    return true;
                 }
             }
+        }
 
-            if (tokens[0] == "error:")
+        if (tokens[0] == "error:")
+        {
+            std::string errorCommand;
+            std::string errorKind;
+            if (getTokenString(tokens[1], "cmd", errorCommand) &&
+                getTokenString(tokens[2], "kind", errorKind) )
             {
-                std::string errorCommand;
-                std::string errorKind;
-                if (getTokenString(tokens[1], "cmd", errorCommand) &&
-                    getTokenString(tokens[2], "kind", errorKind) )
+                if (errorCommand == "load")
                 {
-                    if (errorCommand == "load")
+                    if (errorKind == "passwordrequired:to-view" ||
+                        errorKind == "passwordrequired:to-modify" ||
+                        errorKind == "wrongpassword")
                     {
-                        if (errorKind == "passwordrequired:to-view" ||
-                            errorKind == "passwordrequired:to-modify" ||
-                            errorKind == "wrongpassword")
-                        {
-                            forwardToPeer(buffer, length);
-                            peer->_bLoadError = true;
-                            return false;
-                        }
+                        forwardToPeer(buffer, length);
+                        peer->_bLoadError = true;
+                        return false;
                     }
                 }
             }
+        }
 
-            if (tokens[0] == "curpart:" &&
-                tokens.count() == 2 &&
-                getTokenInteger(tokens[1], "part", _curPart))
-            {
+        if (tokens[0] == "curpart:" &&
+            tokens.count() == 2 &&
+            getTokenInteger(tokens[1], "part", _curPart))
+        {
+            return true;
+        }
+
+        if (tokens.count() == 2 && tokens[0] == "saveas:")
+        {
+            std::string url;
+            if (!getTokenString(tokens[1], "url", url))
                 return true;
-            }
 
-            if (tokens.count() == 2 && tokens[0] == "saveas:")
+            if (peer)
             {
-                std::string url;
-                if (!getTokenString(tokens[1], "url", url))
-                    return true;
+                // Save as completed, inform the other (Kind::ToClient)
+                // MasterProcessSession about it.
 
-                if (peer)
+                const std::string filePrefix("file:///");
+                if (url.find(filePrefix) == 0)
                 {
-                    // Save as completed, inform the other (Kind::ToClient)
-                    // MasterProcessSession about it.
-
-                    const std::string filePrefix("file:///");
-                    if (url.find(filePrefix) == 0)
-                    {
-                        // Rewrite file:// URLs, as they are visible to the outside world.
-                        const Path path(_docBroker->getJailRoot(), url.substr(filePrefix.length()));
-                        url = filePrefix + path.toString().substr(1);
-                    }
-                    peer->_saveAsQueue.put(url);
+                    // Rewrite file:// URLs, as they are visible to the outside world.
+                    const Path path(_docBroker->getJailRoot(), url.substr(filePrefix.length()));
+                    url = filePrefix + path.toString().substr(1);
                 }
 
-                return true;
-            }
-            else if (tokens.count() == 2 && tokens[0] == "statechanged:")
-            {
-                StringTokenizer stateTokens(tokens[1], "=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-                if (stateTokens.count() == 2 && stateTokens[0] == ".uno:ModifiedStatus")
-                {
-                    if (_docBroker)
-                    {
-                        _docBroker->setModified(stateTokens[1] == "true");
-                    }
-                }
+                peer->setSaveAsUrl(url);
             }
-        }
 
-        if (peer && !_isDocPasswordProtected)
+            return true;
+        }
+        else if (tokens.count() == 2 && tokens[0] == "statechanged:")
         {
-            if (tokens[0] == "tile:")
-            {
-                assert(!"Tile traffic should go through the DocumentBroker-LoKit WS.");
-            }
-            else if (tokens[0] == "status:")
-            {
-                _docBroker->setLoaded();
-                _docBroker->tileCache().saveTextFile(std::string(buffer, length), "status.txt");
-
-                // Forward the status response to the client.
-                forwardToPeer(buffer, length);
-
-                // And let clients know if they hold the edit lock.
-                std::string message = "editlock: ";
-                message += std::to_string(peer->isEditLocked());
-                Log::debug("Forwarding [" + message + "] in response to status.");
-                forwardToPeer(message.c_str(), message.size());
-                return true;
-            }
-            else if (tokens[0] == "commandvalues:")
+            StringTokenizer stateTokens(tokens[1], "=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+            if (stateTokens.count() == 2 && stateTokens[0] == ".uno:ModifiedStatus")
             {
-                const std::string stringMsg(buffer, length);
-                const auto index = stringMsg.find_first_of('{');
-                if (index != std::string::npos)
+                if (_docBroker)
                 {
-                    const std::string stringJSON = stringMsg.substr(index);
-                    Poco::JSON::Parser parser;
-                    const auto result = parser.parse(stringJSON);
-                    const auto& object = result.extract<Poco::JSON::Object::Ptr>();
-                    const std::string commandName = object->get("commandName").toString();
-                    if (commandName.find(".uno:CharFontName") != std::string::npos ||
-                        commandName.find(".uno:StyleApply") != std::string::npos)
-                    {
-                        // other commands should not be cached
-                        _docBroker->tileCache().saveTextFile(stringMsg, "cmdValues" + commandName + ".txt");
-                    }
+                    _docBroker->setModified(stateTokens[1] == "true");
                 }
             }
-            else if (tokens[0] == "partpagerectangles:")
-            {
-                if (tokens.count() > 1 && !tokens[1].empty())
-                    _docBroker->tileCache().saveTextFile(std::string(buffer, length), "partpagerectangles.txt");
-            }
-            else if (tokens[0] == "invalidatetiles:")
-            {
-                assert(firstLine.size() == static_cast<std::string::size_type>(length));
-                _docBroker->tileCache().invalidateTiles(firstLine);
-            }
-            else if (tokens[0] == "renderfont:")
-            {
-                std::string font;
-                if (tokens.count() < 2 ||
-                    !getTokenString(tokens[1], "font", font))
-                    assert(false);
-
-                assert(firstLine.size() < static_cast<std::string::size_type>(length));
-                _docBroker->tileCache().saveRendering(font, "font", buffer + firstLine.size() + 1, length - firstLine.size() - 1);
-            }
         }
-
-        forwardToPeer(buffer, length);
-        return true;
     }
 
-    if (_kind == Kind::ToPrisoner)
-    {
-        // Message from child process to be forwarded to client.
-
-        // I think we should never get here
-        Log::error(getName() + ": Unexpected request [" + tokens[0] + "].");
-        assert(false);
-    }
-    else if (tokens[0] == "takeedit")
+    if (peer && !_isDocPasswordProtected)
     {
-        _docBroker->takeEditLock(getId());
-        return true;
-    }
-    else if (tokens[0] == "load")
-    {
-        if (_docURL != "")
+        if (tokens[0] == "tile:")
         {
-            sendTextFrame("error: cmd=load kind=docalreadyloaded");
-            return false;
+            assert(!"Tile traffic should go through the DocumentBroker-LoKit WS.");
         }
-        return loadDocument(buffer, length, tokens);
-    }
-    else if (tokens[0] != "canceltiles" &&
-             tokens[0] != "clientzoom" &&
-             tokens[0] != "clientvisiblearea" &&
-             tokens[0] != "commandvalues" &&
-             tokens[0] != "downloadas" &&
-             tokens[0] != "getchildid" &&
-             tokens[0] != "gettextselection" &&
-             tokens[0] != "paste" &&
-             tokens[0] != "insertfile" &&
-             tokens[0] != "key" &&
-             tokens[0] != "mouse" &&
-             tokens[0] != "partpagerectangles" &&
-             tokens[0] != "renderfont" &&
-             tokens[0] != "requestloksession" &&
-             tokens[0] != "resetselection" &&
-             tokens[0] != "saveas" &&
-             tokens[0] != "selectgraphic" &&
-             tokens[0] != "selecttext" &&
-             tokens[0] != "setclientpart" &&
-             tokens[0] != "setpage" &&
-             tokens[0] != "status" &&
-             tokens[0] != "tile" &&
-             tokens[0] != "tilecombine" &&
-             tokens[0] != "uno" &&
-             tokens[0] != "useractive" &&
-             tokens[0] != "userinactive")
-    {
-        sendTextFrame("error: cmd=" + tokens[0] + " kind=unknown");
-        return false;
-    }
-    else if (_docURL == "")
-    {
-        sendTextFrame("error: cmd=" + tokens[0] + " kind=nodocloaded");
-        return false;
-    }
-    else if (tokens[0] == "canceltiles")
-    {
-        if (!_peer.expired())
+        else if (tokens[0] == "status:")
+        {
+            _docBroker->setLoaded();
+            _docBroker->tileCache().saveTextFile(std::string(buffer, length), "status.txt");
+
+            // Forward the status response to the client.
             forwardToPeer(buffer, length);
-    }
-    else if (tokens[0] == "commandvalues")
-    {
-        return getCommandValues(buffer, length, tokens);
-    }
-    else if (tokens[0] == "partpagerectangles")
-    {
-        return getPartPageRectangles(buffer, length);
-    }
-    else if (tokens[0] == "renderfont")
-    {
-        sendFontRendering(buffer, length, tokens);
-    }
-    else if (tokens[0] == "status")
-    {
-        return getStatus(buffer, length);
-    }
-    else if (tokens[0] == "tile")
-    {
-        sendTile(buffer, length, tokens);
-    }
-    else if (tokens[0] == "tilecombine")
-    {
-        sendCombinedTiles(buffer, length, tokens);
-    }
-    else
-    {
-        // All other commands are such that they always require a
-        // LibreOfficeKitDocument session, i.e. need to be handled in
-        // a child process.
 
-        if (_peer.expired())
+            // And let clients know if they hold the edit lock.
+            std::string message = "editlock: ";
+            message += std::to_string(peer->isEditLocked());
+            Log::debug("Forwarding [" + message + "] in response to status.");
+            forwardToPeer(message.c_str(), message.size());
+            return true;
+        }
+        else if (tokens[0] == "commandvalues:")
         {
-            Log::trace("Dispatching child to handle [" + tokens[0] + "].");
-            dispatchChild();
+            const std::string stringMsg(buffer, length);
+            const auto index = stringMsg.find_first_of('{');
+            if (index != std::string::npos)
+            {
+                const std::string stringJSON = stringMsg.substr(index);
+                Poco::JSON::Parser parser;
+                const auto result = parser.parse(stringJSON);
+                const auto& object = result.extract<Poco::JSON::Object::Ptr>();
+                const std::string commandName = object->get("commandName").toString();
+                if (commandName.find(".uno:CharFontName") != std::string::npos ||
+                    commandName.find(".uno:StyleApply") != std::string::npos)
+                {
+                    // other commands should not be cached
+                    _docBroker->tileCache().saveTextFile(stringMsg, "cmdValues" + commandName + ".txt");
+                }
+            }
         }
-
-        // Allow 'downloadas' for all kinds of views irrespective of editlock
-        if (_kind == Kind::ToClient && !isEditLocked() && tokens[0] != "downloadas" &&
-            tokens[0] != "userinactive" && tokens[0] != "useractive")
+        else if (tokens[0] == "partpagerectangles:")
         {
-            std::string dummyFrame = "dummymsg";
-            forwardToPeer(dummyFrame.c_str(), dummyFrame.size());
+            if (tokens.count() > 1 && !tokens[1].empty())
+                _docBroker->tileCache().saveTextFile(std::string(buffer, length), "partpagerectangles.txt");
         }
-        else if (tokens[0] != "requestloksession")
+        else if (tokens[0] == "invalidatetiles:")
         {
-            forwardToPeer(buffer, length);
+            assert(firstLine.size() == static_cast<std::string::size_type>(length));
+            _docBroker->tileCache().invalidateTiles(firstLine);
+        }
+        else if (tokens[0] == "renderfont:")
+        {
+            std::string font;
+            if (tokens.count() < 2 ||
+                !getTokenString(tokens[1], "font", font))
+                assert(false);
+
+            assert(firstLine.size() < static_cast<std::string::size_type>(length));
+            _docBroker->tileCache().saveRendering(font, "font", buffer + firstLine.size() + 1, length - firstLine.size() - 1);
         }
     }
+
+    forwardToPeer(buffer, length);
     return true;
 }
 
+#if 0
+using namespace LOOLProtocol;
+
+using Poco::Path;
+using Poco::StringTokenizer;
+
+MasterProcessSession::MasterProcessSession(const std::string& id,
+                                           const Kind kind,
+                                           std::shared_ptr<Poco::Net::WebSocket> ws,
+                                           std::shared_ptr<DocumentBroker> docBroker,
+                                           std::shared_ptr<BasicTileQueue> queue) :
+    LOOLSession(id, kind, ws),
+    _curPart(0),
+    _loadPart(-1),
+    _docBroker(docBroker),
+    _queue(queue)
+{
+    Log::info("MasterProcessSession ctor [" + getName() + "].");
+}
+
+MasterProcessSession::~MasterProcessSession()
+{
+    Log::info("~MasterProcessSession dtor [" + getName() + "].");
+
+    // Release the save-as queue.
+    _saveAsQueue.put("");
+}
+
 bool MasterProcessSession::loadDocument(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
 {
     if (tokens.count() < 2)
diff --git a/loolwsd/PrisonerSession.hpp b/loolwsd/PrisonerSession.hpp
index 3cbbe33..65418ee 100644
--- a/loolwsd/PrisonerSession.hpp
+++ b/loolwsd/PrisonerSession.hpp
@@ -26,11 +26,17 @@ class PrisonerSession final : public MasterProcessSession//, public std::enable_
 public:
     using MasterProcessSession::MasterProcessSession;
 
-    //void setPeer(const std::shared_ptr<ClientSession>& peer) { _peer = peer; }
+    virtual ~PrisonerSession();
+
+    void setPeer(const std::shared_ptr<ClientSession>& peer) { MasterProcessSession::_peer = _peer = peer; }
+
+private:
+
+    virtual bool _handleInput(const char *buffer, int length) override;
 
 private:
 
-    //std::weak_ptr<ClientSession> _peer;
+    std::weak_ptr<ClientSession> _peer;
 #if 0
  public:
     MasterProcessSession(const std::string& id,
@@ -56,8 +62,6 @@ private:
 
     std::shared_ptr<BasicTileQueue> getQueue() const { return _queue; }
 
-    void setPeer(const std::shared_ptr<MasterProcessSession>& peer) { _peer = peer; }
-
     bool shutdownPeer(Poco::UInt16 statusCode, const std::string& message);
 
 public:
@@ -77,17 +81,6 @@ public:
     void dispatchChild();
     void forwardToPeer(const char *buffer, int length);
 
-    // If _kind==ToPrisoner and the child process has started and completed its handshake with the
-    // parent process: Points to the WebSocketSession for the child process handling the document in
-    // question, if any.
-
-    // In the session to the child process, points to the LOOLSession for the LOOL client. This will
-    // obvious have to be rethought when we add collaboration and there can be several LOOL clients
-    // per document being edited (i.e., per child process).
-    std::weak_ptr<MasterProcessSession> _peer;
-
-    virtual bool _handleInput(const char *buffer, int length) override;
-
     int _curPart;
     int _loadPart;
     /// Kind::ToClient instances store URLs of completed 'save as' documents.


More information about the Libreoffice-commits mailing list