changeset 379:57ce1a6293b9

Socket: bring SocketSsl back in the run
author David Demelier <markand@malikania.fr>
date Fri, 19 Jun 2015 11:18:53 +0200
parents 92457ea8f7e2
children 06b0f405c58f
files C++/modules/Socket/Socket.cpp C++/modules/Socket/Socket.h C++/modules/Socket/SocketSsl.cpp C++/modules/Socket/SocketSsl.h
diffstat 4 files changed, 84 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Socket/Socket.cpp	Fri Jun 19 10:52:54 2015 +0200
+++ b/C++/modules/Socket/Socket.cpp	Fri Jun 19 11:18:53 2015 +0200
@@ -26,6 +26,14 @@
  * -------------------------------------------------------- */
 
 #if defined(_WIN32)
+const Socket::Handle Socket::Invalid{INVALID_SOCKET};
+const int Socket::Error{SOCKET_ERROR};
+#else
+const int Socket::Invalid{-1};
+const int Socket::Error{-1};
+#endif
+
+#if defined(_WIN32)
 
 std::string Socket::syserror(int errn)
 {
--- a/C++/modules/Socket/Socket.h	Fri Jun 19 10:52:54 2015 +0200
+++ b/C++/modules/Socket/Socket.h	Fri Jun 19 11:18:53 2015 +0200
@@ -71,6 +71,10 @@
  */
 class SocketError : public std::exception {
 public:
+	/**
+	 * @enum Code
+	 * @brief Which kind of error
+	 */
 	enum Code {
 		WouldBlockRead,		///!< The operation would block for reading
 		WouldBlockWrite,	///!< The operation would block for writing
@@ -78,10 +82,12 @@
 		System			///!< There is a system error
 	};
 
+private:
 	Code m_code;
 	std::string m_function;
 	std::string m_error;
 
+public:
 	/**
 	 * Constructor that use the last system error.
 	 *
@@ -165,12 +171,34 @@
 	 * and Windows.
 	 */
 #if defined(_WIN32)
+	/**
+	 * Socket type, SOCKET.
+	 */
 	using Handle	= SOCKET;
+
+	/**
+	 * Argument to pass to set.
+	 */
 	using ConstArg	= const char *;
+
+	/**
+	 * Argument to pass to get.
+	 */
 	using Arg	= char *;
 #else
+	/**
+	 * Socket type, int.
+	 */
 	using Handle	= int;
+
+	/**
+	 * Argument to pass to set.
+	 */
 	using ConstArg	= const void *;
+
+	/**
+	 * Argument to pass to get.
+	 */
 	using Arg	= void *;
 #endif
 
@@ -183,11 +211,25 @@
 	 * to Windows.
 	 */
 #if defined(_WIN32)
-	static constexpr const Handle Invalid	= INVALID_SOCKET;
-	static constexpr const int Error	= SOCKET_ERROR;
+	/**
+	 * Socket creation failure or invalidation.
+	 */
+	static const Handle Invalid;
+
+	/**
+	 * Socket operation failure.
+	 */
+	static const int Error;
 #else
-	static constexpr const int Invalid	= -1;
-	static constexpr const int Error	= -1;
+	/**
+	 * Socket creation failure or invalidation.
+	 */
+	static const int Invalid;
+
+	/**
+	 * Socket operation failure.
+	 */
+	static const int Error;
 #endif
 
 	/* }}} */
@@ -205,11 +247,17 @@
 	static std::atomic<bool> s_initialized;
 
 public:
+	/**
+	 * Calls WSACleanup.
+	 */
 	static inline void finish() noexcept
 	{
 		WSACleanup();
 	}
 
+	/**
+	 * Initialize using WSAStartup.
+	 */
 	static inline void initialize() noexcept
 	{
 		std::lock_guard<std::mutex> lock(s_mutex);
@@ -245,8 +293,8 @@
 	/* }}} */
 
 protected:
-	Handle m_handle{Invalid};
-	SocketState m_state{SocketState::Opened};
+	Handle m_handle{Invalid};			//!< The native handle
+	SocketState m_state{SocketState::Opened};	//!< The socket state
 
 public:
 	/**
--- a/C++/modules/Socket/SocketSsl.cpp	Fri Jun 19 10:52:54 2015 +0200
+++ b/C++/modules/Socket/SocketSsl.cpp	Fri Jun 19 11:18:53 2015 +0200
@@ -41,10 +41,10 @@
 std::mutex SocketSsl::s_sslMutex;
 std::atomic<bool> SocketSsl::s_sslInitialized{false};
 
-SocketSsl::SocketSsl(Socket::Handle handle, SSL_CTX *context, SSL *ssl)
-	: SocketTcp(handle)
-	, m_context(context, SSL_CTX_free)
-	, m_ssl(ssl, SSL_free)
+SocketSsl::SocketSsl(std::unique_ptr<SocketTcp> sc, SSL_CTX *context, SSL *ssl)
+	: SocketTcp{std::move(*sc)}
+	, m_context{context, SSL_CTX_free}
+	, m_ssl{ssl, SSL_free}
 {
 #if !defined(SOCKET_NO_SSL_INIT)
 	if (!s_sslInitialized) {
@@ -54,37 +54,32 @@
 }
 
 SocketSsl::SocketSsl(int family, int protocol, SocketSslOptions options)
-	: SocketTcp(family, protocol)
-	, m_options(std::move(options))
+	: SocketTcp{family, protocol}
+	, m_context{nullptr, nullptr}
+	, m_ssl{nullptr, nullptr}
+	, m_options{std::move(options)}
 {
 #if !defined(SOCKET_NO_SSL_INIT)
 	if (!s_sslInitialized) {
 		sslInitialize();
 	}
 #endif
+	m_context = ContextHandle{SSL_CTX_new(sslMethod(m_options.method)), SSL_CTX_free};
+	m_ssl = SslHandle{SSL_new(m_context.get()), SSL_free};
+
+	SSL_set_fd(m_ssl.get(), m_handle);
 }
 
 void SocketSsl::connect(const std::unique_ptr<SocketAddress> &address)
 {
-#if 0
-	std::unique_ptr<SocketTcp> standard = SocketTcp::connect(address);
-
-	// Context first
-	auto context = SSL_CTX_new(sslMethod(m_options.method));
-
-	m_context = ContextHandle(context, SSL_CTX_free);
+	// 1. Standard connect
+	SocketTcp::connect(address);
 
-	// SSL object then
-	auto ssl = SSL_new(context);
-
-	m_ssl = SslHandle(ssl, SSL_free);
-
-	SSL_set_fd(ssl, m_handle);
-
-	auto ret = SSL_connect(ssl);
+	// 2. OpenSSL handshake
+	auto ret = SSL_connect(m_ssl.get());
 
 	if (ret <= 0) {
-		auto error = SSL_get_error(ssl, ret);
+		auto error = SSL_get_error(m_ssl.get(), ret);
 
 		if (error == SSL_ERROR_WANT_READ) {
 			throw SocketError(SocketError::WouldBlockRead, "connect", "Operation in progress");
@@ -96,13 +91,11 @@
 	}
 
 	m_state = SocketState::Connected;
-#endif
 }
 
 std::unique_ptr<SocketTcp> SocketSsl::accept(std::unique_ptr<SocketAddress> &info)
 {
-#if 0
-	auto client = standardAccept(info);
+	auto client = SocketTcp::accept(info);
 	auto context = SSL_CTX_new(sslMethod(m_options.method));
 
 	if (m_options.certificate.size() > 0)
@@ -110,14 +103,13 @@
 	if (m_options.privateKey.size() > 0)
 		SSL_CTX_use_PrivateKey_file(context, m_options.privateKey.c_str(), SSL_FILETYPE_PEM);
 	if (m_options.verify && !SSL_CTX_check_private_key(context)) {
-		client.close();
 		throw SocketError(SocketError::System, "accept", "certificate failure");
 	}
 
 	// SSL object
 	auto ssl = SSL_new(context);
 
-	SSL_set_fd(ssl, client.handle());
+	SSL_set_fd(ssl, client->handle());
 
 	auto ret = SSL_accept(ssl);
 
@@ -133,8 +125,7 @@
 		}
 	}
 
-	return SocketSsl(client.handle(), context, ssl);
-#endif
+	return std::make_unique<SocketSsl>(std::move(client), context, ssl);
 }
 
 unsigned SocketSsl::recv(void *data, unsigned len)
--- a/C++/modules/Socket/SocketSsl.h	Fri Jun 19 10:52:54 2015 +0200
+++ b/C++/modules/Socket/SocketSsl.h	Fri Jun 19 11:18:53 2015 +0200
@@ -120,11 +120,11 @@
 	/**
 	 * Create a SocketSsl from an already created one.
 	 *
-	 * @param handle the native handle
+	 * @param sc the standard TCP socket
 	 * @param context the context
 	 * @param ssl the ssl object
 	 */
-	SocketSsl(Socket::Handle handle, SSL_CTX *context, SSL *ssl);
+	SocketSsl(std::unique_ptr<SocketTcp> sc, SSL_CTX *context, SSL *ssl);
 
 	/**
 	 * Open a SSL socket with the specified family. Automatically