oveRTOS C++ API
C++20 RAII wrappers for the oveRTOS C API
Loading...
Searching...
No Matches
net.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 *
6 * This file is part of oveRTOS.
7 */
8
14#pragma once
15
16#include <ove/net.h>
17#include <ove/types.hpp>
18
19#ifdef CONFIG_OVE_NET
20
21namespace ove {
22
23/* ── Address (value type, copyable) ─────────────────────────────── */
24
33class Address {
34public:
38 Address() : raw{} {}
39
49 static Address ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
50 uint16_t port) {
51 Address addr;
52 ove_sockaddr_ipv4(&addr.raw, a, b, c, d, port);
53 return addr;
54 }
55
60 uint16_t port() const { return raw.port; }
61
66 void set_port(uint16_t p) { raw.port = p; }
67
69 ove_sockaddr_t raw;
70};
71
72/* ── NetIfConfig (builder, copyable) ────────────────────────────── */
73
81class NetIfConfig {
82public:
86 NetIfConfig() : raw{} {}
87
95 NetIfConfig &static_ip(const Address &ip, const Address &mask,
96 const Address &gw) {
97 raw.use_dhcp = 0;
98 raw.static_ip = ip.raw;
99 raw.netmask = mask.raw;
100 raw.gateway = gw.raw;
101 return *this;
102 }
103
108 NetIfConfig &dhcp() {
109 raw.use_dhcp = 1;
110 return *this;
111 }
112
118 NetIfConfig &dns(const Address &d) {
119 raw.dns = d.raw;
120 return *this;
121 }
122
124 ove_netif_config_t raw;
125};
126
127/* ── NetIf (RAII network interface) ─────────────────────────────── */
128
139class NetIf {
140public:
146 NetIf() {
147 int err = ove_netif_init(&handle_, &storage_);
148 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
149 }
150
154 ~NetIf() {
155 if (!handle_) return;
156 ove_netif_deinit(handle_);
157 }
158
159 NetIf(const NetIf &) = delete;
160 NetIf &operator=(const NetIf &) = delete;
161
162#ifdef CONFIG_OVE_ZERO_HEAP
163 NetIf(NetIf &&) = delete;
164 NetIf &operator=(NetIf &&) = delete;
165#else
170 NetIf(NetIf &&other) noexcept : handle_(other.handle_) {
171 other.handle_ = nullptr;
172 }
173
179 NetIf &operator=(NetIf &&other) noexcept {
180 if (this != &other) {
181 if (handle_) ove_netif_deinit(handle_);
182 handle_ = other.handle_;
183 other.handle_ = nullptr;
184 }
185 return *this;
186 }
187#endif
188
194 [[nodiscard]] int up(const NetIfConfig &cfg) {
195 return ove_netif_up(handle_, &cfg.raw);
196 }
197
201 void down() {
202 ove_netif_down(handle_);
203 }
204
212 [[nodiscard]] int get_addr(Address *ip = nullptr,
213 Address *gateway = nullptr,
214 Address *netmask = nullptr) {
215 return ove_netif_get_addr(handle_,
216 ip ? &ip->raw : nullptr,
217 gateway ? &gateway->raw : nullptr,
218 netmask ? &netmask->raw : nullptr);
219 }
220
225 bool valid() const { return handle_ != nullptr; }
226
231 ove_netif_t handle() const { return handle_; }
232
233private:
234 ove_netif_t handle_{};
235 ove_netif_storage_t storage_{};
236};
237
238/* ── Forward declaration for friend access ──────────────────────── */
239
240class TcpListener;
241
242/* ── TcpSocket (RAII TCP socket) ────────────────────────────────── */
243
254class TcpSocket {
255public:
261 TcpSocket() {
262 int err = ove_socket_open(&handle_, &storage_,
263 OVE_AF_INET, OVE_SOCK_STREAM);
264 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
265 open_ = true;
266 }
267
271 ~TcpSocket() {
272 if (open_) ove_socket_close(handle_);
273 }
274
275 TcpSocket(const TcpSocket &) = delete;
276 TcpSocket &operator=(const TcpSocket &) = delete;
277
278#ifdef CONFIG_OVE_ZERO_HEAP
279 TcpSocket(TcpSocket &&) = delete;
280 TcpSocket &operator=(TcpSocket &&) = delete;
281#else
286 TcpSocket(TcpSocket &&other) noexcept
287 : handle_(other.handle_)
288 , storage_(other.storage_)
289 , open_(other.open_) {
290 other.handle_ = nullptr;
291 other.open_ = false;
292 }
293
299 TcpSocket &operator=(TcpSocket &&other) noexcept {
300 if (this != &other) {
301 if (open_) ove_socket_close(handle_);
302 handle_ = other.handle_;
303 storage_ = other.storage_;
304 open_ = other.open_;
305 other.handle_ = nullptr;
306 other.open_ = false;
307 }
308 return *this;
309 }
310#endif
311
318 [[nodiscard]] int connect(const Address &addr,
319 uint32_t timeout_ms = OVE_WAIT_FOREVER) {
320 return ove_socket_connect(handle_, &addr.raw, timeout_ms);
321 }
322
330 [[nodiscard]] int send(const void *data, size_t len,
331 size_t *sent = nullptr) {
332 return ove_socket_send(handle_, data, len, sent);
333 }
334
343 [[nodiscard]] int recv(void *buf, size_t len,
344 size_t *received = nullptr,
345 uint32_t timeout_ms = OVE_WAIT_FOREVER) {
346 return ove_socket_recv(handle_, buf, len, received, timeout_ms);
347 }
348
354 void close() {
355 if (open_) {
356 ove_socket_close(handle_);
357 open_ = false;
358 }
359 }
360
365 bool is_open() const { return open_; }
366
371 ove_socket_t handle() const { return handle_; }
372
373private:
374 friend class TcpListener;
375
381 TcpSocket(ove_socket_t h, ove_socket_storage_t s)
382 : handle_(h), storage_(s), open_(true) {}
383
384 ove_socket_t handle_{};
385 ove_socket_storage_t storage_{};
386 bool open_{false};
387};
388
389/* ── UdpSocket (RAII UDP socket) ────────────────────────────────── */
390
399class UdpSocket {
400public:
406 UdpSocket() {
407 int err = ove_socket_open(&handle_, &storage_,
408 OVE_AF_INET, OVE_SOCK_DGRAM);
409 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
410 open_ = true;
411 }
412
416 ~UdpSocket() {
417 if (open_) ove_socket_close(handle_);
418 }
419
420 UdpSocket(const UdpSocket &) = delete;
421 UdpSocket &operator=(const UdpSocket &) = delete;
422
423#ifdef CONFIG_OVE_ZERO_HEAP
424 UdpSocket(UdpSocket &&) = delete;
425 UdpSocket &operator=(UdpSocket &&) = delete;
426#else
431 UdpSocket(UdpSocket &&other) noexcept
432 : handle_(other.handle_)
433 , storage_(other.storage_)
434 , open_(other.open_) {
435 other.handle_ = nullptr;
436 other.open_ = false;
437 }
438
444 UdpSocket &operator=(UdpSocket &&other) noexcept {
445 if (this != &other) {
446 if (open_) ove_socket_close(handle_);
447 handle_ = other.handle_;
448 storage_ = other.storage_;
449 open_ = other.open_;
450 other.handle_ = nullptr;
451 other.open_ = false;
452 }
453 return *this;
454 }
455#endif
456
462 [[nodiscard]] int bind(const Address &addr) {
463 return ove_socket_bind(handle_, &addr.raw);
464 }
465
474 [[nodiscard]] int send_to(const void *data, size_t len,
475 const Address &dest,
476 size_t *sent = nullptr) {
477 return ove_socket_sendto(handle_, data, len, sent, &dest.raw);
478 }
479
489 [[nodiscard]] int recv_from(void *buf, size_t len,
490 Address *src = nullptr,
491 size_t *received = nullptr,
492 uint32_t timeout_ms = OVE_WAIT_FOREVER) {
493 return ove_socket_recvfrom(handle_, buf, len, received,
494 src ? &src->raw : nullptr,
495 timeout_ms);
496 }
497
503 void close() {
504 if (open_) {
505 ove_socket_close(handle_);
506 open_ = false;
507 }
508 }
509
514 bool is_open() const { return open_; }
515
520 ove_socket_t handle() const { return handle_; }
521
522private:
523 ove_socket_t handle_{};
524 ove_socket_storage_t storage_{};
525 bool open_{false};
526};
527
528/* ── TcpListener (RAII listening socket) ────────────────────────── */
529
540class TcpListener {
541public:
547 TcpListener() {
548 int err = ove_socket_open(&handle_, &storage_,
549 OVE_AF_INET, OVE_SOCK_STREAM);
550 OVE_STATIC_INIT_ASSERT(err == OVE_OK);
551 open_ = true;
552 }
553
557 ~TcpListener() {
558 if (open_) ove_socket_close(handle_);
559 }
560
561 TcpListener(const TcpListener &) = delete;
562 TcpListener &operator=(const TcpListener &) = delete;
563
564#ifdef CONFIG_OVE_ZERO_HEAP
565 TcpListener(TcpListener &&) = delete;
566 TcpListener &operator=(TcpListener &&) = delete;
567#else
572 TcpListener(TcpListener &&other) noexcept
573 : handle_(other.handle_)
574 , storage_(other.storage_)
575 , open_(other.open_) {
576 other.handle_ = nullptr;
577 other.open_ = false;
578 }
579
585 TcpListener &operator=(TcpListener &&other) noexcept {
586 if (this != &other) {
587 if (open_) ove_socket_close(handle_);
588 handle_ = other.handle_;
589 storage_ = other.storage_;
590 open_ = other.open_;
591 other.handle_ = nullptr;
592 other.open_ = false;
593 }
594 return *this;
595 }
596#endif
597
603 [[nodiscard]] int bind(const Address &addr) {
604 return ove_socket_bind(handle_, &addr.raw);
605 }
606
612 [[nodiscard]] int listen(int backlog = 4) {
613 return ove_socket_listen(handle_, backlog);
614 }
615
627 [[nodiscard]] int accept(TcpSocket &client,
628 uint32_t timeout_ms = OVE_WAIT_FOREVER) {
629 ove_socket_t cli_handle{};
630 ove_socket_storage_t cli_storage{};
631 int err = ove_socket_accept(handle_, &cli_handle,
632 &cli_storage, timeout_ms);
633 if (err == OVE_OK) {
634 client.close();
635 client.handle_ = cli_handle;
636 client.storage_ = cli_storage;
637 client.open_ = true;
638 }
639 return err;
640 }
641
647 void close() {
648 if (open_) {
649 ove_socket_close(handle_);
650 open_ = false;
651 }
652 }
653
658 bool is_open() const { return open_; }
659
664 ove_socket_t handle() const { return handle_; }
665
666private:
667 ove_socket_t handle_{};
668 ove_socket_storage_t storage_{};
669 bool open_{false};
670};
671
672/* ── DNS ────────────────────────────────────────────────────────── */
673
680namespace dns {
681
689[[nodiscard]] inline int resolve(const char *hostname, Address &addr,
690 uint32_t timeout_ms = 5000) {
691 return ove_dns_resolve(hostname, &addr.raw, timeout_ms);
692}
693
694} /* namespace dns */
695
696} /* namespace ove */
697
698#endif /* CONFIG_OVE_NET */
Top-level namespace for all oveRTOS C++ abstractions.
Definition app.hpp:19
Common type definitions and concepts for the C++ wrapper layer.