changeset 509:36e81ef34ed5

Sockets: update examples
author David Demelier <markand@malikania.fr>
date Tue, 23 Feb 2016 12:56:41 +0100
parents 8fc7fe1ec915
children f1749ac790d0
files modules/sockets/examples/ElapsedTimer.cpp modules/sockets/examples/ElapsedTimer.h modules/sockets/examples/blocking-accept.cpp modules/sockets/examples/blocking-connect.cpp modules/sockets/examples/elapsed-timer.cpp modules/sockets/examples/elapsed-timer.h modules/sockets/examples/non-blocking-accept.cpp modules/sockets/examples/non-blocking-connect.cpp modules/sockets/examples/stream-client.cpp modules/sockets/examples/stream-server.cpp modules/sockets/sockets.h
diffstat 11 files changed, 190 insertions(+), 299 deletions(-) [+]
line wrap: on
line diff
--- a/modules/sockets/examples/ElapsedTimer.cpp	Tue Feb 23 12:04:40 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * ElapsedTimer.cpp -- measure elapsed time
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "ElapsedTimer.h"
-
-using std::chrono::duration_cast;
-using std::chrono::high_resolution_clock;
-using std::chrono::milliseconds;
-
-ElapsedTimer::ElapsedTimer() noexcept
-{
-	m_last = high_resolution_clock::now();
-}
-
-void ElapsedTimer::pause() noexcept
-{
-	/*
-	 * When we put the timer on pause, do not forget to set the already
-	 * elapsed time.
-	 */
-	(void)elapsed();
-	m_paused = true;
-}
-
-void ElapsedTimer::restart() noexcept
-{
-	m_paused = false;
-	m_last = high_resolution_clock::now();
-}
-
-void ElapsedTimer::reset() noexcept
-{
-	m_elapsed = 0;
-	m_last = high_resolution_clock::now();
-}
-
-unsigned ElapsedTimer::elapsed() noexcept
-{
-	if (!m_paused) {
-		m_elapsed += duration_cast<milliseconds>(high_resolution_clock::now() - m_last).count();
-		m_last = high_resolution_clock::now();
-	}
-
-	return m_elapsed;
-}
\ No newline at end of file
--- a/modules/sockets/examples/ElapsedTimer.h	Tue Feb 23 12:04:40 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * ElapsedTimer.h -- measure elapsed time
- *
- * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _ELAPSED_TIMER_H_
-#define _ELAPSED_TIMER_H_
-
-/**
- * @file ElapsedTimer.h
- * @brief Measure elapsed time
- */
-
-#include <chrono>
-
-/**
- * @class ElapsedTimer
- * @brief Measure elapsed time
- *
- * This class provides an abstraction to measure elapsed time since the
- * construction of the object.
- *
- * It uses std::chrono::high_resolution_clock for more precision and uses
- * milliseconds only.
- */
-class ElapsedTimer {
-public:
-	using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
-
-private:
-	TimePoint m_last;
-	bool m_paused{false};
-	unsigned m_elapsed{0};
-
-public:
-	/**
-	 * Construct the elapsed timer, start counting.
-	 */
-	ElapsedTimer() noexcept;
-
-	/**
-	 * Put the timer on pause, the already elapsed time is stored.
-	 */
-	void pause() noexcept;
-
-	/**
-	 * Restart the timer, does not reset it.
-	 */
-	void restart() noexcept;
-
-	/**
-	 * Reset the timer to 0.
-	 */
-	void reset() noexcept;
-
-	/**
-	 * Get the number of elapsed milliseconds.
-	 *
-	 * @return the milliseconds
-	 */
-	unsigned elapsed() noexcept;
-};
-
-#endif // !_ELAPSED_TIMER_H_
--- a/modules/sockets/examples/blocking-accept.cpp	Tue Feb 23 12:04:40 2016 +0100
+++ b/modules/sockets/examples/blocking-accept.cpp	Tue Feb 23 12:56:41 2016 +0100
@@ -9,7 +9,7 @@
 
 #include <iostream>
 
-#include "Sockets.h"
+#include "sockets.h"
 
 #if !defined(WITH_PORT)
 #  define WITH_PORT 16000
@@ -39,7 +39,7 @@
 		listener.set(master.handle(), net::Condition::Readable);
 		listener.wait(std::chrono::seconds(WITH_TIMEOUT));
 
-		client = master.accept(nullptr);
+		master.accept(client);
 	} catch (const net::Error &error) {
 		std::cerr << "error: " << error.what() << std::endl;
 		std::exit(1);
--- a/modules/sockets/examples/blocking-connect.cpp	Tue Feb 23 12:04:40 2016 +0100
+++ b/modules/sockets/examples/blocking-connect.cpp	Tue Feb 23 12:56:41 2016 +0100
@@ -22,28 +22,26 @@
 #  define WITH_TIMEOUT 30
 #endif
 
-#include "ElapsedTimer.h"
-#include "Sockets.h"
+#include "elapsed-timer.h"
+#include "sockets.h"
 
 int main()
 {
 #if defined(WITH_SSL)
-	net::SocketTls<net::address::Ip> socket;
+	net::SocketTls<net::address::Ipv4> socket;
 #else
-	net::SocketTcp<net::address::Ip> socket;
+	net::SocketTcp<net::address::Ipv4> socket;
 #endif
 
 	try {
 		std::cout << "Trying to connect to " << WITH_HOST << ":" << WITH_PORT << std::endl;
-		socket.connect(net::address::Ip{WITH_HOST, WITH_PORT});
+		socket.connect(net::address::Ip(WITH_HOST, WITH_PORT));
 	} catch (const net::Error &error) {
 		std::cerr << "error: " << error.what() << std::endl;
 		std::exit(1);
 	}
 
-	if (socket.state() == net::State::Connected) {
-		std::cout << "Successfully connected!" << std::endl;
-	}
+	std::cout << "Successfully connected!" << std::endl;
 
 	return 0;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/sockets/examples/elapsed-timer.cpp	Tue Feb 23 12:56:41 2016 +0100
@@ -0,0 +1,60 @@
+/*
+ * elapsed-timer.cpp -- measure elapsed time
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "elapsed-timer.h"
+
+using std::chrono::duration_cast;
+using std::chrono::high_resolution_clock;
+using std::chrono::milliseconds;
+
+ElapsedTimer::ElapsedTimer() noexcept
+{
+	m_last = high_resolution_clock::now();
+}
+
+void ElapsedTimer::pause() noexcept
+{
+	/*
+	 * When we put the timer on pause, do not forget to set the already
+	 * elapsed time.
+	 */
+	(void)elapsed();
+	m_paused = true;
+}
+
+void ElapsedTimer::restart() noexcept
+{
+	m_paused = false;
+	m_last = high_resolution_clock::now();
+}
+
+void ElapsedTimer::reset() noexcept
+{
+	m_elapsed = 0;
+	m_last = high_resolution_clock::now();
+}
+
+unsigned ElapsedTimer::elapsed() noexcept
+{
+	if (!m_paused) {
+		m_elapsed += duration_cast<milliseconds>(high_resolution_clock::now() - m_last).count();
+		m_last = high_resolution_clock::now();
+	}
+
+	return m_elapsed;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/sockets/examples/elapsed-timer.h	Tue Feb 23 12:56:41 2016 +0100
@@ -0,0 +1,77 @@
+/*
+ * elapsed-timer.h -- measure elapsed time
+ *
+ * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ELAPSED_TIMER_H_
+#define _ELAPSED_TIMER_H_
+
+/**
+ * @file ElapsedTimer.h
+ * @brief Measure elapsed time
+ */
+
+#include <chrono>
+
+/**
+ * @class ElapsedTimer
+ * @brief Measure elapsed time
+ *
+ * This class provides an abstraction to measure elapsed time since the
+ * construction of the object.
+ *
+ * It uses std::chrono::high_resolution_clock for more precision and uses
+ * milliseconds only.
+ */
+class ElapsedTimer {
+public:
+	using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
+
+private:
+	TimePoint m_last;
+	bool m_paused{false};
+	unsigned m_elapsed{0};
+
+public:
+	/**
+	 * Construct the elapsed timer, start counting.
+	 */
+	ElapsedTimer() noexcept;
+
+	/**
+	 * Put the timer on pause, the already elapsed time is stored.
+	 */
+	void pause() noexcept;
+
+	/**
+	 * Restart the timer, does not reset it.
+	 */
+	void restart() noexcept;
+
+	/**
+	 * Reset the timer to 0.
+	 */
+	void reset() noexcept;
+
+	/**
+	 * Get the number of elapsed milliseconds.
+	 *
+	 * @return the milliseconds
+	 */
+	unsigned elapsed() noexcept;
+};
+
+#endif // !_ELAPSED_TIMER_H_
--- a/modules/sockets/examples/non-blocking-accept.cpp	Tue Feb 23 12:04:40 2016 +0100
+++ b/modules/sockets/examples/non-blocking-accept.cpp	Tue Feb 23 12:56:41 2016 +0100
@@ -3,21 +3,21 @@
  *
  * Options:
  *   - WITH_PORT (int), the port to use (default: 16000)
- *   - WITH_TIMEOUT (int), number of seconds before giving up (default: 60)
+ *   - WITH_TIMEOUT (int), number of milliseconds before giving up (default: 3000)
  *   - WITH_SSL (bool), true to test with SSL (default: false)
  */
 
 #include <iostream>
 
-#include "ElapsedTimer.h"
-#include "Sockets.h"
+#include "elapsed-timer.h"
+#include "sockets.h"
 
 #if !defined(WITH_PORT)
 #  define WITH_PORT 16000
 #endif
 
 #if !defined(WITH_TIMEOUT)
-#  define WITH_TIMEOUT 60
+#  define WITH_TIMEOUT 3000
 #endif
 
 int main()
@@ -31,6 +31,8 @@
 #endif
 
 	net::Listener<> listener;
+	net::Condition cond;
+
 	ElapsedTimer timer;
 
 	// 1. Create the master socket for listening.
@@ -39,26 +41,40 @@
 		master.set(net::option::SockBlockMode{false});
 		master.bind(net::address::Ip{"*", WITH_PORT});
 		master.listen();
+
+		listener.set(master.handle(), net::Condition::Readable);
 	} catch (const net::Error &error) {
 		std::cerr << "error: " << error.what() << std::endl;
 		std::exit(1);
 	}
 
-	while (client.state() != net::State::Accepted && timer.elapsed() < (WITH_TIMEOUT * 1000)) {
+	while (!client.isOpen() && timer.elapsed() < WITH_TIMEOUT) {
 		try {
-			if (client.state() == net::State::Closed) {
+			if (!client.isOpen()) {
 				// 2. Wait for a pre-accept process.
-				listener.set(master.handle(), net::Condition::Readable);
 				listener.wait(std::chrono::seconds(WITH_TIMEOUT));
-				client = master.accept(nullptr);
-				client.set(net::option::SockBlockMode{false});
+				master.accept(client, nullptr, &cond);
+				client.set(net::option::SockBlockMode(false));
 				listener.remove(master.handle());
+
+				std::cout << "Accepting new client" << std::endl;
+
+				if (cond != net::Condition::None) {
+					std::cout << "Client accept state not complete" << std::endl;
+					listener.set(client.handle(), cond);
+				}
 			} else {
 				// 3. Wait for the accept process to complete.
+				std::cout << "Continuing accept for the client" << std::endl;
+
+				listener.wait(std::chrono::seconds(WITH_TIMEOUT - timer.elapsed()));
+				client.accept(&cond);
 				listener.remove(client.handle());
-				listener.set(client.handle(), client.condition());
-				listener.wait(std::chrono::seconds(WITH_TIMEOUT));
-				client.accept();
+
+				if (cond != net::Condition::None) {
+					std::cout << "Client accept state not complete" << std::endl;
+					listener.set(client.handle(), cond);
+				}
 			}
 		} catch (const net::Error &error) {
 			std::cerr << error.function() << ": " << error.what() << std::endl;
@@ -66,7 +82,8 @@
 		}
 	}
 
-	std::cout << "Client successfully accepted!" << std::endl;
+	if (client.isOpen())
+		std::cout << "Client successfully accepted!" << std::endl;
 
-	return 0;	
+	return 0;
 }
--- a/modules/sockets/examples/non-blocking-connect.cpp	Tue Feb 23 12:04:40 2016 +0100
+++ b/modules/sockets/examples/non-blocking-connect.cpp	Tue Feb 23 12:56:41 2016 +0100
@@ -4,7 +4,7 @@
  * Options:
  *   - WITH_HOST (string literal), the host to try (default: "malikania.fr")
  *   - WITH_PORT (int), the port to use (default: 80)
- *   - WITH_TIMEOUT (int), number of seconds before giving up (default: 30)
+ *   - WITH_TIMEOUT (int), number of milliseconds before giving up (default: 3000)
  *   - WITH_SSL (bool), true to test with SSL (default: false)
  */
 
@@ -19,11 +19,11 @@
 #endif
 
 #if !defined(WITH_TIMEOUT)
-#  define WITH_TIMEOUT 30
+#  define WITH_TIMEOUT 3000
 #endif
 
-#include "ElapsedTimer.h"
-#include "Sockets.h"
+#include "elapsed-timer.h"
+#include "sockets.h"
 
 int main()
 {
@@ -34,33 +34,32 @@
 #endif
 
 	net::Listener<> listener;
+	net::Condition cond;
 	ElapsedTimer timer;
 
 	// 1. Set to non-blocking.
-	socket.set(net::option::SockBlockMode{false});
+	socket.set(net::option::SockBlockMode(false));
 
 	try {
 		std::cout << "Trying to connect to " << WITH_HOST << ":" << WITH_PORT << std::endl;
 
 		// 2. Initial connection process.
-		socket.connect(net::address::Ip{WITH_HOST, WITH_PORT});
+		socket.connect(net::address::Ip(WITH_HOST, WITH_PORT), &cond);
 
-		while (socket.state() != net::State::Connected) {
+		while (cond != net::Condition::None && timer.elapsed() < WITH_TIMEOUT) {
 			listener.remove(socket.handle());
 
 			// 2. Now complete by waiting for the appropriate condition.
-			listener.set(socket.handle(), socket.condition());
-			listener.wait(std::chrono::seconds(WITH_TIMEOUT));
-			socket.connect();
+			listener.set(socket.handle(), cond);
+			listener.wait(std::chrono::milliseconds(WITH_TIMEOUT - timer.elapsed()));
+			socket.connect(&cond);
 		}
 	} catch (const net::Error &error) {
 		std::cerr << "error: " << error.what() << std::endl;
 		std::exit(1);
 	}
 
-	if (socket.state() == net::State::Connected) {
-		std::cout << "Successfully connected!" << std::endl;
-	}
+	std::cout << "Successfully connected!" << std::endl;
 
 	return 0;
 }
--- a/modules/sockets/examples/stream-client.cpp	Tue Feb 23 12:04:40 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * stream-server -- example of stream server
- *
- * Options:
- *   - WITH_PORT (int) which port to use (default: 12000)
- *   - WITH_HOST (string literal) which host to connect (default: "localhost")
- *   - WITH_SSL (bool) true to use SSL (default: false)
- */
-
-#include <iostream>
-
-#include "Sockets.h"
-
-#if !defined(WITH_PORT)
-#  define WITH_PORT 12000
-#endif
-
-#if !defined(WITH_HOST)
-#  define WITH_HOST "localhost"
-#endif
-
-#if defined(WITH_SSL)
-using Client = net::StreamClient<net::address::Ip, net::protocol::Tls>;
-#else
-using Client = net::StreamClient<net::address::Ip, net::protocol::Tcp>;
-#endif
-
-int main()
-{
-	Client client;
-
-	/*
-	 * Unfortunately at the moment the socket state is not changed, this will be done
-	 * in the future.
-	 */
-	bool connected{true};
-
-	client.setConnectionHandler([&] () {
-		std::cout << "client: successfully connected" << std::endl;
-		client.send("Hello world!");
-	});
-	client.setDisconnectionHandler([&] () {
-		std::cout << "client: disconnected" << std::endl;
-		connected = false;
-	});
-	client.setErrorHandler([&] (const net::Error &error) {
-		std::cout << "client: error: " << error.function() << ": " << error.what() << std::endl;
-		connected = false;
-	});
-	client.setReadHandler([] (const std::string &data) {
-		std::cout << "client: received: " << data << std::endl;
-	});
-	client.setWriteHandler([] (const std::string &data) {
-		std::cout << "client: sent: " << data << std::endl;
-	});
-
-	client.connect(net::address::Ip{WITH_HOST, WITH_PORT});
-
-	while (connected) {
-		client.poll();
-	}
-
-	std::cout << "client: exiting" << std::endl;
-
-	return 0;
-}
--- a/modules/sockets/examples/stream-server.cpp	Tue Feb 23 12:04:40 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * stream-server -- example of stream server
- *
- * Options:
- *   - WITH_PORT (int) which port to use (default: 12000)
- *   - WITH_SSL (bool) true to use SSL (default: false)
- */
-
-#include <iostream>
-
-#include "Sockets.h"
-
-#if !defined(WITH_PORT)
-#  define WITH_PORT 12000
-#endif
-
-#if defined(WITH_SSL)
-using Server = net::StreamServer<net::address::Ip, net::protocol::Tls>;
-using Connection = net::StreamConnection<net::address::Ip, net::protocol::Tls>;
-#else
-using Server = net::StreamServer<net::address::Ip, net::protocol::Tcp>;
-using Connection = net::StreamConnection<net::address::Ip, net::protocol::Tcp>;
-#endif
-
-int main()
-{
-#if defined(WITH_SSL)
-	net::protocol::Tls protocol;
-
-	protocol.setVerify(false);
-	protocol.setPrivateKey("test.key");
-	protocol.setCertificate("test.crt");
-	protocol.setMethod(net::ssl::Tlsv1);
-
-	Server server{std::move(protocol), net::address::Ip{"*", WITH_PORT}};
-#else
-	Server server{net::protocol::Tcp{}, net::address::Ip{"*", WITH_PORT}};
-#endif
-
-	server.setConnectionHandler([] (const std::shared_ptr<Connection> &client) {
-		std::cout << "server: new client connected" << std::endl;
-		client->send("Welcome to our server dude");
-	});
-	server.setReadHandler([] (const std::shared_ptr<Connection> &, const std::string &buffer) {
-		std::cout << "server: received: " << buffer << std::endl;
-	});
-	server.setWriteHandler([] (const std::shared_ptr<Connection> &, const std::string &buffer) {
-		std::cout << "server: sent: " << buffer << std::endl;
-	});
-	server.setDisconnectionHandler([] (const std::shared_ptr<Connection> &) {
-		std::cout << "server: client disconnected" << std::endl;
-	});
-
-	while (true) {
-		server.poll(-1);
-	}
-
-	return 0;
-}
--- a/modules/sockets/sockets.h	Tue Feb 23 12:04:40 2016 +0100
+++ b/modules/sockets/sockets.h	Tue Feb 23 12:56:41 2016 +0100
@@ -1629,6 +1629,8 @@
 	}
 };
 
+using Ip = Ipv4;
+
 #if !defined(_WIN32)
 
 /**