#ifndef SPONGE_LIBSPONGE_SOCKET_HH #define SPONGE_LIBSPONGE_SOCKET_HH #include "address.hh" #include "file_descriptor.hh" #include #include #include #include //! \brief Base class for network sockets (TCP, UDP, etc.) //! \details Socket is generally used via a subclass. See TCPSocket and UDPSocket for usage examples. class Socket : public FileDescriptor { private: //! Get the local or peer address the socket is connected to Address get_address(const std::string &name_of_function, const std::function &function) const; protected: //! Construct via [socket(2)](\ref man2::socket) Socket(const int domain, const int type); //! Construct from a file descriptor. Socket(FileDescriptor &&fd, const int domain, const int type); //! Wrapper around [setsockopt(2)](\ref man2::setsockopt) template void setsockopt(const int level, const int option, const option_type &option_value); public: //! Bind a socket to a specified address with [bind(2)](\ref man2::bind), usually for listen/accept void bind(const Address &address); //! Connect a socket to a specified peer address with [connect(2)](\ref man2::connect) void connect(const Address &address); //! Shut down a socket via [shutdown(2)](\ref man2::shutdown) void shutdown(const int how); //! Get local address of socket with [getsockname(2)](\ref man2::getsockname) Address local_address() const; //! Get peer address of socket with [getpeername(2)](\ref man2::getpeername) Address peer_address() const; //! Allow local address to be reused sooner via [SO_REUSEADDR](\ref man7::socket) void set_reuseaddr(); }; //! A wrapper around [UDP sockets](\ref man7::udp) class UDPSocket : public Socket { protected: //! \brief Construct from FileDescriptor (used by TCPOverUDPSocketAdapter) //! \param[in] fd is the FileDescriptor from which to construct explicit UDPSocket(FileDescriptor &&fd) : Socket(std::move(fd), AF_INET, SOCK_DGRAM) {} public: //! Default: construct an unbound, unconnected UDP socket UDPSocket() : Socket(AF_INET, SOCK_DGRAM) {} //! Returned by UDPSocket::recv; carries received data and information about the sender struct received_datagram { Address source_address; //!< Address from which this datagram was received std::string payload; //!< UDP datagram payload }; //! Receive a datagram and the Address of its sender received_datagram recv(const size_t mtu = 65536); //! Receive a datagram and the Address of its sender (caller can allocate storage) void recv(received_datagram &datagram, const size_t mtu = 65536); //! Send a datagram to specified Address void sendto(const Address &destination, const BufferViewList &payload); //! Send datagram to the socket's connected address (must call connect() first) void send(const BufferViewList &payload); }; //! \class UDPSocket //! Functions in this class are essentially wrappers over their POSIX eponyms. //! //! Example: //! //! \include socket_example_1.cc //! A wrapper around [TCP sockets](\ref man7::tcp) class TCPSocket : public Socket { private: //! \brief Construct from FileDescriptor (used by accept()) //! \param[in] fd is the FileDescriptor from which to construct explicit TCPSocket(FileDescriptor &&fd) : Socket(std::move(fd), AF_INET, SOCK_STREAM) {} public: //! Default: construct an unbound, unconnected TCP socket TCPSocket() : Socket(AF_INET, SOCK_STREAM) {} //! Mark a socket as listening for incoming connections void listen(const int backlog = 16); //! Accept a new incoming connection TCPSocket accept(); }; //! \class TCPSocket //! Functions in this class are essentially wrappers over their POSIX eponyms. //! //! Example: //! //! \include socket_example_2.cc //! A wrapper around [Unix-domain stream sockets](\ref man7::unix) class LocalStreamSocket : public Socket { public: //! Construct from a file descriptor explicit LocalStreamSocket(FileDescriptor &&fd) : Socket(std::move(fd), AF_UNIX, SOCK_STREAM) {} }; //! \class LocalStreamSocket //! Example: //! //! \include socket_example_3.cc #endif // SPONGE_LIBSPONGE_SOCKET_HH