changeset 467:41766abe942e

Socket: - Protocol is passed before Address, - Tls has dedicated funtions to prepare the socket before creating it.
author David Demelier <markand@malikania.fr>
date Wed, 04 Nov 2015 20:53:36 +0100
parents a126c10d9321
children becd06089e8f
files C++/modules/Socket/Sockets.h C++/tests/Socket/main.cpp
diffstat 2 files changed, 109 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Socket/Sockets.h	Wed Nov 04 20:36:07 2015 +0100
+++ b/C++/modules/Socket/Sockets.h	Wed Nov 04 20:53:36 2015 +0100
@@ -620,11 +620,11 @@
 	 *
 	 * Domain and type are determined by the Address and Protocol object.
 	 *
+	 * @param protocol the protocol
 	 * @param address which type of address
-	 * @param type the type instance
 	 */
-	explicit inline Socket(const Address &address = {}, Protocol proto = Protocol{})
-		: Socket{address.domain(), proto.type(), 0, std::move(proto)}
+	explicit inline Socket(Protocol protocol = {}, const Address &address = {})
+		: Socket{address.domain(), protocol.type(), 0, std::move(protocol)}
 	{
 	}
 
@@ -633,12 +633,12 @@
 	 *
 	 * @param handle the native descriptor
 	 * @param state specify the socket state
-	 * @param type the type of socket implementation
+	 * @param protocol the type of socket implementation
 	 * @post action is set to None
 	 * @post condition is set to None
 	 */
-	explicit inline Socket(Handle handle, State state = State::Closed, Protocol type = Protocol{}) noexcept
-		: m_proto(std::move(type))
+	explicit inline Socket(Handle handle, State state = State::Closed, Protocol protocol = {}) noexcept
+		: m_proto(std::move(protocol))
 		, m_state{state}
 		, m_handle{handle}
 	{
@@ -1250,7 +1250,7 @@
 		other.m_handle = Invalid;
 		other.m_state = State::Closed;
 		other.m_action = Action::None;
-		other.m_conditon = Condition::None;
+		other.m_condition = Condition::None;
 
 		return *this;
 	}
@@ -1686,6 +1686,7 @@
 	 *
 	 * @param sc the socket
 	 * @param address the address destination
+	 * @param length the address length
 	 * @return the socket
 	 * @throw Error on errors
 	 */
@@ -1907,20 +1908,24 @@
 
 #if !defined(SOCKET_NO_SSL)
 
+namespace ssl {
+
+/**
+ * @enum Method
+ * @brief Which OpenSSL method to use.
+ */
+enum Method {
+	Tlsv1,		//!< TLS v1.2 (recommended)
+	Sslv3		//!< SSLv3
+};
+
+} // !ssl
+
 /**
  * @class Tls
  * @brief OpenSSL secure layer for TCP
  */
 class Tls : private Tcp {
-public:
-	/**
-	 * OpenSSL method to use.
-	 */
-	enum Method {
-		Tlsv1,	//!< Tlsv1 (recommended)
-		Sslv3	//!< SSL v3
-	};
-
 private:
 	using Context = std::shared_ptr<SSL_CTX>;
 	using Ssl = std::unique_ptr<SSL, void (*)(SSL *)>;
@@ -1929,15 +1934,20 @@
 	Context m_context;
 	Ssl m_ssl{nullptr, nullptr};
 
-	/* Parameters */
-	Method m_method{Tlsv1};
+	/* Status */
+	bool m_tcpconnected{false};
+
+	/*
+	 * User definable parameters
+	 */
+	ssl::Method m_method{ssl::Tlsv1};
 	std::string m_key;
 	std::string m_certificate;
 	bool m_verify{false};
 
-	/* Status */
-	bool m_tcpconnected{false};
-
+	/*
+	 * Construct with a context and ssl, for accept().
+	 */
 	Tls(Context context, Ssl ssl)
 		: m_context{std::move(context)}
 		, m_ssl{std::move(ssl)}
@@ -2031,21 +2041,47 @@
 	}
 
 	/**
-	 * Construct a specific Tls object.
+	 * Set the method.
 	 *
-	 * @param method the method to use#
-	 
-	 * @param verify true to verify the certificate
-	 * @param key the private key
-	 * @param certificate the certificate file
+	 * @param method the method
+	 * @pre the socket must not be already created
+	 */
+	inline void setMethod(ssl::Method method) noexcept
+	{
+		assert(!m_context);
+		assert(!m_ssl);
+
+		m_method = method;
+	}
+
+	/**
+	 * Use the specified private key file.
+	 *
+	 * @param file the path to the private key
 	 */
-	Tls(Method method, bool verify = true, std::string key = "", std::string certificate = "")
-		: Tls()
+	inline void setPrivateKey(std::string file) noexcept
+	{
+		m_key = std::move(file);
+	}
+
+	/**
+	 * Use the specified certificate file.
+	 *
+	 * @param file the path to the file
+	 */
+	inline void setCertificate(std::string file) noexcept
 	{
-		m_method = method;
+		m_certificate = std::move(file);
+	}
+
+	/**
+	 * Set to true if we must verify the certificate and private key.
+	 *
+	 * @param verify the mode
+	 */
+	inline void setVerify(bool verify = true) noexcept
+	{
 		m_verify = verify;
-		m_key = std::move(key);
-		m_certificate = std::move(certificate);
 	}
 
 	/**
@@ -2056,7 +2092,7 @@
 	template <typename Address>
 	inline void create(Socket<Address, Tls> &sc)
 	{
-		auto method = (m_method == Tlsv1) ? TLSv1_method() : SSLv3_method();
+		auto method = (m_method == ssl::Tlsv1) ? TLSv1_method() : SSLv3_method();
 
 		m_context = {SSL_CTX_new(method), SSL_CTX_free};
 		m_ssl = {SSL_new(m_context.get()), SSL_free};
@@ -2080,6 +2116,7 @@
 	 *
 	 * @param sc the socket
 	 * @param address the address
+	 * @param length the address length
 	 * @throw Error on errors
 	 */
 	template <typename Address, typename Protocol>
@@ -2119,6 +2156,7 @@
 	 *
 	 * @param sc the socket
 	 * @param address the address destination
+	 * @param length the address length
 	 * @return the client
 	 */
 	template <typename Address>
@@ -2155,6 +2193,7 @@
 	/**
 	 * Receive some secure data.
 	 *
+	 * @param sc the socket
 	 * @param data the destination
 	 * @param len the buffer length
 	 * @return the number of bytes read
@@ -2181,6 +2220,7 @@
 	/**
 	 * Send some data.
 	 *
+	 * @param sc the socket
 	 * @param data the data to send
 	 * @param len the buffer length
 	 * @return the number of bytes sent
@@ -2851,6 +2891,9 @@
 template <typename Address, typename Protocol>
 class StreamConnection {
 public:
+	/**
+	 * Called when the output has changed.
+	 */
 	using WriteHandler = Callback<>;
 
 private:
@@ -2960,11 +3003,34 @@
 template <typename Address, typename Protocol>
 class StreamServer {
 public:
+	/**
+	 * Handler when a new client is connected.
+	 */
 	using ConnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
+
+	/**
+	 * Handler when a client is disconnected.
+	 */
 	using DisconnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
+
+	/**
+	 * Handler when data has been received from a client.
+	 */
 	using ReadHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
+
+	/**
+	 * Handler when data has been correctly sent to a client.
+	 */
 	using WriteHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
+
+	/**
+	 * Handler when an error occured.
+	 */
 	using ErrorHandler = Callback<const Error &>;
+
+	/**
+	 * Handler when there was a timeout.
+	 */
 	using TimeoutHandler = Callback<>;
 
 private:
@@ -3148,10 +3214,11 @@
 	 * Create a stream server with the specified address to bind.
 	 *
 	 * @param address the address to bind
+	 * @param protocol the protocol
 	 * @param max the max number to listen
 	 * @throw Error on errors
 	 */
-	StreamServer(const Address &address, Protocol type = {}, int max = 128)
+	StreamServer(const Address &address, Protocol protocol = {}, int max = 128)
 		: m_master{address, std::move(type)}
 	{
 		// TODO: m_onError
--- a/C++/tests/Socket/main.cpp	Wed Nov 04 20:36:07 2015 +0100
+++ b/C++/tests/Socket/main.cpp	Wed Nov 04 20:53:36 2015 +0100
@@ -576,7 +576,7 @@
 
 class TlsRecvTest : public testing::Test {
 protected:
-	SocketTls<Ipv4> m_server;
+	SocketTls<Ipv4> m_server{nullptr};
 	SocketTls<Ipv4> m_client;
 
 	std::thread m_tserver;
@@ -584,9 +584,14 @@
 
 public:
 	TlsRecvTest()
-		: m_server{Ipv4{}, Tls{Tls::Tlsv1, false, "Socket/test.key", "Socket/test.crt"}}
-		, m_client{Ipv4{}, Tls{Tls::Tlsv1, false}}
 	{
+		Tls protocol;
+
+		protocol.setCertificate("Socket/test.crt");
+		protocol.setPrivateKey("Socket/test.key");
+		protocol.setVerify(false);
+
+		m_server = SocketTls<Ipv4>{std::move(protocol)};
 		m_server.set(SOL_SOCKET, SO_REUSEADDR, 1);
 		m_server.bind(Ipv4{"*", 16000});
 		m_server.listen();