Skip to content

Commit 946e69a

Browse files
authored
Merge pull request #14 from bcmi-labs/feature-packet-api
Implement packed based receive API for UDP packets.
2 parents e4d421d + b412186 commit 946e69a

File tree

4 files changed

+168
-54
lines changed

4 files changed

+168
-54
lines changed

Diff for: examples/UDP_Client/UDP_Client.ino

+19-8
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ static T1SMacSettings const t1s_default_mac_settings;
2929
static IPAddress const UDP_SERVER_IP_ADDR = {192, 168, 42, 100 + 0};
3030
static uint16_t const UDP_CLIENT_PORT = 8889;
3131
static uint16_t const UDP_SERVER_PORT = 8888;
32-
static uint8_t udp_tx_msg_buf[256] = {0};
33-
static uint8_t udp_rx_msg_buf[256] = {0};
3432

3533
/**************************************************************************************
3634
* GLOBAL VARIABLES
@@ -123,6 +121,7 @@ void loop()
123121
prev_udp_packet_sent = now;
124122

125123
/* Prepare UDP packet. */
124+
uint8_t udp_tx_msg_buf[256] = {0};
126125
int const tx_packet_size = snprintf((char *)udp_tx_msg_buf, sizeof(udp_tx_msg_buf), "Single-Pair Ethernet / 10BASE-T1S: packet cnt = %d", tx_packet_cnt);
127126

128127
/* Send a UDP packet to the UDP server. */
@@ -143,7 +142,7 @@ void loop()
143142
int const rx_packet_size = udp_client.parsePacket();
144143
if (rx_packet_size)
145144
{
146-
/* Receive incoming UDP packets. */
145+
/* Print some metadata from received UDP packet. */
147146
Serial.print("Received ");
148147
Serial.print(rx_packet_size);
149148
Serial.print(" bytes from ");
@@ -152,15 +151,27 @@ void loop()
152151
Serial.print(udp_client.remotePort());
153152
Serial.println();
154153

155-
int const bytes_read = udp_client.read(udp_rx_msg_buf, sizeof(udp_rx_msg_buf));
156-
if (bytes_read > 0) {
157-
udp_rx_msg_buf[bytes_read] = 0;
158-
}
159154
Serial.print("[");
160155
Serial.print(millis());
161156
Serial.print("] UDP_Client received packet content: \"");
162-
Serial.print(reinterpret_cast<char *>(udp_rx_msg_buf));
157+
158+
/* Read from received UDP packet. */
159+
size_t const UDP_RX_MSG_BUF_SIZE = 16 + 1; /* Reserve the last byte for the '\0' termination. */
160+
uint8_t udp_rx_msg_buf[UDP_RX_MSG_BUF_SIZE] = {0};
161+
int bytes_read = udp_client.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1);
162+
while(bytes_read != 0)
163+
{
164+
/* Print received data to Serial. */
165+
udp_rx_msg_buf[bytes_read] = '\0'; /* Terminate buffer so that we can print it as a C-string. */
166+
Serial.print(reinterpret_cast<char *>(udp_rx_msg_buf));
167+
168+
/* Continue reading. */
169+
bytes_read = udp_client.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1);
170+
}
163171
Serial.println("\"");
172+
173+
/* Finish reading the current packet. */
174+
udp_client.flush();
164175
}
165176
}
166177

Diff for: examples/UDP_Server/UDP_Server.ino

+32-12
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ static T1SPlcaSettings const t1s_plca_settings{T1S_PLCA_NODE_ID};
3333
static T1SMacSettings const t1s_default_mac_settings;
3434

3535
static uint16_t const UDP_SERVER_LOCAL_PORT = 8888;
36-
static uint8_t udp_rx_msg_buf[256] = {0};
3736

3837
/**************************************************************************************
3938
* GLOBAL VARIABLES
@@ -119,29 +118,50 @@ void loop()
119118
}
120119

121120
/* Check for incoming UDP packets. */
122-
int const packet_size = udp_server.parsePacket();
123-
if (packet_size)
121+
int const rx_packet_size = udp_server.parsePacket();
122+
if (rx_packet_size)
124123
{
125-
/* Receive incoming UDP packets. */
124+
std::vector<uint8_t> udp_tx_buf;
125+
IPAddress const destination_ip = udp_server.remoteIP();
126+
uint16_t const destination_port = udp_server.remotePort();
127+
128+
/* Print some metadata from received UDP packet. */
126129
Serial.print("Received ");
127-
Serial.print(packet_size);
130+
Serial.print(rx_packet_size);
128131
Serial.print(" bytes from ");
129132
Serial.print(udp_server.remoteIP());
130133
Serial.print(" port ");
131134
Serial.print(udp_server.remotePort());
132135
Serial.println();
133136

134-
int const bytes_read = udp_server.read(udp_rx_msg_buf, sizeof(udp_rx_msg_buf));
135-
if (bytes_read > 0) {
136-
udp_rx_msg_buf[bytes_read] = 0;
137+
Serial.print("[");
138+
Serial.print(millis());
139+
Serial.print("] UDP_Client received packet content: \"");
140+
141+
/* Read from received UDP packet. */
142+
size_t const UDP_RX_MSG_BUF_SIZE = 16 + 1; /* Reserve the last byte for the '\0' termination. */
143+
uint8_t udp_rx_msg_buf[UDP_RX_MSG_BUF_SIZE] = {0};
144+
int bytes_read = udp_server.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1);
145+
while(bytes_read != 0)
146+
{
147+
/* Copy received data into transmit buffer for echo functionality. */
148+
std::copy(udp_rx_msg_buf, udp_rx_msg_buf + bytes_read, std::back_inserter(udp_tx_buf));
149+
150+
/* Print received data to Serial. */
151+
udp_rx_msg_buf[bytes_read] = '\0'; /* Terminate buffer so that we can print it as a C-string. */
152+
Serial.print(reinterpret_cast<char *>(udp_rx_msg_buf));
153+
154+
/* Continue reading. */
155+
bytes_read = udp_server.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1);
137156
}
138-
Serial.print("UDP_Server received packet content: \"");
139-
Serial.print(reinterpret_cast<char *>(udp_rx_msg_buf));
140157
Serial.println("\"");
141158

159+
/* Finish reading the current packet. */
160+
udp_server.flush();
161+
142162
/* Send back a reply, to the IP address and port we got the packet from. */
143-
udp_server.beginPacket(udp_server.remoteIP(), udp_server.remotePort());
144-
udp_server.write((const uint8_t *)udp_rx_msg_buf, packet_size);
163+
udp_server.beginPacket(destination_ip, destination_port);
164+
udp_server.write(udp_tx_buf.data(), udp_tx_buf.size());
145165
udp_server.endPacket();
146166
}
147167
}

Diff for: src/Arduino_10BASE_T1S_UDP.cpp

+50-30
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ static void lwIp_udp_raw_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, co
2626

2727
Arduino_10BASE_T1S_UDP::Arduino_10BASE_T1S_UDP()
2828
: _udp_pcb{nullptr}
29-
, _remote_ip{0,0,0,0}
30-
, _remote_port{0}
3129
, _send_to_ip{0,0,0,0}
3230
, _send_to_port{0}
3331
{
@@ -131,77 +129,99 @@ size_t Arduino_10BASE_T1S_UDP::write(uint8_t data)
131129

132130
size_t Arduino_10BASE_T1S_UDP::write(const uint8_t * buffer, size_t size)
133131
{
134-
_tx_data.reserve(_tx_data.size() + size);
135132
std::copy(buffer, buffer + size, std::back_inserter(_tx_data));
136133
return size;
137134
}
138135

139136
int Arduino_10BASE_T1S_UDP::parsePacket()
140137
{
141-
return available();
138+
if (_rx_pkt_list.size())
139+
return _rx_pkt_list.front()->totalSize();
140+
else
141+
return 0;
142142
}
143143

144144
int Arduino_10BASE_T1S_UDP::available()
145145
{
146-
return _rx_data.size();
146+
if (_rx_pkt_list.size())
147+
return _rx_pkt_list.front()->available();
148+
else
149+
return 0;
147150
}
148151

149152
int Arduino_10BASE_T1S_UDP::read()
150153
{
151-
uint8_t const data = _rx_data.front();
152-
_rx_data.pop_front();
153-
return data;
154+
if (_rx_pkt_list.size())
155+
return _rx_pkt_list.front()->read();
156+
else
157+
return -1;
154158
}
155159

156160
int Arduino_10BASE_T1S_UDP::read(unsigned char* buffer, size_t len)
157161
{
158-
size_t bytes_read = 0;
159-
for (; bytes_read < len && !_rx_data.empty(); bytes_read++)
160-
{
161-
buffer[bytes_read] = _rx_data.front();
162-
_rx_data.pop_front();
163-
}
164-
return bytes_read;
162+
if (_rx_pkt_list.size())
163+
return _rx_pkt_list.front()->read(buffer, len);
164+
else
165+
return -1;
165166
}
166167

167168
int Arduino_10BASE_T1S_UDP::read(char* buffer, size_t len)
168169
{
169-
return read((unsigned char*)buffer, len);
170+
if (_rx_pkt_list.size())
171+
return _rx_pkt_list.front()->read(buffer, len);
172+
else
173+
return -1;
170174
}
171175

172176
int Arduino_10BASE_T1S_UDP::peek()
173177
{
174-
return _rx_data.front();
178+
if (_rx_pkt_list.size())
179+
return _rx_pkt_list.front()->peek();
180+
else
181+
return -1;
175182
}
176183

177184
void Arduino_10BASE_T1S_UDP::flush()
178185
{
179-
/* Nothing to be done. */
186+
/* Drop packet from receive buffer. */
187+
if (_rx_pkt_list.size())
188+
_rx_pkt_list.pop_front();
180189
}
181190

182191
IPAddress Arduino_10BASE_T1S_UDP::remoteIP()
183192
{
184-
return _remote_ip;
193+
if (_rx_pkt_list.size())
194+
return _rx_pkt_list.front()->remoteIP();
195+
else
196+
return IPAddress();
185197
}
186198

187199
uint16_t Arduino_10BASE_T1S_UDP::remotePort()
188200
{
189-
return _remote_port;
201+
if (_rx_pkt_list.size())
202+
return _rx_pkt_list.front()->remotePort();
203+
else
204+
return 0;
190205
}
191206

192207
void Arduino_10BASE_T1S_UDP::onUdpRawRecv(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, uint16_t port)
193208
{
194209
/* Obtain remote port and remote IP. */
195-
_remote_ip = IPAddress(ip4_addr1(addr),
196-
ip4_addr2(addr),
197-
ip4_addr3(addr),
198-
ip4_addr4(addr));
199-
_remote_port = port;
200-
201-
/* Copy data into buffer. */
202-
std::copy((uint8_t *)p->payload,
203-
(uint8_t *)p->payload + p->len,
204-
std::back_inserter(_rx_data));
210+
auto const remote_ip = IPAddress(
211+
ip4_addr1(addr),
212+
ip4_addr2(addr),
213+
ip4_addr3(addr),
214+
ip4_addr4(addr));
215+
auto const remote_port = port;
216+
217+
/* Create UDP object. */
218+
auto const rx_pkt = std::make_shared<UdpRxPacket>(
219+
remote_ip,
220+
remote_port,
221+
(uint8_t const *)p->payload,
222+
p->len);
223+
224+
_rx_pkt_list.push_back(rx_pkt);
205225

206226
/* Free pbuf */
207227
pbuf_free(p);

Diff for: src/Arduino_10BASE_T1S_UDP.h

+67-4
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
* INCLUDE
1515
**************************************************************************************/
1616

17+
#include <list>
1718
#include <deque>
1819
#include <vector>
20+
#include <memory>
1921

2022
#include <api/Udp.h>
2123
#include <api/IPAddress.h>
@@ -67,13 +69,74 @@ class Arduino_10BASE_T1S_UDP : public UDP
6769

6870

6971
private:
72+
/* LWIP */
7073
struct udp_pcb * _udp_pcb;
7174

72-
IPAddress _remote_ip;
73-
uint16_t _remote_port;
74-
std::deque<uint8_t> _rx_data;
75-
75+
/* UDP TRANSMISSION */
7676
IPAddress _send_to_ip;
7777
uint16_t _send_to_port;
7878
std::vector<uint8_t> _tx_data;
79+
80+
/* UDP RECEPTION */
81+
class UdpRxPacket
82+
{
83+
private:
84+
IPAddress const _remote_ip;
85+
uint16_t const _remote_port;
86+
size_t const _rx_data_len;
87+
std::deque<uint8_t> _rx_data;
88+
89+
public:
90+
UdpRxPacket(
91+
IPAddress const remote_ip,
92+
uint16_t const remote_port,
93+
uint8_t const * p_data,
94+
size_t const data_len)
95+
: _remote_ip(remote_ip)
96+
, _remote_port(remote_port)
97+
, _rx_data_len(data_len)
98+
, _rx_data(p_data, p_data + data_len)
99+
{
100+
}
101+
102+
typedef std::shared_ptr<UdpRxPacket> SharedPtr;
103+
104+
IPAddress remoteIP() const { return _remote_ip; }
105+
uint16_t remotePort() const { return _remote_port; }
106+
size_t totalSize() const { return _rx_data_len; }
107+
108+
int available()
109+
{
110+
return _rx_data.size();
111+
}
112+
113+
int read()
114+
{
115+
uint8_t const data = _rx_data.front();
116+
_rx_data.pop_front();
117+
return data;
118+
}
119+
120+
int read(unsigned char* buffer, size_t len)
121+
{
122+
size_t bytes_read = 0;
123+
for (; bytes_read < len && !_rx_data.empty(); bytes_read++)
124+
{
125+
buffer[bytes_read] = _rx_data.front();
126+
_rx_data.pop_front();
127+
}
128+
return bytes_read;
129+
}
130+
131+
int read(char* buffer, size_t len)
132+
{
133+
return read((unsigned char*)buffer, len);
134+
}
135+
136+
int peek()
137+
{
138+
return _rx_data.front();
139+
}
140+
};
141+
std::list<UdpRxPacket::SharedPtr> _rx_pkt_list;
79142
};

0 commit comments

Comments
 (0)