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