Skip to content

Commit 1759edb

Browse files
committed
feat: basic udp_bridge class implementing Udp
1 parent 07a583a commit 1759edb

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

src/Arduino_RouterBridge.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
#include "monitor.h"
1818
#include "tcp_client.h"
1919
#include "tcp_server.h"
20+
#include "udp_bridge.h"
2021

2122
#endif //ARDUINO_ROUTER_BRIDGE_H

src/udp_bridge.h

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
This file is part of the Arduino_RouterBridge library.
3+
4+
Copyright (c) 2025 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
10+
*/
11+
12+
#pragma once
13+
14+
#ifndef UDP_BRIDGE_H
15+
#define UDP_BRIDGE_H
16+
17+
#define UDP_CONNECT_METHOD "udp/connect"
18+
#define UDP_CONNECT_MULTI_METHOD "udp/connectMulticast"
19+
#define UDP_CLOSE_METHOD "udp/close"
20+
#define UDP_WRITE_METHOD "udp/write"
21+
#define UDP_READ_METHOD "udp/read"
22+
23+
#include <zephyr/sys/atomic.h>
24+
#include <api/Udp.h>
25+
26+
class BridgeUDP final: public UDP {
27+
28+
BridgeClass* bridge;
29+
uint32_t connection_id{};
30+
RingBufferN<BufferSize> temp_buffer;
31+
struct k_mutex udp_mutex{};
32+
atomic_t _connected;
33+
34+
uint16_t _port; // local port to listen on
35+
36+
IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed
37+
uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed
38+
uint16_t _offset; // offset into the packet being sent
39+
uint16_t _remaining; // remaining bytes of incoming packet yet to be processed
40+
41+
public:
42+
43+
explicit BridgeUDP(BridgeClass& bridge): bridge(&bridge) {}
44+
45+
uint8_t begin(uint16_t port) override {
46+
47+
if (connected()) return 1;
48+
49+
if (!init()) {
50+
return 0;
51+
}
52+
53+
k_mutex_lock(&udp_mutex, K_FOREVER);
54+
_port = port;
55+
k_mutex_unlock(&udp_mutex);
56+
57+
return 1;
58+
}
59+
60+
uint8_t beginMulticast(IPAddress, uint16_t) override;
61+
62+
void stop() override {
63+
k_mutex_lock(&udp_mutex, K_FOREVER);
64+
65+
String msg;
66+
const bool resp = bridge->call(UDP_CLOSE_METHOD, msg, connection_id);
67+
if (resp) {
68+
atomic_set(&_connected, 0);
69+
}
70+
71+
k_mutex_unlock(&udp_mutex);
72+
}
73+
74+
int beginPacket(IPAddress ip, uint16_t port) override {
75+
return beginPacket(ip.toString().c_str(), port);
76+
}
77+
78+
int beginPacket(const char *host, uint16_t port) override {
79+
80+
k_mutex_lock(&udp_mutex, K_FOREVER);
81+
82+
String hostname = host;
83+
const bool resp = bridge->call(UDP_CONNECT_METHOD, connection_id, hostname, port);
84+
85+
if (!resp) {
86+
atomic_set(&_connected, 0);
87+
k_mutex_unlock(&udp_mutex);
88+
return 0;
89+
}
90+
atomic_set(&_connected, 1);
91+
92+
k_mutex_unlock(&udp_mutex);
93+
94+
return 1;
95+
}
96+
97+
int endPacket() override;
98+
99+
size_t write(uint8_t c) override {
100+
return write(&c, 1);
101+
}
102+
103+
size_t write(const uint8_t *buffer, size_t size) override;
104+
105+
using Print::write;
106+
107+
int parsePacket() override;
108+
109+
int available() override {
110+
k_mutex_lock(&udp_mutex, K_FOREVER);
111+
const int size = temp_buffer.availableForStore();
112+
if (size > 0) _read(size);
113+
const int _available = temp_buffer.available();
114+
k_mutex_unlock(&udp_mutex);
115+
return _available;
116+
}
117+
118+
int read() override;
119+
120+
int read(unsigned char *buffer, size_t len) override;
121+
122+
int read(char *buffer, size_t len) override;
123+
124+
int peek() override;
125+
126+
void flush() override;
127+
128+
IPAddress remoteIP() override;
129+
130+
uint16_t remotePort() override;
131+
132+
bool connected() const {
133+
return atomic_get(&_connected) > 0;
134+
}
135+
136+
private:
137+
138+
bool init() {
139+
k_mutex_init(&udp_mutex);
140+
if (!(*bridge)) {
141+
return bridge->begin();
142+
}
143+
return true;
144+
}
145+
146+
void _read(size_t size) {
147+
148+
if (size == 0 || !connected()) return;
149+
150+
k_mutex_lock(&udp_mutex, K_FOREVER);
151+
152+
MsgPack::arr_t<uint8_t> message;
153+
const bool ret = bridge->call(TCP_READ_METHOD, message, connection_id, size);
154+
155+
if (ret) {
156+
for (size_t i = 0; i < message.size(); ++i) {
157+
temp_buffer.store_char(static_cast<char>(message[i]));
158+
}
159+
}
160+
161+
if (bridge->get_last_client_error().code > NO_ERR) {
162+
atomic_set(&_connected, 0);
163+
}
164+
165+
k_mutex_unlock(&udp_mutex);
166+
}
167+
168+
};
169+
170+
#endif //UDP_BRIDGE_H

0 commit comments

Comments
 (0)