[Libreoffice-commits] online.git: Branch 'private/Ashod/nonblocking' - 2 commits - net/loolnb.cpp net/Socket.hpp net/SslSocket.hpp

Jan Holesovsky kendy at collabora.com
Wed Feb 22 16:18:01 UTC 2017


 net/Socket.hpp    |   75 ++++++++++++++++++++++++++----------------------------
 net/SslSocket.hpp |   66 ++++++++++++++++++++++-------------------------
 net/loolnb.cpp    |   71 +++++++++++++++++++++++++++------------------------
 3 files changed, 106 insertions(+), 106 deletions(-)

New commits:
commit a8e3408830cf9573cf8c9ffbcc77b73ea580e9fc
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Feb 22 17:12:12 2017 +0100

    nb: SimpleResponseClient is a client, not a socket I guess.
    
    Introduce the appropriate interface instead of the template, so that we can
    de-couple the ResponseClient from the Socket itself.
    
    Change-Id: I21892bbce5d83a18ca580a25cfc2efbb05b08705

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 779b526..9c037e9 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -283,10 +283,29 @@ private:
     std::vector<pollfd> _pollFds;
 };
 
+class StreamSocket;
+
+/// Interface that handles the actual incoming message.
+class ResponseClientInterface
+{
+public:
+    /// Set the socket associated with this ResponseClient.
+    virtual void setSocket(StreamSocket* socket) = 0;
+
+    /// Called after successful socket reads.
+    virtual void handleIncomingMessage() = 0;
+};
+
 /// A plain, non-blocking, data streaming socket.
 class StreamSocket : public Socket
 {
 public:
+    StreamSocket(const int fd, ResponseClientInterface* responseClient) :
+        Socket(fd),
+        _responseClient(responseClient)
+    {
+        _responseClient->setSocket(this);
+    }
 
     /// Called when a polling event is received.
     /// @events is the mask of events that triggered the wake.
@@ -303,7 +322,8 @@ public:
         while (!_inBuffer.empty() && oldSize != _inBuffer.size())
         {
             oldSize = _inBuffer.size();
-            handleIncomingMessage();
+            if (_responseClient)
+                _responseClient->handleIncomingMessage();
         }
 
         // SSL might want to do handshake,
@@ -394,18 +414,16 @@ public:
     }
 
 protected:
-    StreamSocket(const int fd) :
-        Socket(fd)
-    {
-    }
+    /// Client handling the actual data.
+    std::unique_ptr<ResponseClientInterface> _responseClient;
 
     std::vector< char > _inBuffer;
     std::vector< char > _outBuffer;
 
-private:
-    /// Override to handle read data.
-    /// Called after successful socket reads.
-    virtual void handleIncomingMessage() = 0;
+    // FIXME temporarily make this friend class; when integrating, we'll see
+    // what methods we need to introduce instead of direct access to the
+    // _inBuffer / _outBuffer.
+    friend class SimpleResponseClient;
 };
 
 #endif
diff --git a/net/SslSocket.hpp b/net/SslSocket.hpp
index 8a9b1f0..c46ffbc 100644
--- a/net/SslSocket.hpp
+++ b/net/SslSocket.hpp
@@ -21,6 +21,33 @@
 class SslStreamSocket : public StreamSocket
 {
 public:
+    SslStreamSocket(const int fd, ResponseClientInterface* responseClient) :
+        StreamSocket(fd, responseClient),
+        _ssl(nullptr),
+        _sslWantsTo(SslWantsTo::ReadOrWrite),
+        _doHandshake(true)
+    {
+        BIO* bio = BIO_new(BIO_s_socket());
+        if (bio == nullptr)
+        {
+            throw std::runtime_error("Failed to create SSL BIO.");
+        }
+
+        BIO_set_fd(bio, fd, BIO_NOCLOSE);
+
+        _ssl = SslContext::newSsl();
+        if (!_ssl)
+        {
+            BIO_free(bio);
+            throw std::runtime_error("Failed to create SSL.");
+        }
+
+        SSL_set_bio(_ssl, bio, bio);
+
+        // We are a server-side socket.
+        SSL_set_accept_state(_ssl);
+    }
+
     ~SslStreamSocket()
     {
         shutdown();
@@ -89,37 +116,6 @@ public:
         return StreamSocket::getPollEvents();
     }
 
-protected:
-    SslStreamSocket(const int fd) :
-        StreamSocket(fd),
-        _ssl(nullptr),
-        _sslWantsTo(SslWantsTo::ReadOrWrite),
-        _doHandshake(true)
-    {
-        BIO* bio = BIO_new(BIO_s_socket());
-        if (bio == nullptr)
-        {
-            throw std::runtime_error("Failed to create SSL BIO.");
-        }
-
-        BIO_set_fd(bio, fd, BIO_NOCLOSE);
-
-        _ssl = SslContext::newSsl();
-        if (!_ssl)
-        {
-            BIO_free(bio);
-            throw std::runtime_error("Failed to create SSL.");
-        }
-
-        SSL_set_bio(_ssl, bio, bio);
-
-        // We are a server-side socket.
-        SSL_set_accept_state(_ssl);
-    }
-
-    // Will construct us upon accept.
-    friend class ServerSocket;
-
 private:
 
     /// The possible next I/O operation that SSL want to do.
diff --git a/net/loolnb.cpp b/net/loolnb.cpp
index ab60d11..4e4ac38 100644
--- a/net/loolnb.cpp
+++ b/net/loolnb.cpp
@@ -37,9 +37,9 @@ constexpr int SslPortNumber = 9193;
 
 static std::string computeAccept(const std::string &key);
 
-template <class T>
-class SimpleResponseClient : public T
+class SimpleResponseClient : public ResponseClientInterface
 {
+    std::unique_ptr<StreamSocket> _socket;
     int _wsVersion;
     std::string _wsKey;
     std::string _wsProtocol;
@@ -47,16 +47,21 @@ class SimpleResponseClient : public T
     enum { HTTP, WEBSOCKET } _wsState;
 
 public:
-    SimpleResponseClient(const int fd) :
-        T(fd),
+    SimpleResponseClient() :
         _wsVersion(0),
         _wsState(HTTP)
     {
     }
-    virtual void handleHTTP()
+
+    virtual void setSocket(StreamSocket* socket) override
+    {
+        _socket.reset(socket);
+    }
+
+    void handleHTTP()
     {
         int number = 0;
-        MemoryInputStream message(&T::_inBuffer[0], T::_inBuffer.size());
+        MemoryInputStream message(&_socket->_inBuffer[0], _socket->_inBuffer.size());
         Poco::Net::HTTPRequest req;
         req.read(message);
 
@@ -66,7 +71,7 @@ public:
         // use Poco HTMLForm to parse the post message properly.
         // Otherwise, we should catch exceptions from the previous read/parse
         // and assume we don't have sufficient data, so we wait some more.
-        T::_inBuffer.clear();
+        _socket->_inBuffer.clear();
 
         StringTokenizer tokens(req.getURI(), "/?");
         if (tokens.count() == 4)
@@ -89,7 +94,7 @@ public:
                 << numberString;
             ;
             std::string str = oss.str();
-            T::_outBuffer.insert(T::_outBuffer.end(), str.begin(), str.end());
+            _socket->_outBuffer.insert(_socket->_outBuffer.end(), str.begin(), str.end());
         }
         else if (tokens.count() == 2 && tokens[1] == "ws")
         { // create our websocket goodness ...
@@ -106,7 +111,7 @@ public:
                 << "Sec-Websocket-Accept: " << computeAccept(_wsKey) << "\r\n"
                 << "\r\n";
             std::string str = oss.str();
-            T::_outBuffer.insert(T::_outBuffer.end(), str.begin(), str.end());
+            _socket->_outBuffer.insert(_socket->_outBuffer.end(), str.begin(), str.end());
             _wsState = WEBSOCKET;
         }
         else
@@ -130,7 +135,7 @@ public:
 
     virtual void handleIncomingMessage() override
     {
-        std::cerr << "incoming message with buffer size " << T::_inBuffer.size() << "\n";
+        std::cerr << "incoming message with buffer size " << _socket->_inBuffer.size() << "\n";
         if (_wsState == HTTP)
         {
             handleHTTP();
@@ -138,11 +143,11 @@ public:
         }
 
         // websocket fun !
-        size_t len = T::_inBuffer.size();
+        size_t len = _socket->_inBuffer.size();
         if (len < 2) // partial read
             return;
 
-        unsigned char *p = reinterpret_cast<unsigned char*>(&T::_inBuffer[0]);
+        unsigned char *p = reinterpret_cast<unsigned char*>(&_socket->_inBuffer[0]);
         bool fin = p[0] & 0x80;
         WSOpCode code = static_cast<WSOpCode>(p[0] & 0x0f);
         bool hasMask = p[1] & 0x80;
@@ -196,15 +201,15 @@ public:
         } else
             _wsPayload.insert(_wsPayload.end(), data, data + payloadLen);
 
-        T::_inBuffer.erase(T::_inBuffer.begin(), T::_inBuffer.begin() + headerLen + payloadLen);
+        _socket->_inBuffer.erase(_socket->_inBuffer.begin(), _socket->_inBuffer.begin() + headerLen + payloadLen);
 
         // FIXME: fin, aggregating payloads into _wsPayload etc.
         handleWSMessage(fin, code, _wsPayload);
         _wsPayload.clear();
     }
 
-    virtual void queueWSMessage(const std::vector<char> &data,
-                                WSOpCode code = WSOpCode::Binary)
+    void queueWSMessage(const std::vector<char> &data,
+                        WSOpCode code = WSOpCode::Binary)
     {
         size_t len = data.size();
         bool fin = false;
@@ -213,42 +218,42 @@ public:
         unsigned char header[2];
         header[0] = (fin ? 0x80 : 0) | static_cast<unsigned char>(code);
         header[1] = mask ? 0x80 : 0;
-        T::_outBuffer.push_back((char)header[0]);
+        _socket->_outBuffer.push_back((char)header[0]);
 
         // no out-bound masking ...
         if (len < 126)
         {
             header[1] |= len;
-            T::_outBuffer.push_back((char)header[1]);
+            _socket->_outBuffer.push_back((char)header[1]);
         }
         else if (len <= 0xffff)
         {
             header[1] |= 126;
-            T::_outBuffer.push_back((char)header[1]);
-            T::_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
+            _socket->_outBuffer.push_back((char)header[1]);
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
         }
         else
         {
             header[1] |= 127;
-            T::_outBuffer.push_back((char)header[1]);
-            T::_outBuffer.push_back(static_cast<char>((len >> 56) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 48) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 40) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 32) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 24) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 16) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
-            T::_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
+            _socket->_outBuffer.push_back((char)header[1]);
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 56) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 48) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 40) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 32) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 24) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 16) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 8) & 0xff));
+            _socket->_outBuffer.push_back(static_cast<char>((len >> 0) & 0xff));
         }
 
         // FIXME: pick random number and mask in the outbuffer etc.
         assert (!mask);
 
-        T::_outBuffer.insert(T::_outBuffer.end(), data.begin(), data.end());
+        _socket->_outBuffer.insert(_socket->_outBuffer.end(), data.begin(), data.end());
     }
 
-    virtual void handleWSMessage( bool fin, WSOpCode code, std::vector<char> &data)
+    void handleWSMessage(bool fin, WSOpCode code, std::vector<char> &data)
     {
         std::cerr << "Message: fin? " << fin << " code " << code << " data size " << data.size();
         if (code == WSOpCode::Text)
@@ -374,7 +379,7 @@ int main(int argc, const char**argv)
     {
         std::shared_ptr<Socket> create(const int fd) override
         {
-            return std::make_shared<SimpleResponseClient<StreamSocket>>(fd);
+            return std::make_shared<StreamSocket>(fd, new SimpleResponseClient());
         }
     };
 
@@ -382,7 +387,7 @@ int main(int argc, const char**argv)
     {
         std::shared_ptr<Socket> create(const int fd) override
         {
-            return std::make_shared<SimpleResponseClient<SslStreamSocket>>(fd);
+            return std::make_shared<SslStreamSocket>(fd, new SimpleResponseClient());
         }
     };
 
commit 46ca4050c4d4abc340e354890c933f6095587ef7
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Feb 22 15:45:41 2017 +0100

    nb: Let's avoid too much abstraction.
    
    Change-Id: If349e6273580b09386ad0a89467a99c6c2c0d4ec

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 5d4d617..779b526 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -283,8 +283,8 @@ private:
     std::vector<pollfd> _pollFds;
 };
 
-/// Abstract buffering socket.
-class BufferingSocket : public Socket
+/// A plain, non-blocking, data streaming socket.
+class StreamSocket : public Socket
 {
 public:
 
@@ -376,10 +376,16 @@ public:
     }
 
     /// Override to handle reading of socket data differently.
-    virtual int readData(char* buf, int len) = 0;
+    virtual int readData(char* buf, int len)
+    {
+        return ::read(getFD(), buf, len);
+    }
 
     /// Override to handle writing data to socket differently.
-    virtual int writeData(const char* buf, const int len) = 0;
+    virtual int writeData(const char* buf, const int len)
+    {
+        return ::write(getFD(), buf, len);
+    }
 
     int getPollEvents() override
     {
@@ -388,7 +394,7 @@ public:
     }
 
 protected:
-    BufferingSocket(const int fd) :
+    StreamSocket(const int fd) :
         Socket(fd)
     {
     }
@@ -402,31 +408,6 @@ private:
     virtual void handleIncomingMessage() = 0;
 };
 
-/// A plain, non-blocking, data streaming socket.
-class StreamSocket : public BufferingSocket
-{
-protected:
-    StreamSocket(const int fd) :
-        BufferingSocket(fd)
-    {
-    }
-
-    /// Override to handle reading of socket data differently.
-    virtual int readData(char* buf, int len)
-    {
-        return ::read(getFD(), buf, len);
-    }
-
-    /// Override to handle writing data to socket differently.
-    virtual int writeData(const char* buf, const int len)
-    {
-        return ::write(getFD(), buf, len);
-    }
-
-    // Will construct us upon accept.
-    friend class ServerSocket;
-};
-
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/net/SslSocket.hpp b/net/SslSocket.hpp
index 220447b..8a9b1f0 100644
--- a/net/SslSocket.hpp
+++ b/net/SslSocket.hpp
@@ -18,7 +18,7 @@
 #include "Socket.hpp"
 
 /// An SSL/TSL, non-blocking, data streaming socket.
-class SslStreamSocket : public BufferingSocket
+class SslStreamSocket : public StreamSocket
 {
 public:
     ~SslStreamSocket()
@@ -46,7 +46,7 @@ public:
         }
 
         // Default implementation.
-        return BufferingSocket::readIncomingData();
+        return StreamSocket::readIncomingData();
     }
 
     void writeOutgoingData() override
@@ -58,7 +58,7 @@ public:
         }
 
         // Default implementation.
-        BufferingSocket::writeOutgoingData();
+        StreamSocket::writeOutgoingData();
     }
 
     virtual int readData(char* buf, int len)
@@ -86,12 +86,12 @@ public:
         }
 
         // Do the default.
-        return BufferingSocket::getPollEvents();
+        return StreamSocket::getPollEvents();
     }
 
 protected:
     SslStreamSocket(const int fd) :
-        BufferingSocket(fd),
+        StreamSocket(fd),
         _ssl(nullptr),
         _sslWantsTo(SslWantsTo::ReadOrWrite),
         _doHandshake(true)


More information about the Libreoffice-commits mailing list