RADLib
RADical C++ application framework
RADNet.h
Go to the documentation of this file.
1 #ifndef RADNET_H
2 #define RADNET_H
3 
10 #pragma once
11 
12 #include <RADCore/RADCore.h>
13 
14 #include <cstdint>
15 #include <map>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 namespace RADNet {
21 
23  struct Datagram {
25  std::vector<uint8_t> payload;
27  std::string address;
29  uint16_t port = 0;
30  };
31 
33  enum class SocketState {
37  Connecting,
39  Connected,
41  Listening,
43  Closed
44  };
45 
48  public:
51 
56 
57  private:
60  };
61 
64  public:
65  RADEvents:
69  RAD_EVENT(errorOccurred, (std::string));
70 
75 
77  bool bind(uint16_t port, const std::string& address = "0.0.0.0");
79  bool sendTo(const std::string& address, uint16_t port, const std::vector<uint8_t>& payload);
81  void close();
83  bool isOpen() const;
85  uint16_t localPort() const;
86 
87  private:
88  struct Impl;
89  std::shared_ptr<Impl> pImpl_;
90  };
91 
94  public:
95  RADEvents:
99  RAD_EVENT(errorOccurred, (std::string));
100 
105 
107  bool listen(uint16_t port, const std::string& address = "0.0.0.0");
109  bool sendTo(const std::string& address, uint16_t port, const std::vector<uint8_t>& payload);
111  void close();
113  uint16_t localPort() const;
114 
115  RADHandlers:
119  void handleError(std::string message);
120 
121  private:
122  RADUdpSocket socket_;
123  RADCore::Connection datagramConnection_;
124  RADCore::Connection errorConnection_;
125  };
126 
129  public:
130  RADEvents:
135 
140 
142  bool open(RADCore::OpenMode mode) override;
144  bool connectToHost(const std::string& address, uint16_t port);
146  void close() override;
148  bool isOpen() const override;
150  ssize_t readData(void* buffer, size_t maxBytes) override;
152  ssize_t writeData(const void* data, size_t size) override;
155 
156  private:
157  friend class RADTcpServer;
158  RADTcpSocket(RADCore::EventLoop& loop, int acceptedFd, std::string peerAddress, uint16_t peerPort);
159 
160  struct Impl;
161  std::shared_ptr<Impl> pImpl_;
162  };
163 
166  public:
167  RADEvents:
169  RAD_EVENT(newConnection, (std::shared_ptr<RADNet::RADTcpSocket>));
171  RAD_EVENT(errorOccurred, (std::string));
172 
177 
179  bool listen(uint16_t port, const std::string& address = "0.0.0.0", int backlog = 128);
181  void close();
183  bool isListening() const;
185  uint16_t localPort() const;
186 
187  private:
188  struct Impl;
189  std::shared_ptr<Impl> pImpl_;
190  };
191 
195  int statusCode = 0;
197  std::string reasonPhrase;
199  std::map<std::string, std::string> headers;
201  std::string body;
202  };
203 
205  struct RADHttpRequest {
207  std::string method = "GET";
209  std::string url;
211  std::map<std::string, std::string> headers;
213  std::string body;
215  long timeoutMs = 30000;
217  long connectTimeoutMs = 10000;
219  bool followRedirects = true;
221  long maxRedirects = 8;
223  bool verifyTls = true;
224  };
225 
227  struct RADDnsResult {
229  std::vector<std::string> addresses;
231  std::string error;
232  };
233 
236  public:
237  RADEvents:
241  RAD_EVENT(errorOccurred, (std::string));
242 
245 
247  static std::optional<RADHttpResponse> request(const RADHttpRequest& request, std::string* error = nullptr);
249  static std::optional<RADHttpResponse> get(const RADCore::RADUrl& url, std::string* error = nullptr);
251  static std::optional<RADHttpResponse> get(const std::string& url, std::string* error = nullptr);
253  static std::optional<RADHttpResponse> post(const std::string& url, const std::string& body,
254  const std::map<std::string, std::string>& headers = {}, std::string* error = nullptr);
256  static RADDnsResult resolve(const std::string& host);
257 
261  void getAsync(const RADCore::RADUrl& url);
263  void getAsync(const std::string& url);
264 
265  private:
266  RADCore::EventLoop& loop_;
267  };
268 
270  struct RADTcpFrame {
272  uint32_t messageId = 0;
274  std::vector<uint8_t> payload;
275  };
276 
280  std::string address = "127.0.0.1";
282  uint16_t port = 0;
284  int backlog = 128;
286  int connectTimeoutMs = 5000;
288  uint32_t maxPayloadBytes = 16 * 1024 * 1024;
289  };
290 
292  std::vector<uint8_t> encodeFrame(const RADTcpFrame& frame);
294  bool decodeFrames(std::vector<uint8_t>& buffer, std::vector<RADTcpFrame>& frames,
295  uint32_t maxPayloadBytes = 16 * 1024 * 1024, std::string* error = nullptr);
298  const RADProtocolEndpointConfig& defaults = {});
299 
302  public:
303  RADEvents:
307  RAD_EVENT(errorOccurred, (std::string));
312 
316  RADProtocolSocket(RADCore::EventLoop& loop, std::shared_ptr<RADTcpSocket> socket);
318  ~RADProtocolSocket() override;
319 
321  bool connectToHost(const std::string& host, uint16_t port);
323  bool sendFrame(uint32_t messageId, const std::vector<uint8_t>& payload);
325  bool sendFrame(const RADTcpFrame& frame);
327  void close();
329  bool isOpen() const;
331  void setMaxPayloadBytes(uint32_t maxPayloadBytes);
332 
333  RADHandlers:
337  void handleError(std::string message);
342 
343  private:
344  void attach(std::shared_ptr<RADTcpSocket> socket);
345 
346  RADCore::EventLoop& loop_;
347  std::shared_ptr<RADTcpSocket> socket_;
348  RADCore::Connection readyReadConnection_;
349  RADCore::Connection errorConnection_;
350  RADCore::Connection connectedConnection_;
351  RADCore::Connection disconnectedConnection_;
352  std::vector<uint8_t> buffer_;
353  uint32_t maxPayloadBytes_ = 16 * 1024 * 1024;
354  };
355 
358  public:
363  };
364 
367  public:
368  RADEvents:
370  RAD_EVENT(newConnection, (std::shared_ptr<RADNet::RADProtocolSocket>));
372  RAD_EVENT(errorOccurred, (std::string));
373 
379  void close();
381  uint16_t localPort() const;
382 
383  RADHandlers:
385  void handleNewConnection(std::shared_ptr<RADNet::RADTcpSocket> socket);
387  void handleError(std::string message);
388 
389  private:
390  RADCore::EventLoop& loop_;
391  RADTcpServer server_;
392  RADCore::Connection newConnection_;
393  RADCore::Connection errorConnection_;
394  uint32_t maxPayloadBytes_ = 16 * 1024 * 1024;
395  };
396 
397 } // namespace RADNet
398 
399 #endif
#define RAD_EVENT(Name, Signature)
Declares a typed RADCore event; example: RAD_EVENT(done, (int)).
Definition: RADCore.h:65
#define RADEvents
Marks a public event declaration block in RADObject-derived classes.
Definition: RADCore.h:43
#define RADHandlers
Marks a public handler declaration block in RADObject-derived classes.
Definition: RADCore.h:45
Explicit event connection handle.
Definition: RADCore.h:903
RADCore task event loop with locked and low-latency scheduling strategies.
Definition: RADCore.h:956
Abstract byte-oriented IO device similar to QIODevice.
Definition: RADCore.h:1254
JSON value supporting null, bool, number, string, array, and object.
Definition: RADCore.h:509
Base class for event receivers, senders, and thread-affinity aware objects.
Definition: RADCore.h:931
Lightweight URL parser for scheme, host, port, path, query, and fragment.
Definition: RADCore.h:455
Small libcurl-backed HTTP client with sync and event-loop async APIs.
Definition: RADNet.h:235
static std::optional< RADHttpResponse > get(const RADCore::RADUrl &url, std::string *error=nullptr)
Performs a blocking GET request for url.
static std::optional< RADHttpResponse > get(const std::string &url, std::string *error=nullptr)
Parses url and performs a blocking GET request.
RADCore::Event< void(std::string) > errorOccurred
Raised by async requests when request setup or transfer fails.
Definition: RADNet.h:241
void requestAsync(const RADHttpRequest &request)
Starts an async request and emits finished/errorOccurred.
void getAsync(const std::string &url)
Parses url and starts an async GET request.
static std::optional< RADHttpResponse > post(const std::string &url, const std::string &body, const std::map< std::string, std::string > &headers={}, std::string *error=nullptr)
Performs a blocking POST request.
RADHttpClient(RADCore::EventLoop &loop)
Creates an async client that posts results to loop.
RADCore::Event< void(RADNet::RADHttpResponse) > finished
Raised by async requests when a response completes.
Definition: RADNet.h:239
static RADDnsResult resolve(const std::string &host)
Resolves host to address strings.
static std::optional< RADHttpResponse > request(const RADHttpRequest &request, std::string *error=nullptr)
Performs a blocking HTTP request.
void getAsync(const RADCore::RADUrl &url)
Starts an async GET request for url and emits finished/errorOccurred.
Framed protocol TCP client.
Definition: RADNet.h:357
bool connectUsingConfig(const RADProtocolEndpointConfig &config)
Connects using runtime config.
RADProtocolClient(RADCore::EventLoop &loop)
Creates a client.
Framed protocol TCP server.
Definition: RADNet.h:366
RADCore::Event< void(std::string) > errorOccurred
Raised when listening or accepting fails.
Definition: RADNet.h:372
uint16_t localPort() const
Returns bound local port.
void close()
Stops listening.
bool listenUsingConfig(const RADProtocolEndpointConfig &config)
Starts listening using config.
RADProtocolServer(RADCore::EventLoop &loop)
Creates a server.
void handleNewConnection(std::shared_ptr< RADNet::RADTcpSocket > socket)
Internal TCP accept handler.
void handleError(std::string message)
Internal error handler.
RADCore::Event< void(std::shared_ptr< RADNet::RADProtocolSocket >) > newConnection
Raised when a framed client is accepted.
Definition: RADNet.h:370
Protocol socket wrapper that frames RADTcpSocket byte streams.
Definition: RADNet.h:301
void handleConnected()
Internal connected handler.
RADCore::Event< void(RADNet::RADTcpFrame) > frameReceived
Raised when a full frame is received.
Definition: RADNet.h:305
bool sendFrame(const RADTcpFrame &frame)
Sends a frame.
void setMaxPayloadBytes(uint32_t maxPayloadBytes)
Sets maximum accepted payload size.
void handleError(std::string message)
Internal TCP error handler.
RADCore::Event< void(std::string) > errorOccurred
Raised on socket or framing errors.
Definition: RADNet.h:307
bool connectToHost(const std::string &host, uint16_t port)
Connects to host:port.
RADCore::Event< void() > connected
Raised when connected.
Definition: RADNet.h:309
bool sendFrame(uint32_t messageId, const std::vector< uint8_t > &payload)
Sends a frame.
void handleDisconnected()
Internal disconnected handler.
bool isOpen() const
Returns true when the wrapped socket is open.
RADProtocolSocket(RADCore::EventLoop &loop, std::shared_ptr< RADTcpSocket > socket)
Wraps an accepted TCP socket.
void handleReadyRead()
Internal TCP readyRead handler.
~RADProtocolSocket() override
Closes the socket.
RADCore::Event< void() > disconnected
Raised when disconnected.
Definition: RADNet.h:311
RADProtocolSocket(RADCore::EventLoop &loop)
Creates an unconnected protocol socket.
void close()
Closes the wrapped socket.
Process-wide epoll reactor used by RADNet sockets.
Definition: RADNet.h:47
static RADSocketReactor & instance()
Returns the singleton reactor instance.
RADSocketReactor & operator=(const RADSocketReactor &)=delete
Reactor ownership is singleton-only.
RADSocketReactor(const RADSocketReactor &)=delete
Reactor ownership is singleton-only.
Non-blocking TCP server that emits accepted sockets.
Definition: RADNet.h:165
bool listen(uint16_t port, const std::string &address="0.0.0.0", int backlog=128)
Starts listening on address:port with backlog.
~RADTcpServer()
Stops listening if needed.
RADCore::Event< void(std::shared_ptr< RADNet::RADTcpSocket >) > newConnection
Raised when a new client connection is accepted.
Definition: RADNet.h:169
bool isListening() const
Returns true when the server socket is listening.
uint16_t localPort() const
Returns the bound local port, or 0 when unavailable.
RADTcpServer(RADCore::EventLoop &loop)
Creates a server using loop for event delivery.
void close()
Stops listening and closes the server descriptor.
RADCore::Event< void(std::string) > errorOccurred
Raised when listen, accept, or reactor setup fails.
Definition: RADNet.h:171
Non-blocking TCP socket that also implements RADCore::RADIODevice.
Definition: RADNet.h:128
ssize_t readData(void *buffer, size_t maxBytes) override
Reads up to maxBytes from the socket into buffer.
RADCore::Event< void() > connected
Raised when a connection is established.
Definition: RADNet.h:132
RADCore::Event< void() > disconnected
Raised when the peer disconnects or the socket closes.
Definition: RADNet.h:134
ssize_t writeData(const void *data, size_t size) override
Writes size bytes from data to the socket.
bool isOpen() const override
Returns true when the descriptor is open.
bool connectToHost(const std::string &address, uint16_t port)
Starts a non-blocking connection to address:port.
~RADTcpSocket()
Closes the socket if needed.
void close() override
Closes the TCP descriptor and updates state.
RADTcpSocket(RADCore::EventLoop &loop)
Creates an unconnected TCP socket using loop for events.
bool open(RADCore::OpenMode mode) override
Opens the IODevice facet; networking is established with connectToHost().
SocketState state() const
Returns the current TCP socket state.
Convenience UDP server built on RADUdpSocket.
Definition: RADNet.h:93
RADUdpServer(RADCore::EventLoop &loop)
Creates a UDP server whose events are posted to loop.
bool sendTo(const std::string &address, uint16_t port, const std::vector< uint8_t > &payload)
Sends payload from the server socket to address:port.
void handleError(std::string message)
Internal handler that forwards socket errors.
RADCore::Event< void(std::string) > errorOccurred
Re-emits socket errors from the internal socket.
Definition: RADNet.h:99
void handleDatagram(RADNet::Datagram datagram)
Internal handler that forwards datagrams from the owned socket.
void close()
Stops listening and closes the socket.
RADCore::Event< void(RADNet::Datagram) > datagramReceived
Re-emits datagrams received by the internal socket.
Definition: RADNet.h:97
~RADUdpServer()
Closes the internal socket.
bool listen(uint16_t port, const std::string &address="0.0.0.0")
Starts listening for UDP datagrams on address:port.
uint16_t localPort() const
Returns the bound local port, or 0 when unavailable.
Event-loop integrated UDP socket.
Definition: RADNet.h:63
bool sendTo(const std::string &address, uint16_t port, const std::vector< uint8_t > &payload)
Sends payload to address:port.
~RADUdpSocket()
Closes the socket and unregisters it from the reactor.
void close()
Closes the UDP file descriptor if open.
RADCore::Event< void(RADNet::Datagram) > datagramReceived
Raised on the owning RADCore event loop when a datagram arrives.
Definition: RADNet.h:67
bool bind(uint16_t port, const std::string &address="0.0.0.0")
Binds to address:port. Use port 0 to request an ephemeral port.
bool isOpen() const
Returns true when the socket currently owns an open descriptor.
RADUdpSocket(RADCore::EventLoop &loop)
Creates a UDP socket whose events are posted to loop.
RADCore::Event< void(std::string) > errorOccurred
Raised when bind, send, receive, or reactor setup fails.
Definition: RADNet.h:69
uint16_t localPort() const
Returns the bound local port, or 0 when unavailable.
OpenMode
Open mode flags shared by RADIODevice, RADFile, and RADBuffer.
Definition: RADCore.h:293
Definition: RADNet.h:20
bool decodeFrames(std::vector< uint8_t > &buffer, std::vector< RADTcpFrame > &frames, uint32_t maxPayloadBytes=16 *1024 *1024, std::string *error=nullptr)
Attempts to decode all complete frames from buffer, removing consumed bytes.
std::vector< uint8_t > encodeFrame(const RADTcpFrame &frame)
Encodes a RADTcpFrame into wire bytes.
RADProtocolEndpointConfig endpointConfigFromJson(const RADCore::RADJsonValue &value, const RADProtocolEndpointConfig &defaults={})
Loads endpoint config from a JSON object.
SocketState
Common socket state used by RADNet TCP sockets.
Definition: RADNet.h:33
@ Closed
Socket was closed.
@ Unconnected
Socket has not connected or listened.
@ Connected
Socket is connected and can transfer data.
@ Listening
Server socket is listening.
@ Connecting
Non-blocking connect is in progress.
UDP datagram payload plus sender/target endpoint metadata.
Definition: RADNet.h:23
std::vector< uint8_t > payload
Raw datagram bytes.
Definition: RADNet.h:25
std::string address
IPv4/IPv6 address text.
Definition: RADNet.h:27
uint16_t port
UDP port in host byte order.
Definition: RADNet.h:29
DNS lookup result.
Definition: RADNet.h:227
std::vector< std::string > addresses
Resolved address strings.
Definition: RADNet.h:229
std::string error
Error text when resolution fails.
Definition: RADNet.h:231
HTTP request options for RADHttpClient::request().
Definition: RADNet.h:205
std::string url
Target URL.
Definition: RADNet.h:209
std::map< std::string, std::string > headers
Request headers.
Definition: RADNet.h:211
long timeoutMs
Total request timeout in milliseconds.
Definition: RADNet.h:215
long maxRedirects
Maximum redirects when followRedirects is true.
Definition: RADNet.h:221
std::string method
HTTP method such as GET, POST, PUT, DELETE.
Definition: RADNet.h:207
long connectTimeoutMs
Connection timeout in milliseconds.
Definition: RADNet.h:217
bool followRedirects
Follow redirects.
Definition: RADNet.h:219
bool verifyTls
Verify TLS peers for HTTPS requests.
Definition: RADNet.h:223
std::string body
Request body bytes/text.
Definition: RADNet.h:213
HTTP response data returned by RADHttpClient.
Definition: RADNet.h:193
std::map< std::string, std::string > headers
Response headers keyed by header name.
Definition: RADNet.h:199
std::string reasonPhrase
HTTP reason phrase, when provided by the server.
Definition: RADNet.h:197
std::string body
Response body as text bytes.
Definition: RADNet.h:201
int statusCode
Numeric HTTP status code.
Definition: RADNet.h:195
Runtime endpoint configuration loaded from JSON.
Definition: RADNet.h:278
int backlog
Server backlog.
Definition: RADNet.h:284
int connectTimeoutMs
Connect timeout in milliseconds.
Definition: RADNet.h:286
uint32_t maxPayloadBytes
Maximum accepted payload bytes.
Definition: RADNet.h:288
std::string address
Server bind address or client host.
Definition: RADNet.h:280
uint16_t port
TCP port.
Definition: RADNet.h:282
Binary TCP protocol frame: u32 messageId, u32 payloadSize, payload.
Definition: RADNet.h:270
uint32_t messageId
Message identifier in host byte order.
Definition: RADNet.h:272
std::vector< uint8_t > payload
Raw payload bytes.
Definition: RADNet.h:274