ReactOS 0.4.16-dev-340-g0540c21
pbuf.c
Go to the documentation of this file.
1
39/*
40 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without modification,
44 * are permitted provided that the following conditions are met:
45 *
46 * 1. Redistributions of source code must retain the above copyright notice,
47 * this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright notice,
49 * this list of conditions and the following disclaimer in the documentation
50 * and/or other materials provided with the distribution.
51 * 3. The name of the author may not be used to endorse or promote products
52 * derived from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
55 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
56 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
57 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
59 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
62 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
63 * OF SUCH DAMAGE.
64 *
65 * This file is part of the lwIP TCP/IP stack.
66 *
67 * Author: Adam Dunkels <adam@sics.se>
68 *
69 */
70
71#include "lwip/opt.h"
72
73#include "lwip/pbuf.h"
74#include "lwip/stats.h"
75#include "lwip/def.h"
76#include "lwip/mem.h"
77#include "lwip/memp.h"
78#include "lwip/sys.h"
79#include "lwip/netif.h"
80#if LWIP_TCP && TCP_QUEUE_OOSEQ
81#include "lwip/priv/tcp_priv.h"
82#endif
83#if LWIP_CHECKSUM_ON_COPY
84#include "lwip/inet_chksum.h"
85#endif
86
87#include <string.h>
88
89#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
90/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically
91 aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
92#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
93
94static const struct pbuf *
95pbuf_skip_const(const struct pbuf *in, u16_t in_offset, u16_t *out_offset);
96
97#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ
98#define PBUF_POOL_IS_EMPTY()
99#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */
100
101#if !NO_SYS
102#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
103#include "lwip/tcpip.h"
104#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \
105 if (tcpip_try_callback(pbuf_free_ooseq_callback, NULL) != ERR_OK) { \
106 SYS_ARCH_PROTECT(old_level); \
107 pbuf_free_ooseq_pending = 0; \
108 SYS_ARCH_UNPROTECT(old_level); \
109 } } while(0)
110#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
111#endif /* !NO_SYS */
112
113volatile u8_t pbuf_free_ooseq_pending;
114#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
115
124#if !NO_SYS
125static
126#endif /* !NO_SYS */
127void
128pbuf_free_ooseq(void)
129{
130 struct tcp_pcb *pcb;
131 SYS_ARCH_SET(pbuf_free_ooseq_pending, 0);
132
133 for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
134 if (pcb->ooseq != NULL) {
136 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
137 tcp_free_ooseq(pcb);
138 return;
139 }
140 }
141}
142
143#if !NO_SYS
147static void
148pbuf_free_ooseq_callback(void *arg)
149{
151 pbuf_free_ooseq();
152}
153#endif /* !NO_SYS */
154
156static void
157pbuf_pool_is_empty(void)
158{
159#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
160 SYS_ARCH_SET(pbuf_free_ooseq_pending, 1);
161#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
162 u8_t queued;
163 SYS_ARCH_DECL_PROTECT(old_level);
164 SYS_ARCH_PROTECT(old_level);
165 queued = pbuf_free_ooseq_pending;
166 pbuf_free_ooseq_pending = 1;
167 SYS_ARCH_UNPROTECT(old_level);
168
169 if (!queued) {
170 /* queue a call to pbuf_free_ooseq if not already queued */
171 PBUF_POOL_FREE_OOSEQ_QUEUE_CALL();
172 }
173#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
174}
175#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */
176
177/* Initialize members of struct pbuf after allocation */
178static void
179pbuf_init_alloced_pbuf(struct pbuf *p, void *payload, u16_t tot_len, u16_t len, pbuf_type type, u8_t flags)
180{
181 p->next = NULL;
182 p->payload = payload;
183 p->tot_len = tot_len;
184 p->len = len;
185 p->type_internal = (u8_t)type;
186 p->flags = flags;
187 p->ref = 1;
188 p->if_idx = NETIF_NO_INDEX;
189}
190
223struct pbuf *
225{
226 struct pbuf *p;
228 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
229
230 switch (type) {
231 case PBUF_REF: /* fall through */
232 case PBUF_ROM:
234 break;
235 case PBUF_POOL: {
236 struct pbuf *q, *last;
237 u16_t rem_len; /* remaining length */
238 p = NULL;
239 last = NULL;
240 rem_len = length;
241 do {
242 u16_t qlen;
243 q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
244 if (q == NULL) {
246 /* free chain so far allocated */
247 if (p) {
248 pbuf_free(p);
249 }
250 /* bail out unsuccessfully */
251 return NULL;
252 }
255 rem_len, qlen, type, 0);
256 LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
257 ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
258 LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT",
260 if (p == NULL) {
261 /* allocated head of pbuf chain (into p) */
262 p = q;
263 } else {
264 /* make previous pbuf point to this pbuf */
265 last->next = q;
266 }
267 last = q;
268 rem_len = (u16_t)(rem_len - qlen);
269 offset = 0;
270 } while (rem_len > 0);
271 break;
272 }
273 case PBUF_RAM: {
275 mem_size_t alloc_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF) + payload_len);
276
277 /* bug #50040: Check for integer overflow when calculating alloc_len */
278 if ((payload_len < LWIP_MEM_ALIGN_SIZE(length)) ||
279 (alloc_len < LWIP_MEM_ALIGN_SIZE(length))) {
280 return NULL;
281 }
282
283 /* If pbuf is to be allocated in RAM, allocate memory for it. */
284 p = (struct pbuf *)mem_malloc(alloc_len);
285 if (p == NULL) {
286 return NULL;
287 }
289 length, length, type, 0);
290 LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
291 ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
292 break;
293 }
294 default:
295 LWIP_ASSERT("pbuf_alloc: erroneous type", 0);
296 return NULL;
297 }
298 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
299 return p;
300}
301
326struct pbuf *
328{
329 struct pbuf *p;
330 LWIP_ASSERT("invalid pbuf_type", (type == PBUF_REF) || (type == PBUF_ROM));
331 /* only allocate memory for the pbuf structure */
332 p = (struct pbuf *)memp_malloc(MEMP_PBUF);
333 if (p == NULL) {
335 ("pbuf_alloc_reference: Could not allocate MEMP_PBUF for PBUF_%s.\n",
336 (type == PBUF_ROM) ? "ROM" : "REF"));
337 return NULL;
338 }
340 return p;
341}
342
343
344#if LWIP_SUPPORT_CUSTOM_PBUF
362struct pbuf *
363pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p,
364 void *payload_mem, u16_t payload_mem_len)
365{
366 u16_t offset = (u16_t)l;
367 void *payload;
368 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
369
370 if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) {
371 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length));
372 return NULL;
373 }
374
375 if (payload_mem != NULL) {
376 payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset);
377 } else {
378 payload = NULL;
379 }
381 return &p->pbuf;
382}
383#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
384
401void
402pbuf_realloc(struct pbuf *p, u16_t new_len)
403{
404 struct pbuf *q;
405 u16_t rem_len; /* remaining length */
406 u16_t shrink;
407
408 LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL);
409
410 /* desired length larger than current length? */
411 if (new_len >= p->tot_len) {
412 /* enlarging not yet supported */
413 return;
414 }
415
416 /* the pbuf chain grows by (new_len - p->tot_len) bytes
417 * (which may be negative in case of shrinking) */
418 shrink = (u16_t)(p->tot_len - new_len);
419
420 /* first, step over any pbufs that should remain in the chain */
421 rem_len = new_len;
422 q = p;
423 /* should this pbuf be kept? */
424 while (rem_len > q->len) {
425 /* decrease remaining length by pbuf length */
426 rem_len = (u16_t)(rem_len - q->len);
427 /* decrease total length indicator */
428 q->tot_len = (u16_t)(q->tot_len - shrink);
429 /* proceed to next pbuf in chain */
430 q = q->next;
431 LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL);
432 }
433 /* we have now reached the new last pbuf (in q) */
434 /* rem_len == desired length for pbuf q */
435
436 /* shrink allocated memory for PBUF_RAM */
437 /* (other types merely adjust their length fields */
440 && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0)
441#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
442 ) {
443 /* reallocate and adjust the length of the pbuf that will be split */
444 struct pbuf *r = (struct pbuf *)mem_trim(q, (mem_size_t)(((u8_t *)q->payload - (u8_t *)q) + rem_len));
445 LWIP_ASSERT("mem_trim returned r == NULL", r != NULL);
446 /* help to detect faulty overridden implementation of mem_trim */
447 LWIP_ASSERT("mem_trim returned r != q", r == q);
449 }
450 /* adjust length fields for new last pbuf */
451 q->len = rem_len;
452 q->tot_len = q->len;
453
454 /* any remaining pbufs in chain? */
455 if (q->next != NULL) {
456 /* free remaining pbufs in chain */
457 pbuf_free(q->next);
458 }
459 /* q is last packet in chain */
460 q->next = NULL;
461
462}
463
475static u8_t
476pbuf_add_header_impl(struct pbuf *p, size_t header_size_increment, u8_t force)
477{
479 void *payload;
480 u16_t increment_magnitude;
481
482 LWIP_ASSERT("p != NULL", p != NULL);
483 if ((p == NULL) || (header_size_increment > 0xFFFF)) {
484 return 1;
485 }
486 if (header_size_increment == 0) {
487 return 0;
488 }
489
490 increment_magnitude = (u16_t)header_size_increment;
491 /* Do not allow tot_len to wrap as a result. */
492 if ((u16_t)(increment_magnitude + p->tot_len) < increment_magnitude) {
493 return 1;
494 }
495
496 type_internal = p->type_internal;
497
498 /* pbuf types containing payloads? */
500 /* set new payload pointer */
501 payload = (u8_t *)p->payload - header_size_increment;
502 /* boundary check fails? */
503 if ((u8_t *)payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) {
505 ("pbuf_add_header: failed as %p < %p (not enough space for new header size)\n",
506 (void *)payload, (void *)((u8_t *)p + SIZEOF_STRUCT_PBUF)));
507 /* bail out unsuccessfully */
508 return 1;
509 }
510 /* pbuf types referring to external payloads? */
511 } else {
512 /* hide a header in the payload? */
513 if (force) {
514 payload = (u8_t *)p->payload - header_size_increment;
515 } else {
516 /* cannot expand payload to front (yet!)
517 * bail out unsuccessfully */
518 return 1;
519 }
520 }
521 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_add_header: old %p new %p (%"U16_F")\n",
522 (void *)p->payload, (void *)payload, increment_magnitude));
523
524 /* modify pbuf fields */
525 p->payload = payload;
526 p->len = (u16_t)(p->len + increment_magnitude);
527 p->tot_len = (u16_t)(p->tot_len + increment_magnitude);
528
529
530 return 0;
531}
532
553u8_t
554pbuf_add_header(struct pbuf *p, size_t header_size_increment)
555{
556 return pbuf_add_header_impl(p, header_size_increment, 0);
557}
558
563u8_t
564pbuf_add_header_force(struct pbuf *p, size_t header_size_increment)
565{
566 return pbuf_add_header_impl(p, header_size_increment, 1);
567}
568
584u8_t
585pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
586{
587 void *payload;
588 u16_t increment_magnitude;
589
590 LWIP_ASSERT("p != NULL", p != NULL);
591 if ((p == NULL) || (header_size_decrement > 0xFFFF)) {
592 return 1;
593 }
594 if (header_size_decrement == 0) {
595 return 0;
596 }
597
598 increment_magnitude = (u16_t)header_size_decrement;
599 /* Check that we aren't going to move off the end of the pbuf */
600 LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
601
602 /* remember current payload pointer */
603 payload = p->payload;
604 LWIP_UNUSED_ARG(payload); /* only used in LWIP_DEBUGF below */
605
606 /* increase payload pointer (guarded by length check above) */
607 p->payload = (u8_t *)p->payload + header_size_decrement;
608 /* modify pbuf length fields */
609 p->len = (u16_t)(p->len - increment_magnitude);
610 p->tot_len = (u16_t)(p->tot_len - increment_magnitude);
611
612 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_remove_header: old %p new %p (%"U16_F")\n",
613 (void *)payload, (void *)p->payload, increment_magnitude));
614
615 return 0;
616}
617
618static u8_t
619pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
620{
621 if (header_size_increment < 0) {
622 return pbuf_remove_header(p, (size_t) - header_size_increment);
623 } else {
624 return pbuf_add_header_impl(p, (size_t)header_size_increment, force);
625 }
626}
627
648u8_t
649pbuf_header(struct pbuf *p, s16_t header_size_increment)
650{
651 return pbuf_header_impl(p, header_size_increment, 0);
652}
653
658u8_t
659pbuf_header_force(struct pbuf *p, s16_t header_size_increment)
660{
661 return pbuf_header_impl(p, header_size_increment, 1);
662}
663
673struct pbuf *
675{
676 struct pbuf *p = q;
677 u16_t free_left = size;
678 while (free_left && p) {
679 if (free_left >= p->len) {
680 struct pbuf *f = p;
681 free_left = (u16_t)(free_left - p->len);
682 p = p->next;
683 f->next = NULL;
684 pbuf_free(f);
685 } else {
686 pbuf_remove_header(p, free_left);
687 free_left = 0;
688 }
689 }
690 return p;
691}
692
726u8_t
728{
729 u8_t alloc_src;
730 struct pbuf *q;
731 u8_t count;
732
733 if (p == NULL) {
734 LWIP_ASSERT("p != NULL", p != NULL);
735 /* if assertions are disabled, proceed with debug output */
737 ("pbuf_free(p == NULL) was called.\n"));
738 return 0;
739 }
740 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
741
743
744 count = 0;
745 /* de-allocate all consecutive pbufs from the head of the chain that
746 * obtain a zero reference count after decrementing*/
747 while (p != NULL) {
749 SYS_ARCH_DECL_PROTECT(old_level);
750 /* Since decrementing ref cannot be guaranteed to be a single machine operation
751 * we must protect it. We put the new ref into a local variable to prevent
752 * further protection. */
753 SYS_ARCH_PROTECT(old_level);
754 /* all pbufs in a chain are referenced at least once */
755 LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
756 /* decrease reference count (number of pointers to pbuf) */
757 ref = --(p->ref);
758 SYS_ARCH_UNPROTECT(old_level);
759 /* this pbuf is no longer referenced to? */
760 if (ref == 0) {
761 /* remember next pbuf in chain for next iteration */
762 q = p->next;
763 LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
764 alloc_src = pbuf_get_allocsrc(p);
765#if LWIP_SUPPORT_CUSTOM_PBUF
766 /* is this a custom pbuf? */
767 if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
768 struct pbuf_custom *pc = (struct pbuf_custom *)p;
769 LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
770 pc->custom_free_function(p);
771 } else
772#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
773 {
774 /* is this a pbuf from the pool? */
776 memp_free(MEMP_PBUF_POOL, p);
777 /* is this a ROM or RAM referencing pbuf? */
778 } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) {
779 memp_free(MEMP_PBUF, p);
780 /* type == PBUF_RAM */
781 } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) {
782 mem_free(p);
783 } else {
784 /* @todo: support freeing other types */
785 LWIP_ASSERT("invalid pbuf type", 0);
786 }
787 }
788 count++;
789 /* proceed to next pbuf */
790 p = q;
791 /* p->ref > 0, this pbuf is still referenced to */
792 /* (and so the remaining pbufs in chain as well) */
793 } else {
794 LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)ref));
795 /* stop walking through the chain */
796 p = NULL;
797 }
798 }
799 PERF_STOP("pbuf_free");
800 /* return number of de-allocated pbufs */
801 return count;
802}
803
810u16_t
811pbuf_clen(const struct pbuf *p)
812{
813 u16_t len;
814
815 len = 0;
816 while (p != NULL) {
817 ++len;
818 p = p->next;
819 }
820 return len;
821}
822
830void
832{
833 /* pbuf given? */
834 if (p != NULL) {
835 SYS_ARCH_SET(p->ref, (LWIP_PBUF_REF_T)(p->ref + 1));
836 LWIP_ASSERT("pbuf ref overflow", p->ref > 0);
837 }
838}
839
854void
855pbuf_cat(struct pbuf *h, struct pbuf *t)
856{
857 struct pbuf *p;
858
859 LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)",
860 ((h != NULL) && (t != NULL)), return;);
861
862 /* proceed to last pbuf of chain */
863 for (p = h; p->next != NULL; p = p->next) {
864 /* add total length of second chain to all totals of first chain */
865 p->tot_len = (u16_t)(p->tot_len + t->tot_len);
866 }
867 /* { p is last pbuf of first h chain, p->next == NULL } */
868 LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
869 LWIP_ASSERT("p->next == NULL", p->next == NULL);
870 /* add total length of second chain to last pbuf total of first chain */
871 p->tot_len = (u16_t)(p->tot_len + t->tot_len);
872 /* chain last pbuf of head (p) with first of tail (t) */
873 p->next = t;
874 /* p->next now references t, but the caller will drop its reference to t,
875 * so netto there is no change to the reference count of t.
876 */
877}
878
896void
897pbuf_chain(struct pbuf *h, struct pbuf *t)
898{
899 pbuf_cat(h, t);
900 /* t is now referenced by h */
901 pbuf_ref(t);
902 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
903}
904
913struct pbuf *
915{
916 struct pbuf *q;
917 u8_t tail_gone = 1;
918 /* tail */
919 q = p->next;
920 /* pbuf has successor in chain? */
921 if (q != NULL) {
922 /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
923 LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
924 /* enforce invariant if assertion is disabled */
925 q->tot_len = (u16_t)(p->tot_len - p->len);
926 /* decouple pbuf from remainder */
927 p->next = NULL;
928 /* total length of pbuf p is its own length only */
929 p->tot_len = p->len;
930 /* q is no longer referenced by p, free it */
931 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
932 tail_gone = pbuf_free(q);
933 if (tail_gone > 0) {
935 ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
936 }
937 /* return remaining tail or NULL if deallocated */
938 }
939 /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
940 LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
941 return ((tail_gone > 0) ? NULL : q);
942}
943
958err_t
959pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
960{
961 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
962 (const void *)p_to, (const void *)p_from));
963
964 LWIP_ERROR("pbuf_copy: invalid source", p_from != NULL, return ERR_ARG;);
965 return pbuf_copy_partial_pbuf(p_to, p_from, p_from->tot_len, 0);
966}
967
985err_t
986pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
987{
988 size_t offset_to = offset, offset_from = 0, len;
989
990 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf(%p, %p, %"U16_F", %"U16_F")\n",
991 (const void *)p_to, (const void *)p_from, copy_len, offset));
992
993 /* is the copy_len in range? */
994 LWIP_ERROR("pbuf_copy_partial_pbuf: copy_len bigger than source", ((p_from != NULL) &&
995 (p_from->tot_len >= copy_len)), return ERR_ARG;);
996 /* is the target big enough to hold the source? */
997 LWIP_ERROR("pbuf_copy_partial_pbuf: target not big enough", ((p_to != NULL) &&
998 (p_to->tot_len >= (offset + copy_len))), return ERR_ARG;);
999
1000 /* iterate through pbuf chain */
1001 do {
1002 /* copy one part of the original chain */
1003 if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
1004 /* complete current p_from fits into current p_to */
1005 len = p_from->len - offset_from;
1006 } else {
1007 /* current p_from does not fit into current p_to */
1008 len = p_to->len - offset_to;
1009 }
1010 len = LWIP_MIN(copy_len, len);
1011 MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len);
1012 offset_to += len;
1013 offset_from += len;
1014 copy_len = (u16_t)(copy_len - len);
1015 LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
1016 LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
1017 if (offset_from >= p_from->len) {
1018 /* on to next p_from (if any) */
1019 offset_from = 0;
1020 p_from = p_from->next;
1021 LWIP_ERROR("p_from != NULL", (p_from != NULL) || (copy_len == 0), return ERR_ARG;);
1022 }
1023 if (offset_to == p_to->len) {
1024 /* on to next p_to (if any) */
1025 offset_to = 0;
1026 p_to = p_to->next;
1027 LWIP_ERROR("p_to != NULL", (p_to != NULL) || (copy_len == 0), return ERR_ARG;);
1028 }
1029
1030 if ((p_from != NULL) && (p_from->len == p_from->tot_len)) {
1031 /* don't copy more than one packet! */
1032 LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
1033 (p_from->next == NULL), return ERR_VAL;);
1034 }
1035 if ((p_to != NULL) && (p_to->len == p_to->tot_len)) {
1036 /* don't copy more than one packet! */
1037 LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
1038 (p_to->next == NULL), return ERR_VAL;);
1039 }
1040 } while (copy_len);
1041 LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf: copy complete.\n"));
1042 return ERR_OK;
1043}
1044
1057u16_t
1059{
1060 const struct pbuf *p;
1061 u16_t left = 0;
1062 u16_t buf_copy_len;
1063 u16_t copied_total = 0;
1064
1065 LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
1066 LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
1067
1068 /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
1069 for (p = buf; len != 0 && p != NULL; p = p->next) {
1070 if ((offset != 0) && (offset >= p->len)) {
1071 /* don't copy from this buffer -> on to the next */
1072 offset = (u16_t)(offset - p->len);
1073 } else {
1074 /* copy from this buffer. maybe only partially. */
1075 buf_copy_len = (u16_t)(p->len - offset);
1076 if (buf_copy_len > len) {
1077 buf_copy_len = len;
1078 }
1079 /* copy the necessary parts of the buffer */
1080 MEMCPY(&((char *)dataptr)[left], &((char *)p->payload)[offset], buf_copy_len);
1081 copied_total = (u16_t)(copied_total + buf_copy_len);
1082 left = (u16_t)(left + buf_copy_len);
1083 len = (u16_t)(len - buf_copy_len);
1084 offset = 0;
1085 }
1086 }
1087 return copied_total;
1088}
1089
1104void *
1106{
1107 const struct pbuf *q;
1108 u16_t out_offset;
1109
1110 LWIP_ERROR("pbuf_get_contiguous: invalid buf", (p != NULL), return NULL;);
1111 LWIP_ERROR("pbuf_get_contiguous: invalid dataptr", (buffer != NULL), return NULL;);
1112 LWIP_ERROR("pbuf_get_contiguous: invalid dataptr", (bufsize >= len), return NULL;);
1113
1114 q = pbuf_skip_const(p, offset, &out_offset);
1115 if (q != NULL) {
1116 if (q->len >= (out_offset + len)) {
1117 /* all data in this pbuf, return zero-copy */
1118 return (u8_t *)q->payload + out_offset;
1119 }
1120 /* need to copy */
1121 if (pbuf_copy_partial(q, buffer, len, out_offset) != len) {
1122 /* copying failed: pbuf is too short */
1123 return NULL;
1124 }
1125 return buffer;
1126 }
1127 /* pbuf is too short (offset does not fit in) */
1128 return NULL;
1129}
1130
1131#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
1144void pbuf_split_64k(struct pbuf *p, struct pbuf **rest)
1145{
1146 *rest = NULL;
1147 if ((p != NULL) && (p->next != NULL)) {
1148 u16_t tot_len_front = p->len;
1149 struct pbuf *i = p;
1150 struct pbuf *r = p->next;
1151
1152 /* continue until the total length (summed up as u16_t) overflows */
1153 while ((r != NULL) && ((u16_t)(tot_len_front + r->len) >= tot_len_front)) {
1154 tot_len_front = (u16_t)(tot_len_front + r->len);
1155 i = r;
1156 r = r->next;
1157 }
1158 /* i now points to last packet of the first segment. Set next
1159 pointer to NULL */
1160 i->next = NULL;
1161
1162 if (r != NULL) {
1163 /* Update the tot_len field in the first part */
1164 for (i = p; i != NULL; i = i->next) {
1165 i->tot_len = (u16_t)(i->tot_len - r->tot_len);
1166 LWIP_ASSERT("tot_len/len mismatch in last pbuf",
1167 (i->next != NULL) || (i->tot_len == i->len));
1168 }
1169 if (p->flags & PBUF_FLAG_TCP_FIN) {
1170 r->flags |= PBUF_FLAG_TCP_FIN;
1171 }
1172
1173 /* tot_len field in rest does not need modifications */
1174 /* reference counters do not need modifications */
1175 *rest = r;
1176 }
1177 }
1178}
1179#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
1180
1181/* Actual implementation of pbuf_skip() but returning const pointer... */
1182static const struct pbuf *
1183pbuf_skip_const(const struct pbuf *in, u16_t in_offset, u16_t *out_offset)
1184{
1185 u16_t offset_left = in_offset;
1186 const struct pbuf *q = in;
1187
1188 /* get the correct pbuf */
1189 while ((q != NULL) && (q->len <= offset_left)) {
1190 offset_left = (u16_t)(offset_left - q->len);
1191 q = q->next;
1192 }
1193 if (out_offset != NULL) {
1194 *out_offset = offset_left;
1195 }
1196 return q;
1197}
1198
1208struct pbuf *
1209pbuf_skip(struct pbuf *in, u16_t in_offset, u16_t *out_offset)
1210{
1211 const struct pbuf *out = pbuf_skip_const(in, in_offset, out_offset);
1212 return LWIP_CONST_CAST(struct pbuf *, out);
1213}
1214
1226err_t
1227pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
1228{
1229 struct pbuf *p;
1230 size_t buf_copy_len;
1231 size_t total_copy_len = len;
1232 size_t copied_total = 0;
1233
1234 LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return ERR_ARG;);
1235 LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
1236 LWIP_ERROR("pbuf_take: buf not large enough", (buf->tot_len >= len), return ERR_MEM;);
1237
1238 if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {
1239 return ERR_ARG;
1240 }
1241
1242 /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
1243 for (p = buf; total_copy_len != 0; p = p->next) {
1244 LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);
1245 buf_copy_len = total_copy_len;
1246 if (buf_copy_len > p->len) {
1247 /* this pbuf cannot hold all remaining data */
1248 buf_copy_len = p->len;
1249 }
1250 /* copy the necessary parts of the buffer */
1251 MEMCPY(p->payload, &((const char *)dataptr)[copied_total], buf_copy_len);
1252 total_copy_len -= buf_copy_len;
1253 copied_total += buf_copy_len;
1254 }
1255 LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);
1256 return ERR_OK;
1257}
1258
1270err_t
1272{
1273 u16_t target_offset;
1274 struct pbuf *q = pbuf_skip(buf, offset, &target_offset);
1275
1276 /* return requested data if pbuf is OK */
1277 if ((q != NULL) && (q->tot_len >= target_offset + len)) {
1278 u16_t remaining_len = len;
1279 const u8_t *src_ptr = (const u8_t *)dataptr;
1280 /* copy the part that goes into the first pbuf */
1281 u16_t first_copy_len;
1282 LWIP_ASSERT("check pbuf_skip result", target_offset < q->len);
1283 first_copy_len = (u16_t)LWIP_MIN(q->len - target_offset, len);
1284 MEMCPY(((u8_t *)q->payload) + target_offset, dataptr, first_copy_len);
1285 remaining_len = (u16_t)(remaining_len - first_copy_len);
1286 src_ptr += first_copy_len;
1287 if (remaining_len > 0) {
1288 return pbuf_take(q->next, src_ptr, remaining_len);
1289 }
1290 return ERR_OK;
1291 }
1292 return ERR_MEM;
1293}
1294
1308struct pbuf *
1310{
1311 struct pbuf *q;
1312 if (p->next == NULL) {
1313 return p;
1314 }
1316 if (q == NULL) {
1317 /* @todo: what do we do now? */
1318 return p;
1319 }
1320 pbuf_free(p);
1321 return q;
1322}
1323
1336struct pbuf *
1338{
1339 struct pbuf *q;
1340 err_t err;
1341 q = pbuf_alloc(layer, p->tot_len, type);
1342 if (q == NULL) {
1343 return NULL;
1344 }
1345 err = pbuf_copy(q, p);
1346 LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
1347 LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
1348 return q;
1349}
1350
1351#if LWIP_CHECKSUM_ON_COPY
1364err_t
1365pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
1366 u16_t len, u16_t *chksum)
1367{
1368 u32_t acc;
1369 u16_t copy_chksum;
1370 char *dst_ptr;
1371 LWIP_ASSERT("p != NULL", p != NULL);
1372 LWIP_ASSERT("dataptr != NULL", dataptr != NULL);
1373 LWIP_ASSERT("chksum != NULL", chksum != NULL);
1374 LWIP_ASSERT("len != 0", len != 0);
1375
1376 if ((start_offset >= p->len) || (start_offset + len > p->len)) {
1377 return ERR_ARG;
1378 }
1379
1380 dst_ptr = ((char *)p->payload) + start_offset;
1381 copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);
1382 if ((start_offset & 1) != 0) {
1383 copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);
1384 }
1385 acc = *chksum;
1386 acc += copy_chksum;
1387 *chksum = FOLD_U32T(acc);
1388 return ERR_OK;
1389}
1390#endif /* LWIP_CHECKSUM_ON_COPY */
1391
1401u8_t
1403{
1404 int ret = pbuf_try_get_at(p, offset);
1405 if (ret >= 0) {
1406 return (u8_t)ret;
1407 }
1408 return 0;
1409}
1410
1419int
1421{
1422 u16_t q_idx;
1423 const struct pbuf *q = pbuf_skip_const(p, offset, &q_idx);
1424
1425 /* return requested data if pbuf is OK */
1426 if ((q != NULL) && (q->len > q_idx)) {
1427 return ((u8_t *)q->payload)[q_idx];
1428 }
1429 return -1;
1430}
1431
1441void
1443{
1444 u16_t q_idx;
1445 struct pbuf *q = pbuf_skip(p, offset, &q_idx);
1446
1447 /* write requested data if pbuf is OK */
1448 if ((q != NULL) && (q->len > q_idx)) {
1449 ((u8_t *)q->payload)[q_idx] = data;
1450 }
1451}
1452
1464u16_t
1465pbuf_memcmp(const struct pbuf *p, u16_t offset, const void *s2, u16_t n)
1466{
1467 u16_t start = offset;
1468 const struct pbuf *q = p;
1469 u16_t i;
1470
1471 /* pbuf long enough to perform check? */
1472 if (p->tot_len < (offset + n)) {
1473 return 0xffff;
1474 }
1475
1476 /* get the correct pbuf from chain. We know it succeeds because of p->tot_len check above. */
1477 while ((q != NULL) && (q->len <= start)) {
1478 start = (u16_t)(start - q->len);
1479 q = q->next;
1480 }
1481
1482 /* return requested data if pbuf is OK */
1483 for (i = 0; i < n; i++) {
1484 /* We know pbuf_get_at() succeeds because of p->tot_len check above. */
1485 u8_t a = pbuf_get_at(q, (u16_t)(start + i));
1486 u8_t b = ((const u8_t *)s2)[i];
1487 if (a != b) {
1488 return (u16_t)LWIP_MIN(i + 1, 0xFFFF);
1489 }
1490 }
1491 return 0;
1492}
1493
1506u16_t
1507pbuf_memfind(const struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)
1508{
1509 u16_t i;
1510 u16_t max_cmp_start = (u16_t)(p->tot_len - mem_len);
1511 if (p->tot_len >= mem_len + start_offset) {
1512 for (i = start_offset; i <= max_cmp_start; i++) {
1513 u16_t plus = pbuf_memcmp(p, i, mem, mem_len);
1514 if (plus == 0) {
1515 return i;
1516 }
1517 }
1518 }
1519 return 0xFFFF;
1520}
1521
1533u16_t
1534pbuf_strstr(const struct pbuf *p, const char *substr)
1535{
1536 size_t substr_len;
1537 if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
1538 return 0xFFFF;
1539 }
1540 substr_len = strlen(substr);
1541 if (substr_len >= 0xFFFF) {
1542 return 0xFFFF;
1543 }
1544 return pbuf_memfind(p, substr, (u16_t)substr_len, 0);
1545}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
r l[0]
Definition: byte_order.h:168
#define MEM_ALIGNMENT
Definition: d3d9_helpers.c:15
#define LWIP_MIN(x, y)
Definition: def.h:66
#define mem_free(ptr, bsize)
Definition: types.h:124
#define NULL
Definition: types.h:112
#define SYS_ARCH_UNPROTECT(lev)
Definition: cc.h:39
#define SYS_ARCH_PROTECT(lev)
Definition: cc.h:38
#define SYS_ARCH_DECL_PROTECT(lev)
Definition: cc.h:37
#define U16_F
Definition: cc.h:19
void * mem_trim(void *rmem, mem_size_t new_size)
Definition: mem.c:699
void * mem_malloc(mem_size_t size_in)
Definition: mem.c:831
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:130
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
u16_t mem_size_t
Definition: mem.h:67
#define ERR_MEM
Definition: fontsub.h:52
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLint left
Definition: glext.h:7726
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLenum GLuint GLint GLint layer
Definition: glext.h:7007
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLintptr offset
Definition: glext.h:5920
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
uint16_t u16_t
Definition: arch.h:127
#define LWIP_CONST_CAST(target_type, val)
Definition: arch.h:240
#define LWIP_MEM_ALIGN(addr)
Definition: arch.h:294
int16_t s16_t
Definition: arch.h:128
#define LWIP_MEM_ALIGN_SIZE(size)
Definition: arch.h:279
uintptr_t mem_ptr_t
Definition: arch.h:135
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:57
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:55
#define LWIP_DBG_TRACE
Definition: debug.h:83
s8_t err_t
Definition: err.h:96
@ ERR_OK
Definition: err.h:55
@ ERR_VAL
Definition: err.h:67
@ ERR_ARG
Definition: err.h:88
#define PBUF_DEBUG
Definition: opt.h:3343
#define LWIP_PBUF_REF_T
Definition: opt.h:1607
struct pbuf * pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
Definition: pbuf.c:1309
u16_t pbuf_memfind(const struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)
Definition: pbuf.c:1507
u16_t pbuf_memcmp(const struct pbuf *p, u16_t offset, const void *s2, u16_t n)
Definition: pbuf.c:1465
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:402
struct pbuf * pbuf_alloc_reference(void *payload, u16_t length, pbuf_type type)
Definition: pbuf.c:327
u8_t pbuf_get_at(const struct pbuf *p, u16_t offset)
Definition: pbuf.c:1402
void * pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset)
Definition: pbuf.c:1105
void pbuf_ref(struct pbuf *p)
Definition: pbuf.c:831
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:855
void pbuf_chain(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:897
int pbuf_try_get_at(const struct pbuf *p, u16_t offset)
Definition: pbuf.c:1420
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
pbuf_type
Definition: pbuf.h:145
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
Definition: pbuf.c:959
struct pbuf * pbuf_skip(struct pbuf *in, u16_t in_offset, u16_t *out_offset)
Definition: pbuf.c:1209
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1058
struct pbuf * pbuf_clone(pbuf_layer layer, pbuf_type type, struct pbuf *p)
Definition: pbuf.c:1337
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
Definition: pbuf.c:1227
err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
Definition: pbuf.c:986
err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1271
pbuf_layer
Definition: pbuf.h:89
void pbuf_put_at(struct pbuf *p, u16_t offset, u8_t data)
Definition: pbuf.c:1442
@ PBUF_ROM
Definition: pbuf.h:156
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_REF
Definition: pbuf.h:160
@ PBUF_POOL
Definition: pbuf.h:167
#define SWAP_BYTES_IN_WORD(w)
Definition: inet_chksum.h:47
#define FOLD_U32T(u)
Definition: inet_chksum.h:52
static substr_t substr(const WCHAR *str, size_t len)
Definition: internet.h:203
int const JOCTET * dataptr
Definition: jpeglib.h:1031
if(dx< 0)
Definition: linetemp.h:194
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
void * memp_malloc(memp_t type)
Definition: memp.c:337
void memp_free(memp_t type, void *mem)
Definition: memp.c:420
struct S2 s2
static UINT UINT last
Definition: font.c:45
#define NETIF_NO_INDEX
Definition: netif.h:579
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:649
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:554
#define PBUF_POOL_BUFSIZE_ALIGNED
Definition: pbuf.c:92
static const struct pbuf * pbuf_skip_const(const struct pbuf *in, u16_t in_offset, u16_t *out_offset)
Definition: pbuf.c:1183
static u8_t pbuf_add_header_impl(struct pbuf *p, size_t header_size_increment, u8_t force)
Definition: pbuf.c:476
u16_t pbuf_clen(const struct pbuf *p)
Definition: pbuf.c:811
static u8_t pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
Definition: pbuf.c:619
static void pbuf_init_alloced_pbuf(struct pbuf *p, void *payload, u16_t tot_len, u16_t len, pbuf_type type, u8_t flags)
Definition: pbuf.c:179
#define SIZEOF_STRUCT_PBUF
Definition: pbuf.c:89
u16_t pbuf_strstr(const struct pbuf *p, const char *substr)
Definition: pbuf.c:1534
struct pbuf * pbuf_free_header(struct pbuf *q, u16_t size)
Definition: pbuf.c:674
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
Definition: pbuf.c:585
struct pbuf * pbuf_dechain(struct pbuf *p)
Definition: pbuf.c:914
u8_t pbuf_header_force(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:659
u8_t pbuf_add_header_force(struct pbuf *p, size_t header_size_increment)
Definition: pbuf.c:564
#define PBUF_POOL_IS_EMPTY()
Definition: pbuf.c:98
#define PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL
Definition: pbuf.h:135
#define PBUF_FLAG_TCP_FIN
Definition: pbuf.h:183
#define PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF
Definition: pbuf.h:134
#define PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS
Definition: pbuf.h:119
#define pbuf_get_allocsrc(p)
Definition: pbuf.h:283
#define LWIP_SUPPORT_CUSTOM_PBUF
Definition: pbuf.h:55
#define pbuf_match_allocsrc(p, type)
Definition: pbuf.h:284
#define PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP
Definition: pbuf.h:133
#define PBUF_FLAG_IS_CUSTOM
Definition: pbuf.h:175
#define PERF_START
Definition: perf.h:3
#define PERF_STOP
Definition: perf.h:4
#define err(...)
static FILE * out
Definition: regtests2xml.c:44
struct define * next
Definition: compiler.c:65
Definition: mem.c:349
Definition: pbuf.h:186
LWIP_PBUF_REF_T ref
Definition: pbuf.h:218
u16_t tot_len
Definition: pbuf.h:200
struct pbuf * next
Definition: pbuf.h:188
u8_t type_internal
Definition: pbuf.h:208
u16_t len
Definition: pbuf.h:203
void * payload
Definition: pbuf.h:191
Definition: send.c:48
#define SYS_ARCH_SET(var, val)
Definition: sys.h:553
int ret