@@ -187,7 +187,7 @@ class UdpContext
187187 if (!_rx_buf)
188188 return 0 ;
189189
190- return _rx_buf->len - _rx_buf_offset;
190+ return _rx_buf->tot_len - _rx_buf_offset;
191191 }
192192
193193 size_t tell () const
@@ -202,7 +202,7 @@ class UdpContext
202202 }
203203
204204 bool isValidOffset (const size_t pos) const {
205- return (pos <= _rx_buf->len );
205+ return (pos <= _rx_buf->tot_len );
206206 }
207207
208208 CONST IPAddress& getRemoteAddress () CONST
@@ -238,6 +238,10 @@ class UdpContext
238238 }
239239
240240 auto deleteme = _rx_buf;
241+
242+ while (_rx_buf->len != _rx_buf->tot_len )
243+ _rx_buf = _rx_buf->next ;
244+
241245 _rx_buf = _rx_buf->next ;
242246
243247 if (_rx_buf)
@@ -274,10 +278,10 @@ class UdpContext
274278
275279 int read ()
276280 {
277- if (!_rx_buf || _rx_buf_offset >= _rx_buf->len )
281+ if (!_rx_buf || _rx_buf_offset >= _rx_buf->tot_len )
278282 return -1 ;
279283
280- char c = reinterpret_cast < char *> (_rx_buf-> payload )[ _rx_buf_offset] ;
284+ char c = pbuf_get_at (_rx_buf, _rx_buf_offset) ;
281285 _consume (1 );
282286 return c;
283287 }
@@ -287,22 +291,28 @@ class UdpContext
287291 if (!_rx_buf)
288292 return 0 ;
289293
290- size_t max_size = _rx_buf->len - _rx_buf_offset;
294+ size_t max_size = _rx_buf->tot_len - _rx_buf_offset;
291295 size = (size < max_size) ? size : max_size;
292- DEBUGV (" :urd %d, %d, %d\r\n " , size, _rx_buf->len , _rx_buf_offset);
296+ DEBUGV (" :urd %d, %d, %d\r\n " , size, _rx_buf->tot_len , _rx_buf_offset);
297+
298+ void * buf = pbuf_get_contiguous (_rx_buf, dst, size, size, _rx_buf_offset);
299+ if (!buf)
300+ return 0 ;
301+
302+ if (buf != dst)
303+ memcpy (dst, buf, size);
293304
294- memcpy (dst, reinterpret_cast <char *>(_rx_buf->payload ) + _rx_buf_offset, size);
295305 _consume (size);
296306
297307 return size;
298308 }
299309
300310 int peek () const
301311 {
302- if (!_rx_buf || _rx_buf_offset == _rx_buf->len )
312+ if (!_rx_buf || _rx_buf_offset == _rx_buf->tot_len )
303313 return -1 ;
304314
305- return reinterpret_cast < char *> (_rx_buf-> payload )[ _rx_buf_offset] ;
315+ return pbuf_get_at (_rx_buf, _rx_buf_offset) ;
306316 }
307317
308318 void flush ()
@@ -311,7 +321,7 @@ class UdpContext
311321 if (!_rx_buf)
312322 return ;
313323
314- _consume (_rx_buf->len - _rx_buf_offset);
324+ _consume (_rx_buf->tot_len - _rx_buf_offset);
315325 }
316326
317327 size_t append (const char * data, size_t size)
@@ -432,8 +442,8 @@ class UdpContext
432442 void _consume (size_t size)
433443 {
434444 _rx_buf_offset += size;
435- if (_rx_buf_offset > _rx_buf->len ) {
436- _rx_buf_offset = _rx_buf->len ;
445+ if (_rx_buf_offset > _rx_buf->tot_len ) {
446+ _rx_buf_offset = _rx_buf->tot_len ;
437447 }
438448 }
439449
@@ -522,6 +532,90 @@ class UdpContext
522532 reinterpret_cast <UdpContext*>(arg)->_recv (upcb, p, srcaddr, srcport);
523533 }
524534
535+ #if LWIP_VERSION_MAJOR == 1
536+ /*
537+ * Code in this conditional block is copied/backported verbatim from
538+ * LwIP 2.1.2 to provide pbuf_get_contiguous.
539+ */
540+
541+ static const struct pbuf *
542+ pbuf_skip_const (const struct pbuf *in, u16_t in_offset, u16_t *out_offset)
543+ {
544+ u16_t offset_left = in_offset;
545+ const struct pbuf *pbuf_it = in;
546+
547+ /* get the correct pbuf */
548+ while ((pbuf_it != NULL ) && (pbuf_it->len <= offset_left)) {
549+ offset_left = (u16_t )(offset_left - pbuf_it->len );
550+ pbuf_it = pbuf_it->next ;
551+ }
552+ if (out_offset != NULL ) {
553+ *out_offset = offset_left;
554+ }
555+ return pbuf_it;
556+ }
557+
558+ u16_t
559+ pbuf_copy_partial (const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
560+ {
561+ const struct pbuf *p;
562+ u16_t left = 0 ;
563+ u16_t buf_copy_len;
564+ u16_t copied_total = 0 ;
565+
566+ LWIP_ERROR (" pbuf_copy_partial: invalid buf" , (buf != NULL ), return 0 ;);
567+ LWIP_ERROR (" pbuf_copy_partial: invalid dataptr" , (dataptr != NULL ), return 0 ;);
568+
569+ /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
570+ for (p = buf; len != 0 && p != NULL ; p = p->next ) {
571+ if ((offset != 0 ) && (offset >= p->len )) {
572+ /* don't copy from this buffer -> on to the next */
573+ offset = (u16_t )(offset - p->len );
574+ } else {
575+ /* copy from this buffer. maybe only partially. */
576+ buf_copy_len = (u16_t )(p->len - offset);
577+ if (buf_copy_len > len) {
578+ buf_copy_len = len;
579+ }
580+ /* copy the necessary parts of the buffer */
581+ MEMCPY (&((char *)dataptr)[left], &((char *)p->payload )[offset], buf_copy_len);
582+ copied_total = (u16_t )(copied_total + buf_copy_len);
583+ left = (u16_t )(left + buf_copy_len);
584+ len = (u16_t )(len - buf_copy_len);
585+ offset = 0 ;
586+ }
587+ }
588+ return copied_total;
589+ }
590+
591+ void *
592+ pbuf_get_contiguous (const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset)
593+ {
594+ const struct pbuf *q;
595+ u16_t out_offset;
596+
597+ LWIP_ERROR (" pbuf_get_contiguous: invalid buf" , (p != NULL ), return NULL ;);
598+ LWIP_ERROR (" pbuf_get_contiguous: invalid dataptr" , (buffer != NULL ), return NULL ;);
599+ LWIP_ERROR (" pbuf_get_contiguous: invalid dataptr" , (bufsize >= len), return NULL ;);
600+
601+ q = pbuf_skip_const (p, offset, &out_offset);
602+ if (q != NULL ) {
603+ if (q->len >= (out_offset + len)) {
604+ /* all data in this pbuf, return zero-copy */
605+ return (u8_t *)q->payload + out_offset;
606+ }
607+ /* need to copy */
608+ if (pbuf_copy_partial (q, buffer, len, out_offset) != len) {
609+ /* copying failed: pbuf is too short */
610+ return NULL ;
611+ }
612+ return buffer;
613+ }
614+ /* pbuf is too short (offset does not fit in) */
615+ return NULL ;
616+ }
617+ #endif
618+
525619private:
526620 udp_pcb* _pcb;
527621 pbuf* _rx_buf;
0 commit comments