18#if DETWS_ENABLE_RADIO_POWER
46struct RelayListenerCtx
52RelayListenerCtx s_ctx;
54RelayBind *bind_by_listener(uint8_t lid)
57 if (s_ctx.binds[i].active && s_ctx.binds[i].listener_id == lid)
58 return &s_ctx.binds[i];
62RelayBridge *bridge_by_conn(uint8_t slot)
65 if (s_ctx.bridges[i].active && s_ctx.bridges[i].conn_slot == slot)
66 return &s_ctx.bridges[i];
73 if (!s_ctx.bridges[i].active)
80int a_recv(
void *c, uint8_t *buf,
size_t cap)
82 RelayBridge *br = (RelayBridge *)c;
83 if (det_conn_available(br->conn_slot))
84 return (
int)det_conn_read(br->conn_slot, buf, cap);
87int a_send(
void *c,
const uint8_t *buf,
size_t len)
89 RelayBridge *br = (RelayBridge *)c;
96 u16_t n = (len < (size_t)room) ? (u16_t)len : room;
100int b_recv(
void *c, uint8_t *buf,
size_t cap)
102 RelayBridge *br = (RelayBridge *)c;
108int b_send(
void *c,
const uint8_t *buf,
size_t len)
110 RelayBridge *br = (RelayBridge *)c;
116void teardown(RelayBridge *br,
bool close_inbound)
119#if DETWS_ENABLE_RADIO_POWER
120 detws_radio_busy_release();
128void service(uint8_t slot)
130 RelayBridge *br = bridge_by_conn(slot);
138 uint32_t moved = br->relay.bytes_a2b + br->relay.bytes_b2a;
139 DetRelayStatus st = det_relay_step(&br->relay);
140 if (st == DetRelayStatus::DET_RELAY_ERROR || st == DetRelayStatus::DET_RELAY_DONE)
145 if (br->relay.bytes_a2b + br->relay.bytes_b2a == moved)
150 br->relay.b2a_off >= br->relay.b2a_len)
154void relay_on_accept(uint8_t slot)
156 RelayBind *bd = bind_by_listener(det_conn_listener_id(slot));
162 int idx = bridge_find_free();
174 RelayBridge *br = &s_ctx.bridges[idx];
176 br->conn_slot = slot;
177 br->origin_cid = cid;
178 DetRelayEnd a = {a_recv, a_send,
nullptr, br};
179 DetRelayEnd b = {b_recv, b_send,
nullptr, br};
180 det_relay_init(&br->relay, &a, &b);
181#if DETWS_ENABLE_RADIO_POWER
182 detws_radio_busy_hold();
186void relay_on_data(uint8_t slot)
191void relay_on_poll(uint8_t slot)
193 if (!det_conn_active(slot))
198void relay_on_close(uint8_t slot)
200 RelayBridge *br = bridge_by_conn(slot);
205const ProtoHandler s_relay_handler = {relay_on_accept, relay_on_data, relay_on_close, relay_on_poll};
209bool det_relay_publish(uint8_t listener_id,
const char *origin_host, uint16_t origin_port)
218 if (!s_ctx.binds[i].active)
225 s_ctx.binds[idx].active =
true;
226 s_ctx.binds[idx].listener_id = listener_id;
227 memcpy(s_ctx.binds[idx].host, origin_host, hl + 1);
228 s_ctx.binds[idx].port = origin_port;
229 if (!s_ctx.registered)
232 s_ctx.registered =
true;
237void det_relay_listener_reset(
void)
240 s_ctx.binds[i].active =
false;
242 if (s_ctx.bridges[i].active)
244 s_ctx.bridges[i].active =
false;
245#if DETWS_ENABLE_RADIO_POWER
246 detws_radio_busy_release();
#define DETWS_RELAY_HOST_MAX
Max origin hostname length (bytes, incl. NUL) stored per published relay port.
@ PROTO_RELAY
TCP relay / DNAT (DETWS_ENABLE_RELAY): bridge to an origin det_client connection.
#define DETWS_RELAY_MAX_PUBLISH
Max published relay ports (bind table size) for the relay listener (DETWS_ENABLE_RELAY).
#define DETWS_RELAY_CONNECT_MS
Blocking connect timeout (ms) when the relay listener dials the origin on a new inbound.
#define DETWS_RELAY_MAX_CONNS
Max concurrent relayed connections (bridge table size) for the relay listener (DETWS_ENABLE_RELAY)....
#define DETWS_RELAY_DRAIN_MAX
Max det_relay_step passes per poll for the relay listener (DETWS_ENABLE_RELAY).
size_t det_client_available(int)
Wire bytes currently buffered and ready to read.
bool det_client_is_closed(int)
True once the peer closed (FIN) or the connection errored.
int det_client_open(const char *, uint16_t, uint32_t)
Resolve host (dotted-quad fast path, else DNS) and connect to host : port, blocking up to timeout_ms.
size_t det_client_read(int, uint8_t *, size_t)
Drain up to cap buffered wire bytes into buf; returns the count.
void det_client_close(int)
Tear down the connection (marshaled) and return the slot to the pool.
bool det_client_send(int, const void *, size_t)
Queue len wire bytes for transmission (marshaled tcp_write + output).
Layer 4 outbound TCP client transport - the client-side peer of the (server) transport in tcp....
Layer 5 (Session) - per-protocol connection handler dispatch table.
void proto_register(ConnProto proto, const ProtoHandler *h)
Register h for protocol proto (replaces any previous handler).
WiFi radio power controls (DETWS_ENABLE_RADIO_POWER).
TCP relay / DNAT port forwarding (DETWS_ENABLE_RELAY) - a bidirectional byte pump.
Server-side TCP relay / DNAT listener (DETWS_ENABLE_RELAY) - publish an internal host:port on a serve...
Per-protocol connection event/poll callbacks (Layer 5 dispatch vtable).
bool det_conn_send(uint8_t slot, const void *data, u16_t len)
Send len bytes on connection slot (copies data; TLS-aware).
u16_t det_conn_sndbuf(uint8_t slot)
Bytes that can currently be queued for sending on slot.
void det_conn_close(uint8_t slot)
Close connection slot gracefully (tcp_close), aborting if the FIN cannot be queued....
Layer 4 (Transport) - TCP connection pool, ring buffers, and lwIP integration.