@@ -47,6 +47,7 @@ class UdpContext
4747 , _rx_buf(0 )
4848 , _first_buf_taken(false )
4949 , _rx_buf_offset(0 )
50+ , _rx_buf_size(0 )
5051 , _refcnt(0 )
5152 , _tx_buf_head(0 )
5253 , _tx_buf_cur(0 )
@@ -74,6 +75,7 @@ class UdpContext
7475 pbuf_free (_rx_buf);
7576 _rx_buf = 0 ;
7677 _rx_buf_offset = 0 ;
78+ _rx_buf_size = 0 ;
7779 }
7880 }
7981
@@ -202,12 +204,36 @@ class UdpContext
202204 _on_rx = handler;
203205 }
204206
207+ #ifdef DEBUG_ESP_CORE
208+ // this helper is ready to be used when debugging UDP
209+ void printChain (const pbuf* pb, const char * msg, size_t n) const
210+ {
211+ // printf the pb pbuf chain, bufferred and all at once
212+ char buf[128 ];
213+ int l = snprintf (buf, sizeof (buf), " UDP: %s %u: " , msg, n);
214+ while (pb)
215+ {
216+ l += snprintf (&buf[l], sizeof (buf) -l, " %p(H=%d,%d<=%d)-" ,
217+ pb, pb->flags == PBUF_HELPER_FLAG, pb->len , pb->tot_len );
218+ pb = pb->next ;
219+ }
220+ l += snprintf (&buf[l], sizeof (buf) - l, " (end)" );
221+ DEBUGV (" %s\n " , buf);
222+ }
223+ #else
224+ void printChain (const pbuf* pb, const char * msg) const
225+ {
226+ (void )pb;
227+ (void )msg;
228+ }
229+ #endif
230+
205231 size_t getSize () const
206232 {
207233 if (!_rx_buf)
208234 return 0 ;
209235
210- return _rx_buf-> tot_len - _rx_buf_offset;
236+ return _rx_buf_size - _rx_buf_offset;
211237 }
212238
213239 size_t tell () const
@@ -222,7 +248,7 @@ class UdpContext
222248 }
223249
224250 bool isValidOffset (const size_t pos) const {
225- return (pos <= _rx_buf-> tot_len );
251+ return (pos <= _rx_buf_size );
226252 }
227253
228254 netif* getInputNetif () const
@@ -262,47 +288,54 @@ class UdpContext
262288 return true ;
263289 }
264290
291+ // We have interleaved informations on addresses within received pbuf chain:
292+ // (before ipv6 code we had: (data-pbuf) -> (data-pbuf) -> (data-pbuf) -> ... in the receiving order)
293+ // Now: (address-info-pbuf -> chained-data-pbuf [-> chained-data-pbuf...]) ->
294+ // (chained-address-info-pbuf -> chained-data-pbuf [-> chained...]) -> ...
295+ // _rx_buf is currently adressing a data pbuf,
296+ // in this function it is going to be discarded.
297+
265298 auto deleteme = _rx_buf;
266299
267- while (_rx_buf->len != _rx_buf->tot_len )
300+ // forward in the chain until next address-info pbuf or end of chain
301+ while (_rx_buf && _rx_buf->flags != PBUF_HELPER_FLAG)
268302 _rx_buf = _rx_buf->next ;
269303
270- _rx_buf = _rx_buf->next ;
271-
272304 if (_rx_buf)
273305 {
274- if (_rx_buf->flags == PBUF_HELPER_FLAG)
275- {
276- // we have interleaved informations on addresses within reception pbuf chain:
277- // before: (data-pbuf) -> (data-pbuf) -> (data-pbuf) -> ... in the receiving order
278- // now: (address-info-pbuf -> data-pbuf) -> (address-info-pbuf -> data-pbuf) -> ...
306+ assert (_rx_buf->flags == PBUF_HELPER_FLAG);
279307
280- // so the first rx_buf contains an address helper,
281- // copy it to "current address"
282- auto helper = (AddrHelper*)PBUF_ALIGNER (_rx_buf->payload );
283- _currentAddr = *helper;
308+ // copy address helper to "current address"
309+ auto helper = (AddrHelper*)PBUF_ALIGNER (_rx_buf->payload );
310+ _currentAddr = *helper;
284311
285- // destroy the helper in the about-to-be-released pbuf
286- helper->~AddrHelper ();
312+ // destroy the helper in the about-to-be-released pbuf
313+ helper->~AddrHelper ();
287314
288- // forward in rx_buf list, next one is effective data
289- // current (not ref'ed) one will be pbuf_free'd with deleteme
290- _rx_buf = _rx_buf-> next ;
291- }
315+ // forward in rx_buf list, next one is effective data
316+ // current (not ref'ed) one will be pbuf_free'd
317+ // with the 'deleteme' pointer above
318+ _rx_buf = _rx_buf-> next ;
292319
293320 // this rx_buf is not nullptr by construction,
321+ assert (_rx_buf);
294322 // ref'ing it to prevent release from the below pbuf_free(deleteme)
323+ // (ref counter prevents release and will be decreased by pbuf_free)
295324 pbuf_ref (_rx_buf);
296325 }
326+
327+ // release in chain previous data, and if any:
328+ // current helper, but not start of current data
297329 pbuf_free (deleteme);
298330
299331 _rx_buf_offset = 0 ;
332+ _rx_buf_size = _processSize (_rx_buf);
300333 return _rx_buf != nullptr ;
301334 }
302335
303336 int read ()
304337 {
305- if (!_rx_buf || _rx_buf_offset >= _rx_buf-> tot_len )
338+ if (!_rx_buf || _rx_buf_offset >= _rx_buf_size )
306339 return -1 ;
307340
308341 char c = pbuf_get_at (_rx_buf, _rx_buf_offset);
@@ -315,9 +348,9 @@ class UdpContext
315348 if (!_rx_buf)
316349 return 0 ;
317350
318- size_t max_size = _rx_buf-> tot_len - _rx_buf_offset;
351+ size_t max_size = _rx_buf_size - _rx_buf_offset;
319352 size = (size < max_size) ? size : max_size;
320- DEBUGV (" :urd %d, %d, %d\r\n " , size, _rx_buf-> tot_len , _rx_buf_offset);
353+ DEBUGV (" :urd %d, %d, %d\r\n " , size, _rx_buf_size , _rx_buf_offset);
321354
322355 void * buf = pbuf_get_contiguous (_rx_buf, dst, size, size, _rx_buf_offset);
323356 if (!buf)
@@ -333,7 +366,7 @@ class UdpContext
333366
334367 int peek () const
335368 {
336- if (!_rx_buf || _rx_buf_offset == _rx_buf-> tot_len )
369+ if (!_rx_buf || _rx_buf_offset == _rx_buf_size )
337370 return -1 ;
338371
339372 return pbuf_get_at (_rx_buf, _rx_buf_offset);
@@ -345,7 +378,7 @@ class UdpContext
345378 if (!_rx_buf)
346379 return ;
347380
348- _consume (_rx_buf-> tot_len - _rx_buf_offset);
381+ _consume (_rx_buf_size - _rx_buf_offset);
349382 }
350383
351384 size_t append (const char * data, size_t size)
@@ -429,6 +462,14 @@ class UdpContext
429462
430463private:
431464
465+ size_t _processSize (const pbuf* pb)
466+ {
467+ size_t ret = 0 ;
468+ for (; pb && pb->flags != PBUF_HELPER_FLAG; pb = pb->next )
469+ ret += pb->len ;
470+ return ret;
471+ }
472+
432473 void _reserve (size_t size)
433474 {
434475 const size_t pbuf_unit_size = 128 ;
@@ -466,8 +507,8 @@ class UdpContext
466507 void _consume (size_t size)
467508 {
468509 _rx_buf_offset += size;
469- if (_rx_buf_offset > _rx_buf-> tot_len ) {
470- _rx_buf_offset = _rx_buf-> tot_len ;
510+ if (_rx_buf_offset > _rx_buf_size ) {
511+ _rx_buf_offset = _rx_buf_size ;
471512 }
472513 }
473514
@@ -476,6 +517,7 @@ class UdpContext
476517 {
477518 (void ) upcb;
478519 // check receive pbuf chain depth
520+ // optimization path: cache the pbuf chain length
479521 {
480522 pbuf* p;
481523 int count = 0 ;
@@ -488,6 +530,7 @@ class UdpContext
488530 return ;
489531 }
490532 }
533+
491534#if LWIP_VERSION_MAJOR == 1
492535 #define TEMPDSTADDR (¤t_iphdr_dest)
493536 #define TEMPINPUTNETIF (current_netif)
@@ -541,6 +584,7 @@ class UdpContext
541584 _first_buf_taken = false ;
542585 _rx_buf = pb;
543586 _rx_buf_offset = 0 ;
587+ _rx_buf_size = pb->tot_len ;
544588 }
545589
546590 if (_on_rx) {
@@ -648,6 +692,7 @@ class UdpContext
648692 pbuf* _rx_buf;
649693 bool _first_buf_taken;
650694 size_t _rx_buf_offset;
695+ size_t _rx_buf_size;
651696 int _refcnt;
652697 pbuf* _tx_buf_head;
653698 pbuf* _tx_buf_cur;
0 commit comments