DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
iface_bridge.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
5
6#if DETWS_ENABLE_IFACE_BRIDGE
7
8#include <string.h>
9
10namespace
11{
12/// The one owned mutable: the address:port -> bus rule table.
13struct BridgeCtx
14{
15 BridgeRule rules[DETWS_BRIDGE_MAX_RULES];
16 uint8_t count;
17};
18BridgeCtx s_bridge;
19} // namespace
20
21void bridge_clear()
22{
23 for (uint8_t i = 0; i < DETWS_BRIDGE_MAX_RULES; i++)
24 s_bridge.rules[i].used = false;
25 s_bridge.count = 0;
26}
27
28bool bridge_add(const BridgeRule *rule)
29{
30 if (!rule)
31 return false;
32 if (bridge_find(rule->listen_port, rule->proto))
33 return false; // a rule already binds this port+proto
34 for (uint8_t i = 0; i < DETWS_BRIDGE_MAX_RULES; i++)
35 {
36 if (!s_bridge.rules[i].used)
37 {
38 s_bridge.rules[i] = *rule;
39 s_bridge.rules[i].used = true;
40 s_bridge.count++;
41 return true;
42 }
43 }
44 return false; // table full
45}
46
47bool bridge_map(const char *ip, uint16_t port, BridgeProto proto, const BridgeTarget *target)
48{
49 if (!target)
50 return false;
51 BridgeRule r;
52 memset(&r, 0, sizeof(r));
53 r.listen_ip.family = DetIpFamily::DET_IP_NONE; // "any interface" unless a valid address is given
54 if (ip && ip[0] && !det_ip_parse(ip, &r.listen_ip))
55 return false; // malformed bind address
56 r.listen_port = port;
57 r.proto = proto;
58 r.target = *target;
59 return bridge_add(&r);
60}
61
62const BridgeRule *bridge_find(uint16_t port, BridgeProto proto)
63{
64 for (uint8_t i = 0; i < DETWS_BRIDGE_MAX_RULES; i++)
65 if (s_bridge.rules[i].used && s_bridge.rules[i].listen_port == port && s_bridge.rules[i].proto == proto)
66 return &s_bridge.rules[i];
67 return nullptr;
68}
69
70uint8_t bridge_count()
71{
72 return s_bridge.count;
73}
74
75size_t bridge_txn_parse(const uint8_t *buf, size_t len, uint16_t *write_len, uint16_t *read_len,
76 const uint8_t **write_data)
77{
78 if (!buf || len < (size_t)DETWS_BRIDGE_TXN_HDR)
79 return 0;
80 uint16_t wl = (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]);
81 uint16_t rl = (uint16_t)(((uint16_t)buf[2] << 8) | buf[3]);
82 if (len < (size_t)DETWS_BRIDGE_TXN_HDR + wl)
83 return 0; // the write payload has not fully arrived yet
84 if (write_len)
85 *write_len = wl;
86 if (read_len)
87 *read_len = rl;
88 if (write_data)
89 *write_data = buf + DETWS_BRIDGE_TXN_HDR;
90 return (size_t)DETWS_BRIDGE_TXN_HDR + wl;
91}
92
93size_t bridge_txn_build(uint8_t *out, size_t cap, const uint8_t *write_data, uint16_t write_len, uint16_t read_len)
94{
95 size_t need = (size_t)DETWS_BRIDGE_TXN_HDR + write_len;
96 if (!out || cap < need)
97 return 0;
98 out[0] = (uint8_t)(write_len >> 8);
99 out[1] = (uint8_t)write_len;
100 out[2] = (uint8_t)(read_len >> 8);
101 out[3] = (uint8_t)read_len;
102 if (write_len && write_data)
103 memcpy(out + DETWS_BRIDGE_TXN_HDR, write_data, write_len);
104 return need;
105}
106
107#endif // DETWS_ENABLE_IFACE_BRIDGE
#define DETWS_BRIDGE_MAX_RULES
Max concurrent address:port -> bus rules (services/iface_bridge).
User-defined address:port -> hardware-bus translation (DETWS_ENABLE_IFACE_BRIDGE).
bool det_ip_parse(const char *s, DetIp *out)
Parse an IPv4 or IPv6 textual address (RFC 4291 §2.2) into out.
Definition ip.cpp:350
@ DET_IP_NONE
empty / unparsed