Mercurial > code
changeset 565:a1841ba6eb61
Net: various documentation fixes
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 23 Jun 2016 13:50:27 +0200 |
parents | 21fa534ce42f |
children | 72390061044d |
files | modules/net/net.hpp modules/net/test/main.cpp |
diffstat | 2 files changed, 289 insertions(+), 381 deletions(-) [+] |
line wrap: on
line diff
--- a/modules/net/net.hpp Thu Jun 23 07:37:02 2016 +0200 +++ b/modules/net/net.hpp Thu Jun 23 13:50:27 2016 +0200 @@ -1,5 +1,5 @@ /* - * net.hpp -- portable C++ socket wrappers + * net.hpp -- portable C++ socket wrapper * * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr> * @@ -66,7 +66,6 @@ * - \subpage net-configuration * - \subpage net-options * - \subpage net-concepts - * - \subpage net-examples */ /** @@ -151,7 +150,7 @@ * ## Synopsis * * ```` - * Address(); // (0); + * Address(); // (0) * Address(const sockaddr *sa, socklen_t length); // (1) * ```` * @@ -354,95 +353,48 @@ * * The type of socket. * - * # create - * - * Function called immediately after creation of socket. Interface must provides this function even if the - * interface does not require anything. - * - * ## Synopsis - * - * ```` - * template <typename Address> - * void create(Socket<Address, Tcp> &) const noexcept; - * ```` - * * # connect * - * Initial connect function. - * - * In this function, the interface receive the socket, address and a condition (initially set to None). If the - * underlying socket is marked non-blocking and the operation would block, the interface must set the condition - * to the required one. + * Connect to the given address. * * ## Synopsis * * ```` - * template <typename Address> - * void connect(Socket<Address> &sc, const sockaddr *address, socklen_t length, Condition &cond); + * void connect(const sockaddr *address, socklen_t length); // (0) + * void connect(const Address &address); // 1 (Optional) * ```` * * ## Arguments * - * - **sc**: the socket, * - **address**: the address, - * - **length**: the address length, - * - **cond**: the condition to update. - * - * # resumeConnect - * - * Continue the connection. + * - **length**: the address length. * - * ## Synopsis + * ## Throws * - * ```` - * template <typename Address> - * void resumeConnect(Socket<Address> &sc, Condition &cond) - * ```` - * - * ## Arguments - * - * - **sc**: the socket, - * - **cond**: the condition to update. + * - **WouldBlockError**: if the operation would block, + * - **Error**: on other error. * * # accept * * Accept a new client. * - * If the interface has no pending connection, an invalid socket SHOULD be returned, otherwise return the client and - * set the condition if the accept process is not complete yet. - * - * The interface MUST stores the client information into address and length parameters, they are guaranted to never be - * null. + * If no pending connection is available and operation would block, the implementation must throw WouldBlockError. Any other error + * can be thrown otherwise a valid socket must be returned. * * ## Synopsis * * ```` - * template <typename Address> - * Socket<Address> accept(Socket<Address> &sc, sockaddr *address, socklen_t *length, Condition &cond); + * Socket<Address> accept(); * ```` * - * ## Arguments + * ## Returns * - * - **sc**: the socket, - * - **address**: the information address, - * - **length**: the address initial length (sockaddr_storage), - * - **cond**: the condition to update. - * - * # resumeAccept - * - * Continue the accept process on the returned client. + * The new socket. * - * ## Synopsis + * ## Throws * - * ```` - * template <typename Address> - * void accept(Socket<Address> &sc, Condition &cond) const noexcept; - * ```` - * - * ## Arguments - * - * - **sc**: the socket, - * - **cond**: the condition to update. + * - **WouldBlockError**: if the operation would block, + * - **Error**: on other error. * * # recv * @@ -451,16 +403,13 @@ * ## Synopsis * * ```` - * template <typename Address> - * std::size_t recv(Socket<Address, Tcp> &sc, void *data, std::size_t length, Condition &cond); + * unsigned recv(void *data, unsigned length); * ```` * * ## Arguments * - * - **sc**: the socket, * - **data**: the destination buffer, - * - **length**: the destination buffer length, - * - **cond**: the condition to update. + * - **length**: the destination buffer length. * * ## Returns * @@ -473,16 +422,13 @@ * ## Synopsis * * ```` - * template <typename Address> - * std::size_t send(Socket<Address, Tcp> &sc, const void *data, std::size_t length, Condition &cond); + * unsigned send(const void *data, unsigned length); * ```` * * ## Arguments * - * - **sc**: the socket, * - **data**: the data to send, - * - **length**: the data length, - * - **cond**: the condition to update. + * - **length**: the data length. * * ## Returns * @@ -515,18 +461,16 @@ * ## Synopsis * * ```` - * template <typename Address> - * std::size_t recvfrom(Socket<Address> &sc, void *data, std::size_t length, sockaddr *address, socklen_t *addrlen, Condition &cond); + * unsigned recvfrom(void *data, unsigned length, sockaddr *address, socklen_t *addrlen); // (0) + * unsigned recvfrom(void *data, unsigned length, Address *source) // (1) (Optional) * ```` * * ## Arguments * - * - **sc**: the socket, * - **data**: the data, * - **length**: the length, * - **address**: the source address, - * - **addrlen**: the source address in/out length, - * - **cond**: the condition. + * - **addrlen**: the source address in/out length. * * ## Returns * @@ -535,108 +479,22 @@ * # sendto * * ```` - * template <typename Address> - * std::size_t sendto(Socket<Address> &sc, const void *data, std::size_t length, const sockaddr *address, socklen_t addrlen, Condition &cond); + * unsigned sendto(const void *data, unsigned length, const sockaddr *address, socklen_t addrlen); // (0) + * unsigned sendto(const void *data, unsigned length, const Address &address); // (1) (Optional) * ```` * * ## Arguments * - * - **sc**: the socket, * - **data**: the data to send, * - **length**: the data length, * - **address**: the destination address, - * - **addrlen**: the destination address length, - * - **cond**: the condition. + * - **addrlen**: the destination address length. * * ## Returns * * The number of bytes sent. */ -/** - * \page net-examples Examples - * - * # Non blocking examples - * - * Non-blocking sockets can be tedious, here various examples on how to do it with this module. - * - * - \subpage net-example-non-blocking-connect - */ - -/** - * \page net-example-non-blocking-connect Non-blocking connect - * - * This example shows how to make a non-blocking connect. - * - * Because SSL support is first class value, the connection functions are a bit more tricky but don't be afraid it is completely - * transparent for the user. - * - * ## Background - * - * First, let's explain what usually happen in traditional fashion. - * - * When you use the connect(2) function in a non-blocking socket, EINPROGRESS is returned if the connection could not be immediately - * established, the user must then wait until the socket is writable and check for SOL_SOCKET/SO_ERROR option. For OpenSSL, user must wait - * for readable/writable depending on the current operation, remember that OpenSSL requires several roundtrips to finalize handshake. - * - * Because these operations are different on TCP and SSL sockets, the Socket class has a unique resumeConnect function which have a - * different implementation depending if the socket is SSL or raw TCP. Also because resumeConnect() must be called only when the socket is - * either readable or writable, a condition is given to the user in several function including Socket::connect(). - * - * ## Code - * - * In this code, we will try to connect to example.org on port 9090 using TCP/IPv4. - * - * ````cpp - * #include <iostream> - * - * #include "net.hpp" - * - * void connect(SocketTcpIpv4 &sc) - * { - * // (0) The listener, used to wait for a condition. - * Listener<> listener; - * - * // (1) The condition that we must wait for, no need to initialize. - * Condition cond; - * - * // (2) Do the initial connection attempt - * // - * // If cond != Condition::None, the connection was unable to complete immediately. - * sc.connect(address::Ipv4::resolve("example.org", "9090"), cond); - * - * while (cond != Condition::None) { - * // (3) Erase the previous condition. - * listener.remove(sc.handle()); - * - * // (4) Add the requested condition. - * listener.set(sc.handle(), cond); - * - * // (5) Wait and try to resume the condition, don't forget to give cond again. - * listener.wait(); - * sc.resumeConnect(cond); - * } - * } - * - * int main() - * { - * try { - * SocketTcpIpv4 sc; - * - * // Set the socket non-blocking. - * sc.set(option::SockBlockMode(false)); - * - * connect(sc); - * } catch (const std::exception &ex) { - * std::cerr << ex.what() << std::endl; - * return 1; - * } - * - * return 0; - * } - * ```` - */ - /* * Headers to include. * ------------------------------------------------------------------ @@ -644,22 +502,22 @@ // Include Windows headers before because it brings _WIN32_WINNT if not specified by the user. #if defined(_WIN32) -# include <WinSock2.h> -# include <WS2tcpip.h> +# include <WinSock2.h> +# include <WS2tcpip.h> #else -# include <sys/ioctl.h> -# include <sys/types.h> -# include <sys/socket.h> -# include <sys/un.h> - -# include <arpa/inet.h> - -# include <netinet/in.h> -# include <netinet/tcp.h> - -# include <fcntl.h> -# include <netdb.h> -# include <unistd.h> +# include <sys/ioctl.h> +# include <sys/types.h> +# include <sys/socket.h> +# include <sys/un.h> + +# include <arpa/inet.h> + +# include <netinet/in.h> +# include <netinet/tcp.h> + +# include <fcntl.h> +# include <netdb.h> +# include <unistd.h> #endif #include <algorithm> @@ -698,23 +556,23 @@ */ #if defined(_WIN32) -# if _WIN32_WINNT >= 0x0600 && !defined(NET_HAVE_POLL) -# define NET_HAVE_POLL -# endif +# if _WIN32_WINNT >= 0x0600 && !defined(NET_HAVE_POLL) +# define NET_HAVE_POLL +# endif #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) -# if !defined(NET_HAVE_KQUEUE) -# define NET_HAVE_KQUEUE -# endif -# if !defined(NET_HAVE_POLL) -# define NET_HAVE_POLL -# endif +# if !defined(NET_HAVE_KQUEUE) +# define NET_HAVE_KQUEUE +# endif +# if !defined(NET_HAVE_POLL) +# define NET_HAVE_POLL +# endif #elif defined(__linux__) -# if !defined(NET_HAVE_EPOLL) -# define NET_HAVE_EPOLL -# endif -# if !defined(NET_HAVE_POLL) -# define NET_HAVE_POLL -# endif +# if !defined(NET_HAVE_EPOLL) +# define NET_HAVE_EPOLL +# endif +# if !defined(NET_HAVE_POLL) +# define NET_HAVE_POLL +# endif #endif /* @@ -726,26 +584,26 @@ * \brief Tells if inet_pton is available */ #if !defined(NET_HAVE_INET_PTON) -# if defined(_WIN32) -# if _WIN32_WINNT >= 0x0600 -# define NET_HAVE_INET_PTON -# endif -# else -# define NET_HAVE_INET_PTON -# endif +# if defined(_WIN32) +# if _WIN32_WINNT >= 0x0600 +# define NET_HAVE_INET_PTON +# endif +# else +# define NET_HAVE_INET_PTON +# endif #endif /** * \brief Tells if inet_ntop is available */ #if !defined(NET_HAVE_INET_NTOP) -# if defined(_WIN32) -# if _WIN32_WINNT >= 0x0600 -# define NET_HAVE_INET_NTOP -# endif -# else -# define NET_HAVE_INET_NTOP -# endif +# if defined(_WIN32) +# if _WIN32_WINNT >= 0x0600 +# define NET_HAVE_INET_NTOP +# endif +# else +# define NET_HAVE_INET_NTOP +# endif #endif /* @@ -759,35 +617,35 @@ * \brief Defines the default backend */ #if defined(_WIN32) -# if !defined(NET_DEFAULT_BACKEND) -# if defined(NET_HAVE_POLL) -# define NET_DEFAULT_BACKEND Poll -# else -# define NET_DEFAULT_BACKEND Select -# endif -# endif +# if !defined(NET_DEFAULT_BACKEND) +# if defined(NET_HAVE_POLL) +# define NET_DEFAULT_BACKEND Poll +# else +# define NET_DEFAULT_BACKEND Select +# endif +# endif #elif defined(__linux__) -# include <sys/epoll.h> - -# if !defined(NET_DEFAULT_BACKEND) -# define NET_DEFAULT_BACKEND Epoll -# endif +# include <sys/epoll.h> + +# if !defined(NET_DEFAULT_BACKEND) +# define NET_DEFAULT_BACKEND Epoll +# endif #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) -# include <sys/types.h> -# include <sys/event.h> -# include <sys/time.h> - -# if !defined(NET_DEFAULT_BACKEND) -# define NET_DEFAULT_BACKEND Kqueue -# endif +# include <sys/types.h> +# include <sys/event.h> +# include <sys/time.h> + +# if !defined(NET_DEFAULT_BACKEND) +# define NET_DEFAULT_BACKEND Kqueue +# endif #else -# if !defined(NET_DEFAULT_BACKEND) -# define NET_DEFAULT_BACKEND Select -# endif +# if !defined(NET_DEFAULT_BACKEND) +# define NET_DEFAULT_BACKEND Select +# endif #endif #if defined(NET_HAVE_POLL) && !defined(_WIN32) -# include <poll.h> +# include <poll.h> #endif /** @@ -1063,32 +921,64 @@ } }; +/** + * \brief Timeout occured. + */ class TimeoutError : public std::exception { public: + /** + * Get the error message. + * + * \return the message + */ const char *what() const noexcept override { return std::strerror(ETIMEDOUT); } }; +/** + * \brief Operation would block. + */ class WouldBlockError : public std::exception { public: + /** + * Get the error message. + * + * \return the message + */ const char *what() const noexcept override { return std::strerror(EWOULDBLOCK); } }; +/** + * \brief Operation requires sending data to complete. + */ class WantWriteError : public std::exception { public: + /** + * Get the error message. + * + * \return the message + */ const char *what() const noexcept override { return "operation requires writing to complete"; } }; +/** + * \brief Operation requires reading data to complete. + */ class WantReadError : public std::exception { public: + /** + * Get the error message. + * + * \return the message + */ const char *what() const noexcept override { return "operation requires read to complete"; @@ -1105,9 +995,6 @@ /** * \enum Condition * \brief Define the required condition for the socket. - * - * As explained in Action enumeration, some operations required to be called several times, before calling these - * operations, the user must wait the socket to be readable or writable. This can be checked with Socket::condition. */ enum class Condition { None, //!< No condition is required @@ -1213,24 +1100,7 @@ */ /** - * \brief Base socket class for socket operations. - * - * **Important:** When using non-blocking sockets, some considerations must be taken. See the implementation of the - * underlying protocol for more details. - * - * When using non-blocking sockets, it is important to pass the condition to functions which may block, they indicate - * the condition to wait to perform or continue the operation if they would block. - * - * For example, when trying to connect with non-blocking, user should do the following: - * - * 1. Call Socket::connect() with the condition, - * 2. Loop until condition is not set to Condition::None (or an exception is thrown), - * 3. Wait with a listener for the condition to be ready (see Listener::wait), - * 4. Call Socket::resumeConnect() with the condition again. - * - * \see protocol::Tls - * \see protocol::Tcp - * \see protocol::Udp + * \brief Base socket class. */ template <typename Address> class Socket { @@ -1267,7 +1137,6 @@ * Create the socket with an already defined handle and its protocol. * * \param handle the handle - * \param protocol the protocol */ explicit inline Socket(Handle handle) noexcept : m_handle(handle) @@ -1618,14 +1487,32 @@ template <typename Address> class TcpSocket : public Socket<Address> { public: + /** + * Inherited constructors. + */ using Socket<Address>::Socket; - TcpSocket() + /** + * Create a TCP socket using the address domain. + * + * \throw Error on errors + */ + inline TcpSocket() : Socket<Address>(Address().domain(), SOCK_STREAM, 0) { } /** + * Get the type of the socket. + * + * \return the type + */ + inline int type() const noexcept + { + return SOCK_STREAM; + } + + /** * Initiate connection. * * \param address the address @@ -1669,7 +1556,6 @@ * * If there are no pending connection, an invalid socket is returned. * - * \param sc the socket * \return the new socket * \throw WouldBlockError if the socket is marked non-blocking and no connection are available * \throw Error on other errors @@ -1766,9 +1652,34 @@ * This class is the basic implementation of UDP sockets. */ template <typename Address> -class UdpSocket { +class UdpSocket : public Socket<Address> { public: /** + * Inherited constructors. + */ + using Socket<Address>::Socket; + + /** + * Create a UDP socket using the address domain. + * + * \throw Error on errors + */ + inline UdpSocket() + : Socket<Address>(Address().domain(), SOCK_DGRAM, 0) + { + } + + /** + * Get the type of the socket. + * + * \return the type + */ + inline int type() const noexcept + { + return SOCK_DGRAM; + } + + /** * Receive some data. * * \param data the data @@ -1776,6 +1687,8 @@ * \param address the source address * \param addrlen the source address in/out length * \return the number of bytes received + * \throw WouldBlockError if the socket is marked non-blocking and the operation would block + * \throw Error on other errors */ unsigned recvfrom(void *data, unsigned length, sockaddr *address, socklen_t *addrlen) { @@ -1802,6 +1715,28 @@ } /** + * Overloaded function. + * + * \param data the data + * \param length the length + * \param source the source information (optional) + * \throw WouldBlockError if the socket is marked non-blocking and the operation would block + * \throw Error on other errors + */ + inline unsigned recvfrom(void *data, unsigned length, Address *source = nullptr) + { + sockaddr_storage st; + socklen_t socklen = sizeof (sockaddr_storage); + + auto nr = recvfrom(data, length, reinterpret_cast<sockaddr *>(&st), &socklen); + + if (source) + *source = Address(reinterpret_cast<const sockaddr *>(&st), socklen); + + return nr; + } + + /** * Send some data. * * \param data the data to send @@ -1809,6 +1744,8 @@ * \param address the destination address * \param addrlen the destination address length * \return the number of bytes sent + * \throw WouldBlockError if the socket is marked non-blocking and the operation would block + * \throw Error on other errors */ unsigned sendto(const void *data, unsigned length, const sockaddr *address, socklen_t addrlen) { @@ -1833,6 +1770,21 @@ return static_cast<unsigned>(nbsent); } + + /** + * Overloaded function + * + * \param data the data to send + * \param length the data length + * \param address the destination address + * \return the number of bytes sent + * \throw WouldBlockError if the socket is marked non-blocking and the operation would block + * \throw Error on other errors + */ + inline unsigned sendto(const void *data, unsigned length, const Address &address) + { + return sendto(data, length, address.address(), address.length()); + } }; #if !defined(NET_NO_SSL) @@ -1900,6 +1852,7 @@ * * \param sock the TCP socket * \param mode the mode + * \param method the method */ inline TlsSocket(TcpSocket<Address> &sock, Mode mode = Server, const SSL_METHOD *method = TLSv1_method()) : Socket<Address>(sock.handle()) @@ -1919,9 +1872,20 @@ } /** + * Get the type of socket. + * + * \return the type + */ + inline int type() const noexcept + { + return SOCK_STREAM; + } + + /** * Use the specified private key file. * * \param file the path to the private key + * \param type the type of file */ inline void setPrivateKey(std::string file, int type = SSL_FILETYPE_PEM) { @@ -1933,6 +1897,7 @@ * Use the specified certificate file. * * \param file the path to the file + * \param type the type of file */ inline void setCertificate(std::string file, int type = SSL_FILETYPE_PEM) { @@ -1942,10 +1907,6 @@ /** * Do handshake, needed in some case when you have non blocking sockets. - * - * \param address the address - * \param length the address length - * \param cond the condition */ void handshake() { @@ -1978,7 +1939,6 @@ * * \param data the data to send * \param length the length - * \param cond the condition * \return the number of bytes sent */ unsigned send(const void *data, unsigned length) @@ -2295,7 +2255,7 @@ #if !defined(NET_HAVE_INET_NTOP) (void)sin; - throw Error(ENOSYS, std::strerror(ENOSYS)); + throw Error(std::strerror(ENOSYS)); #else char result[INET_ADDRSTRLEN + 1]; @@ -2324,7 +2284,7 @@ #if !defined(NET_HAVE_INET_NTOP) (void)sin6; - throw Error(ENOSYS, std::strerror(ENOSYS)); + throw Error(std::strerror(ENOSYS)); #else char result[INET6_ADDRSTRLEN]; @@ -4114,8 +4074,6 @@ return address::Iterator(addresses, 0); } -#if 0 - /** * \ingroup net-module-resolv * @@ -4133,8 +4091,6 @@ return resolve(host, service, Address().domain(), sc.type()); } -#endif - /** * \ingroup net-module-resolv * @@ -4159,8 +4115,6 @@ return *it; } -#if 0 - /** * \ingroup net-module-resolv * @@ -4178,8 +4132,6 @@ return resolveOne(host, service, Address().domain(), sc.type()); } -#endif - } // !net #endif // !NET_HPP
--- a/modules/net/test/main.cpp Thu Jun 23 07:37:02 2016 +0200 +++ b/modules/net/test/main.cpp Thu Jun 23 13:50:27 2016 +0200 @@ -29,7 +29,6 @@ using namespace net; using namespace net::address; using namespace net::option; -using namespace net::protocol; using namespace std::literals::chrono_literals; @@ -40,7 +39,7 @@ TEST(Options, reuse) { - SocketTcpIp s; + TcpSocketIp s; try { s.set(option::SockReuseAddress(true)); @@ -55,7 +54,7 @@ TEST(Options, nodelay) { - SocketTcpIp s; + TcpSocketIp s; try { s.set(option::TcpNoDelay(true)); @@ -70,7 +69,7 @@ TEST(Options, v6only) { - SocketTcpIpv6 s; + TcpSocketIpv6 s; try { s.set(option::Ipv6Only(true)); @@ -90,8 +89,8 @@ class TcpServerTest : public testing::Test { protected: - SocketTcp<Ipv4> m_server; - SocketTcp<Ipv4> m_client; + TcpSocketIpv4 m_server; + TcpSocketIpv4 m_client; std::thread m_tserver; std::thread m_tclient; @@ -115,7 +114,7 @@ { m_tserver = std::thread([this] () { try { - SocketTcp<Ipv4> sc; + TcpSocketIpv4 sc; m_server.bind(Ipv4("*", 16000)); m_server.listen(); @@ -144,22 +143,30 @@ m_server.bind(Ipv4("*", 16000)); m_server.listen(); - SocketTcp<Ipv4> client = m_server.accept(); + TcpSocketIpv4 client = m_server.accept(); - auto msg = client.recv(512); + std::string msg; + + msg.resize(512); + msg.resize(client.recv(&msg[0], 512)); ASSERT_EQ("hello world", msg); - client.send(msg); + client.send(msg.data(), msg.length()); }); std::this_thread::sleep_for(100ms); m_tclient = std::thread([this] () { + std::string msg = "hello world"; + m_client.connect(Ipv4("127.0.0.1", 16000)); - m_client.send("hello world"); + m_client.send(msg.c_str(), msg.length()); - ASSERT_EQ("hello world", m_client.recv(512)); + msg.resize(512); + msg.resize(m_client.recv(&msg[0], 512)); + + ASSERT_EQ("hello world", msg); }); } @@ -170,8 +177,8 @@ class UdpServerTest : public testing::Test { protected: - SocketUdp<Ipv4> m_server; - SocketUdp<Ipv4> m_client; + UdpSocketIpv4 m_server; + UdpSocketIpv4 m_client; std::thread m_tserver; std::thread m_tclient; @@ -200,14 +207,17 @@ m_server.bind(info); - auto msg = m_server.recvfrom(512, client); + std::string msg; + + msg.resize(512); + msg.resize(m_server.recvfrom(&msg[0], 512, &client)); ASSERT_EQ("hello world", msg); - m_server.sendto(msg, client); + m_server.sendto(msg.c_str(), msg.length(), client); m_server.close(); } catch (const net::Error &ex) { - FAIL() << ex.function() << ": " << ex.what(); + FAIL() << ex.what(); } }); @@ -216,14 +226,18 @@ m_tclient = std::thread([this] () { try { Ipv4 info("127.0.0.1", 16000); + std::string msg = "hello world"; - m_client.sendto("hello world", info); + m_client.sendto(msg.c_str(), msg.length(), info); - ASSERT_EQ("hello world", m_client.recvfrom(512, info)); + msg.resize(512); + msg.resize(m_client.recvfrom(&msg[0], 512, &info)); + + ASSERT_EQ("hello world", msg); m_client.close(); } catch (const net::Error &ex) { - FAIL() << ex.function() << ": " << ex.what(); + FAIL() << ex.what(); } }); } @@ -466,8 +480,8 @@ class ListenerTest : public testing::Test { protected: Listener<backend::Select> m_listener; - SocketTcp<Ipv4> m_masterTcp; - SocketTcp<Ipv4> m_clientTcp; + TcpSocketIpv4 m_masterTcp; + TcpSocketIpv4 m_clientTcp; std::thread m_tserver; std::thread m_tclient; @@ -518,9 +532,14 @@ m_listener.set(m_masterTcp.handle(), Condition::Readable); m_listener.wait(); - SocketTcp<Ipv4> sc = m_masterTcp.accept(); + TcpSocketIpv4 sc = m_masterTcp.accept(); + + std::string msg; - ASSERT_EQ("hello", sc.recv(512)); + msg.resize(512); + msg.resize(sc.recv(&msg[0], 512)); + + ASSERT_EQ("hello", msg); } catch (const std::exception &ex) { FAIL() << ex.what(); } @@ -529,8 +548,10 @@ std::this_thread::sleep_for(100ms); m_tclient = std::thread([this] () { + std::string msg = "hello"; + m_clientTcp.connect(Ipv4("127.0.0.1", 16000)); - m_clientTcp.send("hello"); + m_clientTcp.send(msg.c_str(), msg.length()); }); } @@ -541,8 +562,8 @@ class NonBlockingConnectTest : public testing::Test { protected: - SocketTcp<Ipv4> m_server; - SocketTcp<Ipv4> m_client; + TcpSocketIpv4 m_server; + TcpSocketIpv4 m_client; std::thread m_tserver; std::thread m_tclient; @@ -569,8 +590,8 @@ class TcpAcceptTest : public testing::Test { protected: - SocketTcp<Ipv4> m_server; - SocketTcp<Ipv4> m_client; + TcpSocketIpv4 m_server; + TcpSocketIpv4 m_client; std::thread m_tserver; std::thread m_tclient; @@ -599,8 +620,8 @@ class TcpRecvTest : public testing::Test { protected: - SocketTcp<Ipv4> m_server; - SocketTcp<Ipv4> m_client; + TcpSocketIpv4 m_server; + TcpSocketIpv4 m_client; std::thread m_tserver; std::thread m_tclient; @@ -625,91 +646,26 @@ TEST_F(TcpRecvTest, blockingSuccess) { m_tserver = std::thread([this] () { - SocketTcp<Ipv4> client = m_server.accept(); + TcpSocketIpv4 client = m_server.accept(); + std::string msg; - ASSERT_EQ("hello", client.recv(32)); + msg.resize(512); + msg.resize(client.recv(&msg[0], 512)); + + ASSERT_EQ("hello", msg); }); std::this_thread::sleep_for(100ms); m_tclient = std::thread([this] () { + std::string msg = "hello"; + m_client.connect(Ipv4("127.0.0.1", 16000)); - m_client.send("hello"); + m_client.send(msg.c_str(), msg.length()); m_client.close(); }); } -/* - * Socket SSL. - * ------------------------------------------------------------------ - */ - -#if !defined(SOCKET_NO_SSL) - -class TlsRecvTest : public testing::Test { -protected: - SocketTls<Ipv4> m_server{nullptr}; - SocketTls<Ipv4> m_client{nullptr}; - - std::thread m_tserver; - std::thread m_tclient; - -public: - TlsRecvTest() - { - Tls cp, sp; - - // Client. - cp.setVerify(false); - - m_client = SocketTls<Ipv4>(Ipv4(), std::move(cp)); - - // Server. - sp.setVerify(false); - sp.setCertificate(DIRECTORY "test.crt"); - sp.setPrivateKey(DIRECTORY "test.key"); - - m_server = SocketTls<Ipv4>(Ipv4(), std::move(sp)); - m_server.set(SockReuseAddress()); - m_server.bind(Ipv4("*", 16000)); - m_server.listen(); - } - - ~TlsRecvTest() - { - if (m_tserver.joinable()) - m_tserver.join(); - if (m_tclient.joinable()) - m_tclient.join(); - } -}; - -TEST_F(TlsRecvTest, blockingSuccess) -{ - m_tserver = std::thread([this] () { - try { - SocketTls<Ipv4> client = m_server.accept(); - - ASSERT_EQ("hello", client.recv(32)); - } catch (const net::Error &ex) { - FAIL() << ex.function() << ": " << ex.what(); - } - }); - - std::this_thread::sleep_for(250ms); - - m_tclient = std::thread([this] () { - try { - m_client.connect(Ipv4("127.0.0.1", 16000)); - m_client.send("hello"); - } catch (const net::Error &ex) { - FAIL() << ex.function() << ": " << ex.what(); - } - }); -} - -#endif - int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv);