#ifndef _TCPSTREAM_HPP #define _TCPSTREAM_HPP #include <string> #include "sockaddr.hpp" namespace netlib { /** * @brief The TcpStream represents tcp a connection with another endpoint and is * used to send and receive data through that connection. */ class TcpStream { private: /** * @brief The remote SockAddr that the TcpStream will be connected to, or * currently is connected to (depending on wether the connection is open * or closed). */ SockAddr remote; /** * @brief The filedescriptor of the current socket. If this is 0, the socket * is closed. */ int sockfd; public: /** * @brief Create a TcpStream that will connect to the specified remote * socket address. * * @param remote The SockAddress that will be connected to in the connect * function. */ TcpStream(SockAddr remote); /** * @brief Same as TcpStream(SockAddr) and the parameters are passed to * SockAddr constructor. * * @see SockAddr */ TcpStream(IpAddr remoteAddress, uint16_t port); /** * @brief Same as TcpStream(SockAddr) and the parameters are passed to * SockAddr constructor. * * @see SockAddr */ TcpStream(const std::string &remoteAddress, uint16_t port); /** * @brief Same as TcpStream(SockAddr) and the parameters are passed to * SockAddr constructor. * * @see SockAddr */ TcpStream(const std::string &remoteAddressPort); /** * @brief The socket is automatically closed when the TcpStream is * destroyed. */ ~TcpStream(); TcpStream(TcpStream &&other) = default; TcpStream& operator=(TcpStream &&other) = default; /** * @brief Copying TcpListener is not allowed. */ TcpStream(const TcpStream &other) = delete; /** * @brief Copying TcpListener is not allowed. */ TcpStream& operator=(const TcpStream &other) = delete; /** * @brief Connect to the remote socket address specified in the constructor. */ void connect(); /** * @brief Close the listening socket. After this, the TcpStream can no * longer be used without reconnecting using connect. */ void close(); /** * @brief Send a maximum of len bytes of data into the tcp connection. It * is possible that less than len bytes are sent, in that case the rest has * to be sent with another call to send. * * If sending fails, an exception is thrown. * * @param data Pointer to at least len bytes that will be sent over the * tcp connection. * @param len The maxiumum number of bytes that will be sent over the tcp * connection. * * @return The number of bytes that were actually sent over the connection. * This can be less than len. */ ssize_t send(const void *data, size_t len); /** * @brief Send exactly len bytes of data into the tcp connection. * * If sending fails, an exception is thrown. * * @param data Pointer to at least len bytes that will be sent over the * tcp connection. * @param len The number of bytes that will be sent over the tcp connection. * * @return The number of bytes that were actually sent over the connection. */ void sendAll(const void *data, size_t len); /** * @brief Send the given string data over the tcp connection. The function * send all chars of the given string. * * If the sending fails, an exception is thrown. * * @param str The string that will be sent. */ void sendAllString(const std::string &str); /** * @brief Receive a maximum of len bytes of data from the tcp connection. It * is possible that less than len bytes are received. This call will block * until at least byte can be received or the connection terminates. * * If receiving fails, an exception is thrown. * * @param data Pointer to at least len bytes where the data received over * the tcp connection will be stored. * @param len The maxiumum number of bytes that will be received over the * tcp connection. * * @return The number of bytes that were actually received over the * connection. This can be less than len. */ ssize_t read(void *data, size_t len); /** * @brief Read exactly len bytes from the tcp stream. If the connection is * closed before len bytes are read, the number of bytes actually read is * returned. This will block until exactly len bytes are read or the * connection is closed. * * If receiving failed or the connection is closed before at least one * byte was received, an exception is thrown. * * @param data Pointer to at least len bytes where the data received over * the tcp connection will be stored. * @param len The number of bytes that will be received over the tcp * connection. * * @return The number of bytes that were actually received over the * connection. This can be less than len if the connection is closed. */ ssize_t readAll(void *data, size_t len); /** * @brief Same as TcpStream::read but with a millisecond timeout. If the * timeout is reached without receiving data, 0 is returned. * * If receiving fails, an exception is thrown. * * @param data Pointer to at least len bytes where the data received over * the tcp connection will be stored. * @param len The maxiumum number of bytes that will be received over the * tcp connection. * @param timeoutMs The number of milliseconds before a timeout occurs. * * @return The number of bytes that were actually received over the * connection. This can be less than len. If a timeout occurs 0 is * returned. */ ssize_t readTimeout(void *data, size_t len, int timeoutMs); /** * @brief Same as TcpStream::readAll but with a millisecond timeout. If * the timeout is reached without receiving any data, 0 is returned. If * the timout occurs after receiving some data, the number of bytes * received before the timeout is returned as NEGATIVE. The timeout * starts from the begining if partial data is received. * * If receiving failed an exception is thrown. * * @param data Pointer to at least len bytes where the data received over * the tcp connection will be stored. * @param len The number of bytes that will be received over the tcp * connection. * @param timeoutMs The number of milliseconds before a timeout occurs. * * @return The number of bytes that were actually received over the * connection. This can be less than len if the connection is closed. * If a timout occurs after some data was already read, the number of * bytes is returned as negative. */ ssize_t readAllTimeout(void *data, size_t len, int timeoutMs); /** * @brief Get the socket address of the connection target. * * @return The connection targets socket address. */ const SockAddr & getRemoteAddr() const; /** * @brief Check if the socket is closed or open. Open in this case means * connected to the remote. * * @return True if the socket was not yet opened, or if it has been closed. */ bool isClosed() const; friend class TcpListener; }; } // namespace netlib #endif // _TCPSTREAM_HPP