[Libreoffice-commits] online.git: Branch 'private/Ashod/nonblocking' - 7 commits - common/FileUtil.cpp loleaflet/src Makefile.am net/loolnb.cpp net/ServerSocket.hpp net/socket.hpp net/Socket.hpp net/ssl.cpp net/Ssl.cpp net/ssl.hpp net/Ssl.hpp net/SslSocket.hpp

Jan Holesovsky kendy at collabora.com
Wed Feb 22 06:34:55 UTC 2017


 Makefile.am                           |    2 
 common/FileUtil.cpp                   |    7 
 loleaflet/src/layer/tile/TileLayer.js |    9 
 net/ServerSocket.hpp                  |  101 +++++
 net/Socket.hpp                        |  432 ++++++++++++++++++++++
 net/Ssl.cpp                           |  265 +++++++++++++
 net/Ssl.hpp                           |   93 ++++
 net/SslSocket.hpp                     |  246 ++++++++++++
 net/loolnb.cpp                        |  104 +----
 net/socket.hpp                        |  657 ----------------------------------
 net/ssl.cpp                           |  265 -------------
 net/ssl.hpp                           |   93 ----
 12 files changed, 1179 insertions(+), 1095 deletions(-)

New commits:
commit 6087220eb64e06020b7f60584e6d9c361000bb2a
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Feb 21 19:55:04 2017 +0100

    We should be able to run with 5G of free space just fine.
    
    Change-Id: Ie5df96388eeaa0ddf1a41564ec7d52c283e6b1bb
    (cherry picked from commit 7eff2294d938d0e14db50a385ab9e226c14f7c77)

diff --git a/common/FileUtil.cpp b/common/FileUtil.cpp
index 078379b..52dd3ec 100644
--- a/common/FileUtil.cpp
+++ b/common/FileUtil.cpp
@@ -236,8 +236,15 @@ namespace FileUtil
         if (statfs(path.c_str(), &sfs) == -1)
             return true;
 
+        // we should be able to run just OK with 5GB
+        constexpr int64_t ENOUGH_SPACE = int64_t(5)*1024*1024*1024;
+
+        if (static_cast<int64_t>(sfs.f_bavail) * sfs.f_bsize > ENOUGH_SPACE)
+            return true;
+
         if (static_cast<double>(sfs.f_bavail) / sfs.f_blocks <= 0.05)
             return false;
+
         return true;
     }
 
commit 1e3aa895bc95c30cfaaf87e5f03aafdcc0dce223
Author: László Németh <laszlo.nemeth at collabora.com>
Date:   Tue Feb 21 11:22:20 2017 +0100

    loleaflet: debug mode: fade out blue color of the tiles
    
    after 1 sec, if it wasn't removed by a tile update.
    
    From commit bc19f90dd48a1792fca9d5b7bbf13b8f1b35134b
    (Don't send a tile that hasn't changed even if client asks for it),
    blue color of the requested tiles isn't removed completely.
    
    Change-Id: I0f4c152f61c2b0f70f1b7c23bd63d3e0bc80ec74
    (cherry picked from commit cc3b521572ccc33875ee179ca6c78b61cffb5087)

diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 62180dd..762ee03 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -2015,6 +2015,7 @@ L.TileLayer = L.GridLayer.extend({
 		if (tile._debugTile) {
 			tile._debugTile.setStyle({fillOpacity: 0.5, fillColor: 'blue'});
 			tile._debugTime.date = +new Date();
+			tile._debugTile.date = +new Date();
 			tile._debugInvalidateCount++;
 			this._debugInvalidateCount++;
 		}
@@ -2049,6 +2050,14 @@ L.TileLayer = L.GridLayer.extend({
 					rect.setStyle({fillOpacity: opac - 0.04});
 				}
 			}
+			for (var key in this._debugTiles) {
+				var rect = this._debugTiles[key];
+				var col = rect.options.fillColor;
+				var opac = rect.options.fillOpacity;
+				if (col === 'blue' && opac >= 0.04 && rect.date + 1000 < +new Date()) {
+					rect.setStyle({fillOpacity: opac - 0.04});
+				}
+			}
 			this._debugTimeoutId = setTimeout(function () { map._docLayer._debugTimeout(); }, 50);
 		}
 	},
commit a72338cc5b463b0ad8664d9e6488bf5ea5a35ba9
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Tue Feb 21 21:49:29 2017 -0500

    nb: de-templatize ServerSocket
    
    Change-Id: I5680bbf24ade807e34f67f7fce4698ffe5364cb2

diff --git a/net/ServerSocket.hpp b/net/ServerSocket.hpp
new file mode 100644
index 0000000..a206e7c
--- /dev/null
+++ b/net/ServerSocket.hpp
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SERVERSOCKET_HPP
+#define INCLUDED_SERVERSOCKET_HPP
+
+#include "config.h"
+
+#include "memory"
+
+#include "Socket.hpp"
+
+class SocketFactory
+{
+public:
+    virtual std::shared_ptr<Socket> create(const int fd) = 0;
+};
+
+/// A non-blocking, streaming socket.
+class ServerSocket : public Socket
+{
+public:
+    ServerSocket(SocketPoll& clientPoller, std::unique_ptr<SocketFactory> sockFactory) :
+        _clientPoller(clientPoller),
+        _sockFactory(std::move(sockFactory))
+    {
+    }
+
+    /// Binds to a local address (Servers only).
+    /// Does not retry on error.
+    /// Returns true on success only.
+    bool bind(const Poco::Net::SocketAddress& address)
+    {
+        // Enable address reuse to avoid stalling after
+        // recycling, when previous socket is TIME_WAIT.
+        //TODO: Might be worth refactoring out.
+        const int reuseAddress = 1;
+        constexpr unsigned int len = sizeof(reuseAddress);
+        ::setsockopt(getFD(), SOL_SOCKET, SO_REUSEADDR, &reuseAddress, len);
+
+        const int rc = ::bind(getFD(), address.addr(), address.length());
+        return (rc == 0);
+    }
+
+    /// Listen to incoming connections (Servers only).
+    /// Does not retry on error.
+    /// Returns true on success only.
+    bool listen(const int backlog = 64)
+    {
+        const int rc = ::listen(getFD(), backlog);
+        return (rc == 0);
+    }
+
+    /// Accepts an incoming connection (Servers only).
+    /// Does not retry on error.
+    /// Returns a valid Socket shared_ptr on success only.
+    std::shared_ptr<Socket> accept()
+    {
+        // Accept a connection (if any) and set it to non-blocking.
+        // We don't care about the client's address, so ignored.
+        const int rc = ::accept4(getFD(), nullptr, nullptr, SOCK_NONBLOCK);
+        return (rc != -1 ? _sockFactory->create(rc) : std::shared_ptr<Socket>(nullptr));
+    }
+
+    int getPollEvents() override
+    {
+        return POLLIN;
+    }
+
+    HandleResult handlePoll(int events) override
+    {
+        if (events & POLLIN)
+        {
+            std::shared_ptr<Socket> clientSocket = accept();
+            if (!clientSocket)
+            {
+                const std::string msg = "Failed to accept. (errno: ";
+                throw std::runtime_error(msg + std::strerror(errno) + ")");
+            }
+
+            std::cout << "Accepted client #" << clientSocket->getFD() << std::endl;
+            _clientPoller.insertNewSocket(clientSocket);
+        }
+
+        return Socket::HandleResult::CONTINUE;
+    }
+
+private:
+    SocketPoll& _clientPoller;
+    std::unique_ptr<SocketFactory> _sockFactory;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/net/Socket.hpp b/net/Socket.hpp
index eb9f9e9..5d4d617 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -424,7 +424,7 @@ protected:
     }
 
     // Will construct us upon accept.
-    template<class T> friend class ServerSocket;
+    friend class ServerSocket;
 };
 
 #endif
diff --git a/net/SslSocket.hpp b/net/SslSocket.hpp
index 270b2eb..220447b 100644
--- a/net/SslSocket.hpp
+++ b/net/SslSocket.hpp
@@ -118,7 +118,7 @@ protected:
     }
 
     // Will construct us upon accept.
-    template<class T> friend class ServerSocket;
+    friend class ServerSocket;
 
 private:
 
diff --git a/net/loolnb.cpp b/net/loolnb.cpp
index d22102b..ab60d11 100644
--- a/net/loolnb.cpp
+++ b/net/loolnb.cpp
@@ -29,6 +29,7 @@ using Poco::MemoryInputStream;
 using Poco::StringTokenizer;
 
 #include "Socket.hpp"
+#include "ServerSocket.hpp"
 #include "SslSocket.hpp"
 
 constexpr int HttpPortNumber = 9191;
@@ -322,83 +323,11 @@ private:
 Poco::Net::SocketAddress addrHttp("127.0.0.1", HttpPortNumber);
 Poco::Net::SocketAddress addrSsl("127.0.0.1", SslPortNumber);
 
-/// A non-blocking, streaming socket.
-/// T is the socket type created by accept.
-template <class T>
-class ServerSocket : public Socket
-{
-    SocketPoll& _clientPoller;
-public:
-    ServerSocket(SocketPoll& clientPoller)
-        : _clientPoller(clientPoller)
-    {
-    }
-
-    /// Binds to a local address (Servers only).
-    /// Does not retry on error.
-    /// Returns true on success only.
-    bool bind(const Poco::Net::SocketAddress& address)
-    {
-        // Enable address reuse to avoid stalling after
-        // recycling, when previous socket is TIME_WAIT.
-        //TODO: Might be worth refactoring out.
-        const int reuseAddress = 1;
-        constexpr unsigned int len = sizeof(reuseAddress);
-        ::setsockopt(getFD(), SOL_SOCKET, SO_REUSEADDR, &reuseAddress, len);
-
-        const int rc = ::bind(getFD(), address.addr(), address.length());
-        return (rc == 0);
-    }
-
-    /// Listen to incoming connections (Servers only).
-    /// Does not retry on error.
-    /// Returns true on success only.
-    bool listen(const int backlog = 64)
-    {
-        const int rc = ::listen(getFD(), backlog);
-        return (rc == 0);
-    }
-
-    /// Accepts an incoming connection (Servers only).
-    /// Does not retry on error.
-    /// Returns a valid Socket shared_ptr on success only.
-    std::shared_ptr<Socket> accept()
-    {
-        // Accept a connection (if any) and set it to non-blocking.
-        // We don't care about the client's address, so ignored.
-        const int rc = ::accept4(getFD(), nullptr, nullptr, SOCK_NONBLOCK);
-        return (rc != -1 ? std::make_shared<T>(rc) : std::shared_ptr<T>(nullptr));
-    }
-
-    int getPollEvents() override
-    {
-        return POLLIN;
-    }
-
-    HandleResult handlePoll( int events ) override
-    {
-        if (events & POLLIN)
-        {
-            std::shared_ptr<Socket> clientSocket = accept();
-            if (!clientSocket)
-            {
-                const std::string msg = "Failed to accept. (errno: ";
-                throw std::runtime_error(msg + std::strerror(errno) + ")");
-            }
-
-            std::cout << "Accepted client #" << clientSocket->getFD() << std::endl;
-            _clientPoller.insertNewSocket(clientSocket);
-        }
-
-        return Socket::HandleResult::CONTINUE;
-    }
-};
-
-template <typename T>
-void server(const Poco::Net::SocketAddress& addr, SocketPoll& clientPoller)
+void server(const Poco::Net::SocketAddress& addr, SocketPoll& clientPoller,
+            std::unique_ptr<SocketFactory> sockFactory)
 {
     // Start server.
-    auto server = std::make_shared<ServerSocket<T>>(clientPoller);
+    auto server = std::make_shared<ServerSocket>(clientPoller, std::move(sockFactory));
     if (!server->bind(addr))
     {
         const std::string msg = "Failed to bind. (errno: ";
@@ -441,11 +370,28 @@ int main(int argc, const char**argv)
         }
     });
 
+    class PlainSocketFactory : public SocketFactory
+    {
+        std::shared_ptr<Socket> create(const int fd) override
+        {
+            return std::make_shared<SimpleResponseClient<StreamSocket>>(fd);
+        }
+    };
+
+    class SslSocketFactory : public SocketFactory
+    {
+        std::shared_ptr<Socket> create(const int fd) override
+        {
+            return std::make_shared<SimpleResponseClient<SslStreamSocket>>(fd);
+        }
+    };
+
+
     // Start the server.
     if (!strcmp(argv[argc-1], "ssl"))
-        server<SimpleResponseClient<SslStreamSocket>>(addrSsl, poller);
+        server(addrSsl, poller, std::unique_ptr<SocketFactory>{new SslSocketFactory});
     else
-        server<SimpleResponseClient<StreamSocket>>(addrHttp, poller);
+        server(addrHttp, poller, std::unique_ptr<SocketFactory>{new PlainSocketFactory});
 
     std::cout << "Shutting down server." << std::endl;
 
commit 25530284edd99de8ddc3b1933f94c3904b0a5c46
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Tue Feb 21 20:54:13 2017 -0500

    nb: move SslStreamSocket to own file
    
    Change-Id: I4b6f2b0b4be3fc595dfeafc8e2b6d3e73694bd49

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 8425b9f..eb9f9e9 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -7,6 +7,9 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#ifndef INCLUDED_SOCKET_HPP
+#define INCLUDED_SOCKET_HPP
+
 #include "config.h"
 
 #include <poll.h>
@@ -20,8 +23,6 @@
 
 #include <Poco/Net/SocketAddress.h>
 
-#include "Ssl.hpp"
-
 /// A non-blocking, streaming socket.
 class Socket
 {
@@ -426,228 +427,6 @@ protected:
     template<class T> friend class ServerSocket;
 };
 
-/// An SSL/TSL, non-blocking, data streaming socket.
-class SslStreamSocket : public BufferingSocket
-{
-public:
-    ~SslStreamSocket()
-    {
-        shutdown();
-        SSL_free(_ssl);
-    }
-
-    /// Shutdown the TLS/SSL connection properly.
-    void shutdown()
-    {
-        if (SSL_shutdown(_ssl) == 0)
-        {
-            // Complete the bidirectional shutdown.
-            SSL_shutdown(_ssl);
-        }
-    }
-
-    bool readIncomingData() override
-    {
-        const int rc = doHandshake();
-        if (rc <= 0)
-        {
-            return (rc != 0);
-        }
-
-        // Default implementation.
-        return BufferingSocket::readIncomingData();
-    }
-
-    void writeOutgoingData() override
-    {
-        const int rc = doHandshake();
-        if (rc <= 0)
-        {
-            return;
-        }
-
-        // Default implementation.
-        BufferingSocket::writeOutgoingData();
-    }
-
-    virtual int readData(char* buf, int len)
-    {
-        return handleSslState(SSL_read(_ssl, buf, len));
-    }
-
-    virtual int writeData(const char* buf, const int len)
-    {
-        assert (len > 0); // Never write 0 bytes.
-        return handleSslState(SSL_write(_ssl, buf, len));
-    }
-
-    int getPollEvents() override
-    {
-        if (_sslWantsTo == SslWantsTo::Read)
-        {
-            // Must read next before attempting to write.
-            return POLLIN;
-        }
-        else if (_sslWantsTo == SslWantsTo::Write)
-        {
-            // Must write next before attempting to read.
-            return POLLOUT;
-        }
-
-        // Do the default.
-        return BufferingSocket::getPollEvents();
-    }
-
-protected:
-    SslStreamSocket(const int fd) :
-        BufferingSocket(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.
-    template<class T> friend class ServerSocket;
-
-private:
-
-    /// The possible next I/O operation that SSL want to do.
-    enum class SslWantsTo
-    {
-        ReadOrWrite,
-        Read,
-        Write
-    };
-
-    int doHandshake()
-    {
-        if (_doHandshake)
-        {
-            int rc;
-            do
-            {
-                rc = SSL_do_handshake(_ssl);
-            }
-            while (rc < 0 && errno == EINTR);
-
-            if (rc <= 0)
-            {
-                rc = handleSslState(rc);
-                if (rc <= 0)
-                {
-                    return (rc != 0);
-                }
-            }
-
-            _doHandshake = false;
-        }
-
-        // Handshake complete.
-        return 1;
-    }
-
-    /// Handles the state of SSL after read or write.
-    int handleSslState(const int rc)
-    {
-        if (rc > 0)
-        {
-            // Success: Reset so we can do either.
-            _sslWantsTo = SslWantsTo::ReadOrWrite;
-            return rc;
-        }
-
-        // Last operation failed. Find out if SSL was trying
-        // to do something different that failed, or not.
-        const int sslError = SSL_get_error(_ssl, rc);
-        switch (sslError)
-        {
-        case SSL_ERROR_ZERO_RETURN:
-            // Shutdown complete, we're disconnected.
-            return 0;
-
-        case SSL_ERROR_WANT_READ:
-            _sslWantsTo = SslWantsTo::Read;
-            return rc;
-
-        case SSL_ERROR_WANT_WRITE:
-            _sslWantsTo = SslWantsTo::Write;
-            return rc;
-
-        case SSL_ERROR_WANT_CONNECT:
-        case SSL_ERROR_WANT_ACCEPT:
-        case SSL_ERROR_WANT_X509_LOOKUP:
-            // Unexpected.
-            return rc;
-
-        case SSL_ERROR_SYSCALL:
-            if (errno != 0)
-            {
-                // Posix API error, let the caller handle.
-                return rc;
-            }
-
-            // Fallthrough...
-        default:
-            {
-                // The error is comming from BIO. Find out what happened.
-                const long bioError = ERR_get_error();
-                if (bioError == 0)
-                {
-                    if (rc == 0)
-                    {
-                        // Socket closed.
-                        return 0;
-                    }
-                    else if (rc == -1)
-                    {
-                        throw std::runtime_error("SSL Socket closed unexpectedly.");
-                    }
-                    else
-                    {
-                        throw std::runtime_error("SSL BIO reported error [" + std::to_string(rc) + "].");
-                    }
-                }
-                else
-                {
-                    char buf[512];
-                    ERR_error_string_n(bioError, buf, sizeof(buf));
-                    throw std::runtime_error(buf);
-                }
-            }
-            break;
-        }
-
-        return rc;
-    }
-
-private:
-    SSL* _ssl;
-    /// During handshake SSL might want to read
-    /// on write, or write on read.
-    SslWantsTo _sslWantsTo;
-    /// We must do the handshake during the first
-    /// read or write in non-blocking.
-    bool _doHandshake;
-};
+#endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/net/SslSocket.hpp b/net/SslSocket.hpp
new file mode 100644
index 0000000..270b2eb
--- /dev/null
+++ b/net/SslSocket.hpp
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SSLSOCKET_HPP
+#define INCLUDED_SSLSOCKET_HPP
+
+#include "config.h"
+
+#include <cerrno>
+
+#include "Ssl.hpp"
+#include "Socket.hpp"
+
+/// An SSL/TSL, non-blocking, data streaming socket.
+class SslStreamSocket : public BufferingSocket
+{
+public:
+    ~SslStreamSocket()
+    {
+        shutdown();
+        SSL_free(_ssl);
+    }
+
+    /// Shutdown the TLS/SSL connection properly.
+    void shutdown()
+    {
+        if (SSL_shutdown(_ssl) == 0)
+        {
+            // Complete the bidirectional shutdown.
+            SSL_shutdown(_ssl);
+        }
+    }
+
+    bool readIncomingData() override
+    {
+        const int rc = doHandshake();
+        if (rc <= 0)
+        {
+            return (rc != 0);
+        }
+
+        // Default implementation.
+        return BufferingSocket::readIncomingData();
+    }
+
+    void writeOutgoingData() override
+    {
+        const int rc = doHandshake();
+        if (rc <= 0)
+        {
+            return;
+        }
+
+        // Default implementation.
+        BufferingSocket::writeOutgoingData();
+    }
+
+    virtual int readData(char* buf, int len)
+    {
+        return handleSslState(SSL_read(_ssl, buf, len));
+    }
+
+    virtual int writeData(const char* buf, const int len)
+    {
+        assert (len > 0); // Never write 0 bytes.
+        return handleSslState(SSL_write(_ssl, buf, len));
+    }
+
+    int getPollEvents() override
+    {
+        if (_sslWantsTo == SslWantsTo::Read)
+        {
+            // Must read next before attempting to write.
+            return POLLIN;
+        }
+        else if (_sslWantsTo == SslWantsTo::Write)
+        {
+            // Must write next before attempting to read.
+            return POLLOUT;
+        }
+
+        // Do the default.
+        return BufferingSocket::getPollEvents();
+    }
+
+protected:
+    SslStreamSocket(const int fd) :
+        BufferingSocket(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.
+    template<class T> friend class ServerSocket;
+
+private:
+
+    /// The possible next I/O operation that SSL want to do.
+    enum class SslWantsTo
+    {
+        ReadOrWrite,
+        Read,
+        Write
+    };
+
+    int doHandshake()
+    {
+        if (_doHandshake)
+        {
+            int rc;
+            do
+            {
+                rc = SSL_do_handshake(_ssl);
+            }
+            while (rc < 0 && errno == EINTR);
+
+            if (rc <= 0)
+            {
+                rc = handleSslState(rc);
+                if (rc <= 0)
+                {
+                    return (rc != 0);
+                }
+            }
+
+            _doHandshake = false;
+        }
+
+        // Handshake complete.
+        return 1;
+    }
+
+    /// Handles the state of SSL after read or write.
+    int handleSslState(const int rc)
+    {
+        if (rc > 0)
+        {
+            // Success: Reset so we can do either.
+            _sslWantsTo = SslWantsTo::ReadOrWrite;
+            return rc;
+        }
+
+        // Last operation failed. Find out if SSL was trying
+        // to do something different that failed, or not.
+        const int sslError = SSL_get_error(_ssl, rc);
+        switch (sslError)
+        {
+        case SSL_ERROR_ZERO_RETURN:
+            // Shutdown complete, we're disconnected.
+            return 0;
+
+        case SSL_ERROR_WANT_READ:
+            _sslWantsTo = SslWantsTo::Read;
+            return rc;
+
+        case SSL_ERROR_WANT_WRITE:
+            _sslWantsTo = SslWantsTo::Write;
+            return rc;
+
+        case SSL_ERROR_WANT_CONNECT:
+        case SSL_ERROR_WANT_ACCEPT:
+        case SSL_ERROR_WANT_X509_LOOKUP:
+            // Unexpected.
+            return rc;
+
+        case SSL_ERROR_SYSCALL:
+            if (errno != 0)
+            {
+                // Posix API error, let the caller handle.
+                return rc;
+            }
+
+            // Fallthrough...
+        default:
+            {
+                // The error is comming from BIO. Find out what happened.
+                const long bioError = ERR_get_error();
+                if (bioError == 0)
+                {
+                    if (rc == 0)
+                    {
+                        // Socket closed.
+                        return 0;
+                    }
+                    else if (rc == -1)
+                    {
+                        throw std::runtime_error("SSL Socket closed unexpectedly.");
+                    }
+                    else
+                    {
+                        throw std::runtime_error("SSL BIO reported error [" + std::to_string(rc) + "].");
+                    }
+                }
+                else
+                {
+                    char buf[512];
+                    ERR_error_string_n(bioError, buf, sizeof(buf));
+                    throw std::runtime_error(buf);
+                }
+            }
+            break;
+        }
+
+        return rc;
+    }
+
+private:
+    SSL* _ssl;
+    /// During handshake SSL might want to read
+    /// on write, or write on read.
+    SslWantsTo _sslWantsTo;
+    /// We must do the handshake during the first
+    /// read or write in non-blocking.
+    bool _doHandshake;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/net/loolnb.cpp b/net/loolnb.cpp
index 71de984..d22102b 100644
--- a/net/loolnb.cpp
+++ b/net/loolnb.cpp
@@ -28,8 +28,8 @@
 using Poco::MemoryInputStream;
 using Poco::StringTokenizer;
 
-#include "Ssl.hpp"
 #include "Socket.hpp"
+#include "SslSocket.hpp"
 
 constexpr int HttpPortNumber = 9191;
 constexpr int SslPortNumber = 9193;
commit b5d1500e971d51cfa6b05d57dc9ae0bdd4d9f650
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Tue Feb 21 20:43:51 2017 -0500

    nb: more consistent filenames
    
    Change-Id: I2f1ff0b18080d469dc68b75ea0d7b9ddf5ea7d57

diff --git a/Makefile.am b/Makefile.am
index 08a522d..e4d4f75 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -91,7 +91,7 @@ loolwsd_fuzzer_SOURCES = $(loolwsd_sources) \
                          kit/DummyLibreOfficeKit.cpp
 
 loolnb_SOURCES = net/loolnb.cpp \
-                 net/ssl.cpp \
+                 net/Ssl.cpp \
                  common/Log.cpp \
                  common/Util.cpp
 
diff --git a/net/socket.hpp b/net/Socket.hpp
similarity index 99%
rename from net/socket.hpp
rename to net/Socket.hpp
index 82f62e1..8425b9f 100644
--- a/net/socket.hpp
+++ b/net/Socket.hpp
@@ -20,7 +20,7 @@
 
 #include <Poco/Net/SocketAddress.h>
 
-#include "ssl.hpp"
+#include "Ssl.hpp"
 
 /// A non-blocking, streaming socket.
 class Socket
diff --git a/net/ssl.cpp b/net/Ssl.cpp
similarity index 99%
rename from net/ssl.cpp
rename to net/Ssl.cpp
index f05ab64..0b9af1e 100644
--- a/net/ssl.cpp
+++ b/net/Ssl.cpp
@@ -7,7 +7,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include "ssl.hpp"
+#include "Ssl.hpp"
 #include "config.h"
 
 #include <sys/syscall.h>
diff --git a/net/ssl.hpp b/net/Ssl.hpp
similarity index 100%
rename from net/ssl.hpp
rename to net/Ssl.hpp
diff --git a/net/loolnb.cpp b/net/loolnb.cpp
index a25007d..71de984 100644
--- a/net/loolnb.cpp
+++ b/net/loolnb.cpp
@@ -28,8 +28,8 @@
 using Poco::MemoryInputStream;
 using Poco::StringTokenizer;
 
-#include "ssl.hpp"
-#include "socket.hpp"
+#include "Ssl.hpp"
+#include "Socket.hpp"
 
 constexpr int HttpPortNumber = 9191;
 constexpr int SslPortNumber = 9193;
commit 80d9e6374b0a3f808301b737c3e5f6a3122d0602
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Tue Feb 21 20:34:37 2017 -0500

    nb: write while output buffer not empty
    
    Change-Id: I257b72365b4711fd7ffc8bbda5a21d501828575b

diff --git a/net/socket.hpp b/net/socket.hpp
index 46d1e92..82f62e1 100644
--- a/net/socket.hpp
+++ b/net/socket.hpp
@@ -352,7 +352,7 @@ public:
     virtual void writeOutgoingData()
     {
         assert(!_outBuffer.empty());
-        while (!_outBuffer.empty())
+        do
         {
             ssize_t len;
             do
@@ -363,8 +363,7 @@ public:
 
             if (len > 0)
             {
-                _outBuffer.erase(_outBuffer.begin(),
-                                _outBuffer.begin() + len);
+                _outBuffer.erase(_outBuffer.begin(), _outBuffer.begin() + len);
             }
             else
             {
@@ -372,6 +371,7 @@ public:
                 break;
             }
         }
+        while (!_outBuffer.empty());
     }
 
     /// Override to handle reading of socket data differently.
commit 1129b901d32b9c965e055f5c0071bf1cf5c10cd7
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Tue Feb 21 20:12:17 2017 -0500

    nb: failing to drain the wakeup pipe is no error
    
    Change-Id: Ie7a75f96b655cb7861d1bae539d78cbf702cf334

diff --git a/net/socket.hpp b/net/socket.hpp
index 7ce7378..46d1e92 100644
--- a/net/socket.hpp
+++ b/net/socket.hpp
@@ -204,11 +204,7 @@ public:
             addNewSocketsToPoll();
 
             // Clear the data.
-            int dump;
-            while (::read(_wakeup[0], &dump, sizeof(dump)) == -1 && errno == EINTR)
-            {
-                // Nothing to do.
-            }
+            int dump = ::read(_wakeup[0], &dump, sizeof(dump));
         }
     }
 


More information about the Libreoffice-commits mailing list