RF24Ethernet - TCP/IP over RF24Network v1.6.14
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Udp.cpp
Go to the documentation of this file.
1/*
2 RF24UDP.cpp - Arduino implementation of a uIP wrapper class.
3 Copyright (c) 2014 tmrh20@gmail.com, github.com/TMRh20
4 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
5 All rights reserved.
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20#include "RF24Ethernet.h"
21
22#if UIP_CONF_UDP > 0
23
24 #ifdef RF24ETHERNET_DEBUG_UDP
25 #include "HardwareSerial.h"
26 #endif
27
28 #if UIP_UDP
29 #define UIP_ARPHDRSIZE 42
30 #define UDPBUF ((struct uip_udpip_hdr*)&uip_buf[UIP_LLH_LEN])
31
32/*******************************************************/
33
34// Constructor
35RF24UDP::RF24UDP() : _uip_udp_conn(NULL)
36{
37 memset(&appdata, 0, sizeof(appdata));
38}
39
40/*******************************************************/
41
42// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
43uint8_t RF24UDP::begin(uint16_t port)
44{
45 if (!_uip_udp_conn)
46 {
47 _uip_udp_conn = uip_udp_new(NULL, 0);
48 }
49 if (_uip_udp_conn)
50 {
51 uip_udp_bind(_uip_udp_conn, htons(port));
52 _uip_udp_conn->appstate = &appdata;
53 return 1;
54 }
55 return 0;
56}
57
58/*******************************************************/
59
60// Finish with the UDP socket
61void RF24UDP::stop()
62{
63 if (_uip_udp_conn)
64 {
65 uip_udp_remove(_uip_udp_conn);
66 _uip_udp_conn->appstate = NULL;
67 _uip_udp_conn = NULL;
68 appdata.packet_in = 0;
69 appdata.packet_next = 0;
70 appdata.packet_out = 0;
71
72 memset(&appdata, 0, sizeof(appdata));
73 }
74}
75
76/*******************************************************/
77
78// Sending UDP packets
79
80// Start building up a packet to send to the remote host specific in ip and port
81// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
82int RF24UDP::beginPacket(IPAddress ip, uint16_t port)
83{
84 RF24EthernetClass::tick();
85 if (ip && port)
86 {
87 uip_ipaddr_t ripaddr;
88 uip_ip_addr(&ripaddr, ip);
89 IF_RF24ETHERNET_DEBUG_UDP(Serial.print(F("RF24UDP udp beginPacket, ")););
90
91 if (_uip_udp_conn)
92 {
93 _uip_udp_conn->rport = htons(port);
94 uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr);
95 }
96 else
97 {
98 _uip_udp_conn = uip_udp_new(&ripaddr, htons(port));
99 if (_uip_udp_conn)
100 {
101 IF_RF24ETHERNET_DEBUG_UDP(Serial.print(F("RF24UDP New connection, ")););
102 _uip_udp_conn->appstate = &appdata;
103 }
104 else
105 {
106 IF_RF24ETHERNET_DEBUG_UDP(Serial.println(F("RF24UDP Failed to allocate new connection")););
107 return 0;
108 }
109 }
110 IF_RF24ETHERNET_DEBUG_UDP(Serial.print(F("rip: ")); Serial.print(ip); Serial.print(F(", port: ")); Serial.println(port););
111 }
112
113 if (_uip_udp_conn)
114 {
115 if (appdata.packet_out == 0)
116 {
117 appdata.packet_out = 1;
118 appdata.out_pos = 0; // UIP_UDP_PHYH_LEN;
119 if (appdata.packet_out != 0)
120 {
121 return 1;
122 }
123 else
124 {
125 IF_RF24ETHERNET_DEBUG_UDP(Serial.println(F("RF24UDP Failed to allocate memory for packet")););
126 }
127 }
128 else
129 {
130 IF_RF24ETHERNET_DEBUG_UDP(Serial.println(F("RF24UDP Previous packet on that connection not sent yet")););
131 }
132 }
133 return 0;
134}
135
136/*******************************************************/
137
138// Start building up a packet to send to the remote host specific in host and port
139// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
140int RF24UDP::beginPacket(const char* host, uint16_t port)
141{
142 // Look up the host first
143 int ret = 0;
144 DNSClient dns;
145 IPAddress remote_addr;
146
147 dns.begin(RF24Ethernet.dnsServerIP());
148 ret = dns.getHostByName(host, remote_addr);
149 if (ret == 1)
150 {
151 return beginPacket(remote_addr, port);
152 }
153 else
154 {
155 return ret;
156 }
157}
158
159/*******************************************************/
160
161// Finish off this packet and send it
162// Returns 1 if the packet was sent successfully, 0 if there was an error
163int RF24UDP::endPacket()
164{
165 if (_uip_udp_conn && appdata.packet_out != 0)
166 {
167 appdata.send = true;
168 IF_RF24ETHERNET_DEBUG_UDP(Serial.println(F("RF24UDP endpacket")););
169 uip_udp_periodic_conn(_uip_udp_conn);
170 if (uip_len > 0)
171 {
172 _send(&appdata);
173 return 1;
174 }
175 }
176 return 0;
177}
178
179/*******************************************************/
180
181// Write a single byte into the packet
182size_t RF24UDP::write(uint8_t c)
183{
184 return write(&c, 1);
185}
186
187/*******************************************************/
188
189// Write size bytes from buffer into the packet
190size_t RF24UDP::write(const uint8_t* buffer, size_t size)
191{
192 if (appdata.packet_out != 0)
193 {
194 IF_RF24ETHERNET_DEBUG_UDP(Serial.println("RF24UDP Write: "); Serial.println(size); for (int i = 0; i < size; i++) { Serial.print((char)buffer[i]); Serial.print(" "); } Serial.println(""););
195 size_t ret = size;
196 memcpy(RF24Client::all_data[0].myData + appdata.out_pos, buffer, size);
197 appdata.out_pos += ret;
198 return ret;
199 }
200 return 0;
201}
202
203/*******************************************************/
204
205// Start processing the next available incoming packet
206// Returns the size of the packet in bytes, or 0 if no packets are available
207int RF24UDP::parsePacket()
208{
209
210 RF24EthernetClass::tick();
211 int size = appdata.packet_in_size;
212
213 IF_RF24ETHERNET_DEBUG_UDP(if (appdata.packet_in != 0) { Serial.print(F("RF24UDP udp parsePacket freeing previous packet: ")); Serial.println(appdata.packet_in); });
214
215 // appdata.packet_in_size = 0;
216
217 // appdata.packet_in = appdata.packet_next;
218 // appdata.packet_next = 0;
219
220 IF_RF24ETHERNET_DEBUG_UDP(if (appdata.packet_in != 0) { Serial.print(F("RF24UDP udp parsePacket received packet: ")); Serial.print(appdata.packet_in); } Serial.print(F(", size: ")); Serial.println(size););
221
222 return size;
223}
224
225/*******************************************************/
226
227// Number of bytes remaining in the current packet
228int RF24UDP::available()
229{
230 RF24EthernetClass::tick();
231 return appdata.packet_in_size;
232}
233
234/*******************************************************/
235
236// Read a single byte from the current packet
237int RF24UDP::read()
238{
239 unsigned char c;
240 if (read(&c, 1) > 0)
241 {
242 return c;
243 }
244 return -1;
245}
246
247/*******************************************************/
248
249// Read up to len bytes from the current packet and place them into buffer
250// Returns the number of bytes read, or 0 if none are available
251int RF24UDP::read(unsigned char* buffer, size_t len)
252{
253
254 RF24EthernetClass::tick();
255
256 if (appdata.packet_in != 0)
257 {
258 memcpy(buffer, RF24Client::all_data[0].myData + appdata.in_pos, len);
259 appdata.in_pos += len;
260 appdata.packet_in_size -= len;
261
262 if (appdata.packet_in_size < 1)
263 {
264 appdata.packet_in = 0;
265 }
266 return len;
267 }
268 return 0;
269}
270
271/*******************************************************/
272
273// Return the next byte from the current packet without moving on to the next byte
274int RF24UDP::peek()
275{
276
277 RF24EthernetClass::tick();
278
279 if (appdata.packet_in != 0)
280 {
281 return RF24Client::all_data[0].myData[appdata.in_pos];
282 }
283 return -1;
284}
285
286/*******************************************************/
287
288// Finish reading the current packet
289void RF24UDP::flush()
290{
291 appdata.packet_in = 0;
292 appdata.packet_in_size = 0;
293 RF24EthernetClass::tick();
294}
295
296/*******************************************************/
297
298// Return the IP address of the host who sent the current incoming packet
299IPAddress RF24UDP::remoteIP()
300{
301 return _uip_udp_conn ? ip_addr_uip(_uip_udp_conn->ripaddr) : IPAddress();
302}
303
304/*******************************************************/
305
306// Return the port of the host who sent the current incoming packet
307uint16_t RF24UDP::remotePort()
308{
309 return _uip_udp_conn ? ntohs(_uip_udp_conn->rport) : 0;
310}
311
312/*******************************************************/
313
314// uIP callback function
315
316void uipudp_appcall(void)
317{
318 if (uip_udp_userdata_t* data = (uip_udp_userdata_t*)(uip_udp_conn->appstate))
319 {
320 if (uip_newdata())
321 {
322 if (data->packet_next == 0)
323 {
324 uip_udp_conn->rport = UDPBUF->srcport;
325 uip_ipaddr_copy(uip_udp_conn->ripaddr, UDPBUF->srcipaddr);
326
327 // discard Linklevel and IP and udp-header and any trailing bytes:
328 memcpy(RF24Client::all_data[0].myData, uip_appdata, uip_len);
329 data->packet_in_size += uip_len;
330 data->packet_in = 1;
331
332 IF_RF24ETHERNET_DEBUG_UDP(Serial.print(F("RF24UDP udp, uip_newdata received packet: ")); Serial.print(data->packet_next); Serial.print(F(", size: ")); Serial.println(data->packet_in_size); for (int i = 0; i < data->packet_in_size; i++) { Serial.print(RF24Client::all_data[0].myData[i],HEX); Serial.print(F(" : ")); } Serial.println(););
333 }
334 }
335 if (uip_poll() && data->send)
336 {
337 // set uip_slen (uip private) by calling uip_udp_send
338 IF_RF24ETHERNET_DEBUG_UDP(Serial.print(F("udp, uip_poll preparing packet to send: ")); Serial.print(data->packet_out); Serial.print(F(", size: ")); Serial.println(data->out_pos););
339
340 memcpy(uip_appdata, RF24Client::all_data[0].myData, data->out_pos);
341 uip_udp_send(data->out_pos);
342 }
343 }
344}
345
346/*******************************************************/
347
348void RF24UDP::_send(uip_udp_userdata_t* data)
349{
350 #if defined(RF24_TAP)
351 uip_arp_out(); // add arp
352 #endif
353 if (uip_len == UIP_ARPHDRSIZE)
354 {
355 // RF24EthernetClass::uip_packet = 0;
356 // RF24EthernetClass::packetstate &= ~UIPETHERNET_SENDPACKET;
357
358 IF_RF24ETHERNET_DEBUG_UDP(Serial.println(F("udp, uip_poll results in ARP-packet")););
359 RF24EthernetClass::network_send();
360 }
361 else
362 {
363 // arp found ethaddr for ip (otherwise packet is replaced by arp-request)
364 data->send = false;
365 data->packet_out = 0;
366 // RF24EthernetClass::packetstate |= UIPETHERNET_SENDPACKET;
367 IF_RF24ETHERNET_DEBUG_UDP(Serial.println(data->out_pos); Serial.print(F("udp, uip_packet to send: ")); for (int i = 0; i < data->out_pos; i++) { Serial.print((char)RF24Client::all_data[0].myData[i]); } Serial.println(""););
368
369 RF24NetworkHeader headerOut(00, EXTERNAL_DATA_TYPE);
370 RF24Ethernet.network.write(headerOut, uip_buf, data->out_pos + UIP_UDP_PHYH_LEN);
371 }
372}
373
374 /*******************************************************/
375
376 #endif // UIP_UDP
377#endif // UDP Enabled
#define uip_ip_addr(addr, ip)
#define ip_addr_uip(a)
RF24EthernetClass RF24Ethernet
static uip_userdata_t all_data[UIP_CONNS]
Definition RF24Client.h:163
IPAddress dnsServerIP()
#define IF_RF24ETHERNET_DEBUG_UDP(x)
void uipudp_appcall(void)