Line data Source code
1 : // Copyright 2025 Accenture. 2 : 3 : #pragma once 4 : 5 : #include <etl/delegate.h> 6 : #include <etl/span.h> 7 : #include <ip/IPAddress.h> 8 : 9 : #include <cstdint> 10 : 11 : namespace tcp 12 : { 13 : class IDataListener; 14 : class IDataSendNotificationListener; 15 : 16 : /** 17 : * Abstract base class for all sockets. 18 : * 19 : * \section Overview 20 : * The AbstractSocket is designed to be a socket abstraction to 21 : * a TCP stack. 22 : * The socket class can be used to connect to a remote system. It is also 23 : * returned to an ISocketConnectionListener by AbstractServerSocket 24 : * (using its ISocketProvider) once a connection from a remote system 25 : * is accepted. An active socket is used to receive and transmit data 26 : * from and to a remote system. 27 : * 28 : * \section Receive 29 : * The application that wants to receive data from a socket has to register 30 : * through the setDataListener method as an IDataListener. 31 : * After that the application is notified through its dataReceived 32 : * method. 33 : * 34 : * \section Send 35 : * Sending data through a socket is usually asynchronous. Because of that 36 : * it is possible to register an IDataSendNotificationListener who is 37 : * notified when the data passed to the send method is written to the 38 : * TCP-stack. 39 : * <b>This is not the time when the ACK package from the remote 40 : * system, is received!</b> 41 : * 42 : * \see AbstractServerSocket 43 : * \see ISocketProvidingConnectionListener 44 : * \see IDataListener 45 : * \see IDataSendNotificationListener 46 : */ 47 : class AbstractSocket 48 : { 49 : public: 50 : // [AbstractSocket] 51 : /** 52 : * all ErrorCodes used by socket 53 : * \enum ErrorCode 54 : */ 55 : enum class ErrorCode : uint8_t 56 : { 57 : /** everything ok */ 58 : SOCKET_ERR_OK, 59 : /** an error occurred */ 60 : SOCKET_ERR_NOT_OK, 61 : /** socket not open to send */ 62 : SOCKET_ERR_NOT_OPEN, 63 : /** no more outgoing buffer available */ 64 : SOCKET_ERR_NO_MORE_BUFFER, 65 : /** socket is full, flush before continuing */ 66 : SOCKET_FLUSH 67 : }; 68 : 69 : using ConnectedDelegate = ::etl::delegate<void(ErrorCode)>; 70 : 71 : /** 72 : * constructor 73 : * \post fpDataListener == 0L 74 : * \post fpSendNotificationListener == 0L 75 : */ 76 : AbstractSocket(); 77 : 78 : AbstractSocket(AbstractSocket const&) = delete; 79 : AbstractSocket& operator=(AbstractSocket const&) = delete; 80 : 81 : /** 82 : * binds to a local address and port 83 : * \param ipAddr local ip address 84 : * \param port local port 85 : */ 86 : virtual ErrorCode bind(ip::IPAddress const& ipAddr, uint16_t port) = 0; 87 : 88 : /** 89 : * connects to a remote host 90 : * \param ipAddr remote ip address 91 : * \param port remote port 92 : */ 93 : virtual ErrorCode 94 : connect(ip::IPAddress const& ipAddr, uint16_t port, ConnectedDelegate delegate) 95 : = 0; 96 : 97 : /** 98 : * closes the socket by sending a FIN packet 99 : */ 100 : virtual ErrorCode close() = 0; 101 : 102 : /** 103 : * aborts the socket by sending a RST packet 104 : */ 105 : virtual void abort() = 0; 106 : 107 : /** 108 : * flushes enqueued data 109 : */ 110 : virtual ErrorCode flush() = 0; 111 : 112 : /** 113 : * discards any received data without ack 114 : */ 115 : virtual void discardData() = 0; 116 : 117 : /** 118 : * \return number of bytes available in outgoing buffer 119 : */ 120 : virtual size_t available() = 0; 121 : 122 : /** 123 : * reads a single byte 124 : * \param byte byte to read 125 : * \return number of bytes read 126 : * - 0: an error occurred reading from the socket 127 : * - 1: byte read 128 : */ 129 : virtual uint8_t read(uint8_t& byte) = 0; 130 : 131 : /** 132 : * reads a given number of bytes from the socket 133 : * \param buffer buffer to receive data to. If 0L is passed the n 134 : * bytes should be skipped, i.e. the input stream has to advance by 135 : * n bytes. 136 : * \param n number of bytes to receive 137 : * \return number of bytes really read 138 : * - 0: an error occurred reading from the socket 139 : * - else: bytes read 140 : */ 141 : virtual size_t read(uint8_t* buffer, size_t n) = 0; 142 : 143 : /** 144 : * sends an amount of data 145 : * \param data data to send 146 : * \return status of transmission 147 : * - SOCKET_OK when data was sent to TCP stack 148 : * - SOCKET_CLOSED when socket has not been opened 149 : * \note 150 : * Sending the data may be asynchronous. For this reason the 151 : * IDataSendNotificationListener has an appropriate callback. 152 : */ 153 : virtual ErrorCode send(::etl::span<uint8_t const> const& data) = 0; 154 : 155 : /** 156 : * sets the listener to this socket instance 157 : * \param pListener IDataListener to attach 158 : */ 159 : void setDataListener(IDataListener* pListener); 160 : 161 : IDataListener* getDataListener() const; 162 : 163 : /** 164 : * sets the IDataSendNotificationListener of this socket 165 : * \param pListener listener that gets notified when data has been 166 : * copied completely to TCP stack 167 : */ 168 : void setSendNotificationListener(IDataSendNotificationListener* pListener); 169 : 170 : IDataSendNotificationListener* getSendNotificationListener() const; 171 : 172 : virtual ip::IPAddress getRemoteIPAddress() const = 0; 173 : 174 : virtual ip::IPAddress getLocalIPAddress() const = 0; 175 : 176 : virtual uint16_t getRemotePort() const = 0; 177 : 178 : virtual uint16_t getLocalPort() const = 0; 179 : 180 : virtual bool isClosed() const = 0; 181 : 182 : virtual bool isEstablished() const = 0; 183 : 184 : /** 185 : * Permanently disables NAGLE algorithm for this socket. 186 : */ 187 : virtual void disableNagleAlgorithm() = 0; 188 : 189 : /** 190 : * Enables TCP keepalive for this socket. 191 : * \param idle the length of time to keep an idle TCP connection active 192 : * \param interval the interval between packets sent to validate the TCP connection 193 : * \param probes the number of keepalive probes to be sent before terminating the connection 194 : */ 195 : virtual void enableKeepAlive(uint32_t idle, uint32_t interval, uint32_t probes) = 0; 196 : 197 : /** 198 : * Disables TCP keepalive for this socket. 199 : */ 200 : virtual void disableKeepAlive() = 0; 201 : // [AbstractSocket] 202 : 203 : protected: 204 : IDataListener* _dataListener; 205 : IDataSendNotificationListener* _sendNotificationListener; 206 : }; 207 : 208 : /* 209 : * inline methods 210 : */ 211 2 : inline void AbstractSocket::setDataListener(IDataListener* const pListener) 212 : { 213 2 : _dataListener = pListener; 214 : } 215 : 216 : inline void 217 2 : AbstractSocket::setSendNotificationListener(IDataSendNotificationListener* const pListener) 218 : { 219 2 : _sendNotificationListener = pListener; 220 : } 221 : 222 2 : inline IDataListener* AbstractSocket::getDataListener() const { return _dataListener; } 223 : 224 2 : inline IDataSendNotificationListener* AbstractSocket::getSendNotificationListener() const 225 : { 226 2 : return _sendNotificationListener; 227 : } 228 : 229 : } // namespace tcp