@@ -28,9 +28,13 @@ extern "C" void esp_schedule();
28
28
29
29
#define GET_IP_HDR (pb ) reinterpret_cast <ip_hdr*>(((uint8_t *)((pb)->payload)) - UDP_HLEN - IP_HLEN);
30
30
#define GET_UDP_HDR (pb ) reinterpret_cast <udp_hdr*>(((uint8_t *)((pb)->payload)) - UDP_HLEN);
31
+
31
32
class UdpContext
32
33
{
33
34
public:
35
+
36
+ typedef std::function<void (void )> rxhandler_t ;
37
+
34
38
UdpContext ()
35
39
: _pcb(0 )
36
40
, _rx_buf(0 )
@@ -40,8 +44,11 @@ class UdpContext
40
44
, _tx_buf_head(0 )
41
45
, _tx_buf_cur(0 )
42
46
, _tx_buf_offset(0 )
47
+ , _multicast_ttl(1 )
48
+ , _dest_port(0 )
43
49
{
44
50
_pcb = udp_new ();
51
+ _dest_addr.addr = 0 ;
45
52
}
46
53
47
54
~UdpContext ()
@@ -79,8 +86,9 @@ class UdpContext
79
86
80
87
bool connect (ip_addr_t addr, uint16_t port)
81
88
{
82
- err_t err = udp_connect (_pcb, &addr, port);
83
- return err == ERR_OK;
89
+ _dest_addr = addr;
90
+ _dest_port = port;
91
+ return true ;
84
92
}
85
93
86
94
bool listen (ip_addr_t addr, uint16_t port)
@@ -107,7 +115,13 @@ class UdpContext
107
115
// newer versions of lwip have an additional field (mcast_ttl) for this purpose
108
116
// and a macro to set it instead of direct field access
109
117
// udp_set_multicast_ttl(_pcb, ttl);
110
- _pcb->ttl = ttl;
118
+ _multicast_ttl = ttl;
119
+ }
120
+
121
+ // warning: handler is called from tcp stack context
122
+ // esp_yield and non-reentrant functions which depend on it will fail
123
+ void onRx (rxhandler_t handler) {
124
+ _on_rx = handler;
111
125
}
112
126
113
127
size_t getSize () const
@@ -173,10 +187,10 @@ class UdpContext
173
187
return _rx_buf != 0 ;
174
188
}
175
189
176
- char read ()
190
+ int read ()
177
191
{
178
192
if (!_rx_buf || _rx_buf->len == _rx_buf_offset)
179
- return 0 ;
193
+ return - 1 ;
180
194
181
195
char c = reinterpret_cast <char *>(_rx_buf->payload )[_rx_buf_offset];
182
196
_consume (1 );
@@ -190,7 +204,7 @@ class UdpContext
190
204
191
205
size_t max_size = _rx_buf->len - _rx_buf_offset;
192
206
size = (size < max_size) ? size : max_size;
193
- DEBUGV (" :rd %d, %d, %d\r\n " , size, _rx_buf->len , _rx_buf_offset);
207
+ DEBUGV (" :urd %d, %d, %d\r\n " , size, _rx_buf->len , _rx_buf_offset);
194
208
195
209
os_memcpy (dst, reinterpret_cast <char *>(_rx_buf->payload ) + _rx_buf_offset, size);
196
210
_consume (size);
@@ -257,10 +271,19 @@ class UdpContext
257
271
}
258
272
}
259
273
260
- if (addr)
261
- udp_sendto (_pcb, _tx_buf_head, addr, port);
262
- else
263
- udp_send (_pcb, _tx_buf_head);
274
+ if (!addr) {
275
+ addr = &_dest_addr;
276
+ port = _dest_port;
277
+ }
278
+
279
+ uint16_t old_ttl = _pcb->ttl ;
280
+ if (ip_addr_ismulticast (addr)) {
281
+ _pcb->ttl = _multicast_ttl;
282
+ }
283
+
284
+ udp_sendto (_pcb, _tx_buf_head, addr, port);
285
+
286
+ _pcb->ttl = old_ttl;
264
287
265
288
for (pbuf* p = _tx_buf_head; p; p = p->next )
266
289
{
@@ -317,16 +340,19 @@ class UdpContext
317
340
{
318
341
// there is some unread data
319
342
// chain the new pbuf to the existing one
320
- DEBUGV (" :rch %d, %d\r\n " , _rx_buf->tot_len , pb->tot_len );
343
+ DEBUGV (" :urch %d, %d\r\n " , _rx_buf->tot_len , pb->tot_len );
321
344
pbuf_cat (_rx_buf, pb);
322
345
}
323
346
else
324
347
{
325
- DEBUGV (" :rn %d\r\n " , pb->tot_len );
348
+ DEBUGV (" :urn %d\r\n " , pb->tot_len );
326
349
_first_buf_taken = false ;
327
350
_rx_buf = pb;
328
351
_rx_buf_offset = 0 ;
329
352
}
353
+ if (_on_rx) {
354
+ _on_rx ();
355
+ }
330
356
}
331
357
332
358
@@ -341,13 +367,20 @@ class UdpContext
341
367
int _refcnt;
342
368
udp_pcb* _pcb;
343
369
370
+ ip_addr_t _dest_addr;
371
+ uint16_t _dest_port;
372
+
373
+ uint16_t _multicast_ttl;
374
+
344
375
bool _first_buf_taken;
345
376
pbuf* _rx_buf;
346
377
size_t _rx_buf_offset;
347
378
348
379
pbuf* _tx_buf_head;
349
380
pbuf* _tx_buf_cur;
350
381
size_t _tx_buf_offset;
382
+
383
+ rxhandler_t _on_rx;
351
384
};
352
385
353
386
0 commit comments