changeset 574:d1afc6cc5974

Net: allow ownership and non-ownership in TlsSocket
author David Demelier <markand@malikania.fr>
date Tue, 19 Jul 2016 15:05:42 +0200
parents db2934ac95c7
children 0f6501d6df34
files modules/net/net.hpp
diffstat 1 files changed, 53 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/modules/net/net.hpp	Tue Jul 19 13:36:29 2016 +0200
+++ b/modules/net/net.hpp	Tue Jul 19 15:05:42 2016 +0200
@@ -2021,6 +2021,9 @@
     using Context = std::shared_ptr<SSL_CTX>;
     using Ssl = std::unique_ptr<SSL, void (*)(SSL *)>;
 
+    // Determine if we created a TlsSocket from a temporary or a lvalue.
+    bool m_mustclose{false};
+
     Context m_context;
     Ssl m_ssl{nullptr, nullptr};
 
@@ -2058,16 +2061,7 @@
         }
     }
 
-public:
-    /**
-     * Wrap a socket around an existing one, takes ownership.
-     *
-     * \param sock the TCP socket
-     * \param mode the mode
-     * \param method the method
-     */
-    inline TlsSocket(TcpSocket sock, Mode mode = Server, const SSL_METHOD *method = TLSv1_method())
-        : Socket(std::move(sock))
+    void create(Mode mode, const SSL_METHOD *method)
     {
 #if !defined(NET_NO_SSL_AUTO_INIT)
         ssl::init();
@@ -2083,6 +2077,55 @@
             SSL_set_connect_state(m_ssl.get());
     }
 
+public:
+    /**
+     * Create a socket around an existing one.
+     *
+     * The original socket is moved to this instance and must not be used anymore.
+     *
+     * \param sock the TCP socket
+     * \param mode the mode
+     * \param method the method
+     */
+    TlsSocket(TcpSocket &&sock, Mode mode = Server, const SSL_METHOD *method = TLSv1_method())
+        : Socket(std::move(sock))
+        , m_mustclose(true)
+    {
+        create(mode, method);
+    }
+
+    /**
+     * Wrap a socket around an existing one without taking ownership.
+     *
+     * The original socket must still exist until this TlsSocket is closed.
+     *
+     * \param sock the TCP socket
+     * \param mode the mode
+     * \param method the method
+     */
+    TlsSocket(TcpSocket &sock, Mode mode = Server, const SSL_METHOD *method = TLSv1_method())
+        : Socket(sock.handle())
+    {
+        create(mode, method);
+    }
+
+    /**
+     * Destroy the socket if owned.
+     */
+    ~TlsSocket()
+    {
+        /**
+         * If the socket has been created from a rvalue this class owns the
+         * socket and will close it in the parent destructor.
+         *
+         * Otherwise, when created from a lvalue, mark this socket as invalid
+         * to avoid double close'ing it as two sockets points to the same
+         * descriptor.
+         */
+        if (!m_mustclose)
+            m_handle = Invalid;
+    }
+
     /**
      * Get the type of socket.
      *