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 47 : inline void AbstractSocket::setDataListener(IDataListener* const pListener)
212 : {
213 47 : _dataListener = pListener;
214 47 : }
215 :
216 : inline void
217 47 : AbstractSocket::setSendNotificationListener(IDataSendNotificationListener* const pListener)
218 : {
219 47 : _sendNotificationListener = pListener;
220 47 : }
221 :
222 57 : inline IDataListener* AbstractSocket::getDataListener() const { return _dataListener; }
223 :
224 44 : inline IDataSendNotificationListener* AbstractSocket::getSendNotificationListener() const
225 : {
226 44 : return _sendNotificationListener;
227 : }
228 :
229 : } // namespace tcp
|