# HG changeset patch # User David Demelier # Date 1450082488 -3600 # Node ID 8b161d143975dfa35f4f7bc8e96987a52e27b045 # Parent 3c783cf492abef9bf93c4a75e1adb67890bbc66e Socket: put back examples that were removed by mistake diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/ElapsedTimer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/ElapsedTimer.cpp Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,60 @@ +/* + * ElapsedTimer.cpp -- measure elapsed time + * + * Copyright (c) 2013-2015 David Demelier + * + * 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(high_resolution_clock::now() - m_last).count(); + m_last = high_resolution_clock::now(); + } + + return m_elapsed; +} \ No newline at end of file diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/ElapsedTimer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/ElapsedTimer.h Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,77 @@ +/* + * ElapsedTimer.h -- measure elapsed time + * + * Copyright (c) 2013-2015 David Demelier + * + * 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 + +/** + * @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; + +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_ diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/blocking-accept.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/blocking-accept.cpp Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,52 @@ +/* + * blocking-accept.cpp -- example of blocking accept + * + * Options: + * - WITH_PORT (int), the port to use (default: 16000) + * - WITH_TIMEOUT (int), number of seconds before giving up (default: 60) + * - WITH_SSL (bool), true to test with SSL (default: false) + */ + +#include + +#include "Sockets.h" + +#if !defined(WITH_PORT) +# define WITH_PORT 16000 +#endif + +#if !defined(WITH_TIMEOUT) +# define WITH_TIMEOUT 60 +#endif + +int main() +{ +#if defined(WITH_SSL) + net::SocketTls master; + net::SocketTls client{net::Invalid}; +#else + net::SocketTcp master; + net::SocketTcp client{net::Invalid}; +#endif + + net::Listener<> listener; + + try { + master.set(net::option::SockReuseAddress{true}); + master.bind(net::address::Ip{"*", WITH_PORT}); + master.listen(); + + listener.set(master.handle(), net::Condition::Readable); + listener.wait(std::chrono::seconds(WITH_TIMEOUT)); + + client = master.accept(nullptr); + } catch (const net::Error &error) { + std::cerr << "error: " << error.what() << std::endl; + std::exit(1); + } + + std::cout << "Client successfully accepted!" << std::endl; + + return 0; +} + diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/blocking-connect.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/blocking-connect.cpp Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,50 @@ +/* + * blocking-connect.cpp -- example of blocking connect + * + * 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_SSL (bool), true to test with SSL (default: false) + */ + +#include + +#if !defined(WITH_HOST) +# define WITH_HOST "malikania.fr" +#endif + +#if !defined(WITH_PORT) +# define WITH_PORT 80 +#endif + +#if !defined(WITH_TIMEOUT) +# define WITH_TIMEOUT 30 +#endif + +#include "ElapsedTimer.h" +#include "Sockets.h" + +int main() +{ +#if defined(WITH_SSL) + net::SocketTls socket; +#else + net::SocketTcp socket; +#endif + + try { + std::cout << "Trying to connect to " << WITH_HOST << ":" << WITH_PORT << std::endl; + 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; + } + + return 0; +} + diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/non-blocking-accept.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/non-blocking-accept.cpp Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,72 @@ +/* + * non-blocking-accept.cpp -- example of total non-blocking accept + * + * Options: + * - WITH_PORT (int), the port to use (default: 16000) + * - WITH_TIMEOUT (int), number of seconds before giving up (default: 60) + * - WITH_SSL (bool), true to test with SSL (default: false) + */ + +#include + +#include "ElapsedTimer.h" +#include "Sockets.h" + +#if !defined(WITH_PORT) +# define WITH_PORT 16000 +#endif + +#if !defined(WITH_TIMEOUT) +# define WITH_TIMEOUT 60 +#endif + +int main() +{ +#if defined(WITH_SSL) + net::SocketTls master; + net::SocketTls client{net::Invalid}; +#else + net::SocketTcp master; + net::SocketTcp client{net::Invalid}; +#endif + + net::Listener<> listener; + ElapsedTimer timer; + + // 1. Create the master socket for listening. + try { + master.set(net::option::SockReuseAddress{true}); + master.set(net::option::SockBlockMode{false}); + master.bind(net::address::Ip{"*", WITH_PORT}); + master.listen(); + } 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)) { + try { + if (client.state() == net::State::Closed) { + // 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}); + listener.remove(master.handle()); + } else { + // 3. Wait for the accept process to complete. + listener.remove(client.handle()); + listener.set(client.handle(), client.condition()); + listener.wait(std::chrono::seconds(WITH_TIMEOUT)); + client.accept(); + } + } catch (const net::Error &error) { + std::cerr << error.function() << ": " << error.what() << std::endl; + std::exit(1); + } + } + + std::cout << "Client successfully accepted!" << std::endl; + + return 0; +} diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/non-blocking-connect.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/non-blocking-connect.cpp Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,66 @@ +/* + * non-blocking-connect.cpp -- example of non blocking connect + * + * 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_SSL (bool), true to test with SSL (default: false) + */ + +#include + +#if !defined(WITH_HOST) +# define WITH_HOST "malikania.fr" +#endif + +#if !defined(WITH_PORT) +# define WITH_PORT 80 +#endif + +#if !defined(WITH_TIMEOUT) +# define WITH_TIMEOUT 30 +#endif + +#include "ElapsedTimer.h" +#include "Sockets.h" + +int main() +{ +#if defined(WITH_SSL) + net::SocketTls socket; +#else + net::SocketTcp socket; +#endif + + net::Listener<> listener; + ElapsedTimer timer; + + // 1. Set to non-blocking. + 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}); + + while (socket.state() != net::State::Connected) { + 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(); + } + } 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; + } + + return 0; +} diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/stream-client.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/stream-client.cpp Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,66 @@ +/* + * 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 + +#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; +#else +using Client = net::StreamClient; +#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; +} diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/stream-server.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/stream-server.cpp Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,59 @@ +/* + * 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 + +#include "Sockets.h" + +#if !defined(WITH_PORT) +# define WITH_PORT 12000 +#endif + +#if defined(WITH_SSL) +using Server = net::StreamServer; +using Connection = net::StreamConnection; +#else +using Server = net::StreamServer; +using Connection = net::StreamConnection; +#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 &client) { + std::cout << "server: new client connected" << std::endl; + client->send("Welcome to our server dude"); + }); + server.setReadHandler([] (const std::shared_ptr &, const std::string &buffer) { + std::cout << "server: received: " << buffer << std::endl; + }); + server.setWriteHandler([] (const std::shared_ptr &, const std::string &buffer) { + std::cout << "server: sent: " << buffer << std::endl; + }); + server.setDisconnectionHandler([] (const std::shared_ptr &) { + std::cout << "server: client disconnected" << std::endl; + }); + + while (true) { + server.poll(-1); + } + + return 0; +} diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/test.crt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/test.crt Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICITCCAYoCCQCGm4grkVCohjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJG +UjEPMA0GA1UECAwGRnJhbmNlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0 +eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNTEwMjYyMDM0NThaFw0yNTEw +MjMyMDM0NThaMFUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxITAfBgNV +BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0 +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDp13OqVyOWyv5QWD4xr+Duw6SZ +gU7D5huzsAOcneSI6JUhf+7Ecu6BQ2JGkFn4srIVkMWGQuImETJ8JCpSQH7rk+xO +L9fTTK+TwhP2hW/Rf/b2gWedhJAS+gilqt4JNT7v2wFv+aTtRt/lpTXVSdtpLa/m +Pdy219f6MAPgODJ/7QIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAJSnn/IBn1ZblfzP +rJO/lE1Jwpmx3B7+oR/e4fkZd6JR3s06umGYWr2H+TPl/5dj9x0gPokhoIL9zCGq +SxCPnOeaxjBkw7yh3Ks6m3xKxmK4aMpAtBHtwmbfQyIcgz71/lfCzbJ3WcKpn1ig +IZbByt5QSSPcFORRzJJa35eHBdfX +-----END CERTIFICATE----- diff -r 3c783cf492ab -r 8b161d143975 modules/sockets/examples/test.key --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/test.key Mon Dec 14 09:41:28 2015 +0100 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDp13OqVyOWyv5QWD4xr+Duw6SZgU7D5huzsAOcneSI6JUhf+7E +cu6BQ2JGkFn4srIVkMWGQuImETJ8JCpSQH7rk+xOL9fTTK+TwhP2hW/Rf/b2gWed +hJAS+gilqt4JNT7v2wFv+aTtRt/lpTXVSdtpLa/mPdy219f6MAPgODJ/7QIDAQAB +AoGBANDt4ndQkgi56A1rOm50gVlzTg6lPPXFE/0xB5kYbcdxX0VmI7Q8KCMwTI9V +jD2rk3e3OPSjr6FpfhzyxylkXMBz2BL5NRNPowCJbiMgZOUIzlcWPKo0tgf1bZJx +YdB5U003ISGPPBjVOAjyizY7tJnaNvbpLQ0hbIAsvHPEAOnBAkEA9r3g8NQjPrvb +oIr5SMIxM8HDJ1/q+MEBSFtRFzQpmur6P64Jsu96zCyencUYTxs0L/sottrj6dPC +vjGCc6PjsQJBAPKdqK1knJv6Y95M2bnEwrymCFVdxCi7AxObStB+bg/+7mMCUqqX +j2g71bfvhYakHV7CiaYrrORChwj6vTbimv0CQGpd2IZ5LOhyW2+N+YDgFg3Vzac/ +ti+eJEto8kAqgHUELvUctZmpmypBYe9pc91GQO0ePKL3IaE/ZIhRF4d6c0ECQH9A +XiaD7PiKvjLs0A31u8ZCt4A+7BII9LYl73mntobBSbu4ji9Xyyn6qEAPa1ORZK49 +DwGPSuF2W2lESlYtSOkCQGrtczhx3IyJjk5e2Y1i/UddPKjviAysCSzcW6aVTNr9 +Y2L0sWmva2FKnkl9FDuEqxvmGr6OOkr5Ll7aWLzJri8= +-----END RSA PRIVATE KEY-----