80#if LWIP_TCP && TCP_QUEUE_OOSEQ
83#if LWIP_CHECKSUM_ON_COPY
89#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
92#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
94static const struct pbuf *
95pbuf_skip_const(
const struct pbuf *in, u16_t in_offset, u16_t *out_offset);
97#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ
98#define PBUF_POOL_IS_EMPTY()
102#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
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); \
113volatile u8_t pbuf_free_ooseq_pending;
114#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
131 SYS_ARCH_SET(pbuf_free_ooseq_pending, 0);
133 for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
134 if (pcb->ooseq != NULL) {
148pbuf_free_ooseq_callback(
void *arg)
157pbuf_pool_is_empty(
void)
159#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
160 SYS_ARCH_SET(pbuf_free_ooseq_pending, 1);
164 SYS_ARCH_PROTECT(old_level);
165 queued = pbuf_free_ooseq_pending;
166 pbuf_free_ooseq_pending = 1;
167 SYS_ARCH_UNPROTECT(old_level);
171 PBUF_POOL_FREE_OOSEQ_QUEUE_CALL();
179pbuf_init_alloced_pbuf(
struct pbuf *p,
void *payload, u16_t tot_len, u16_t len,
pbuf_type type, u8_t flags)
182 p->payload = payload;
183 p->tot_len = tot_len;
185 p->type_internal = (u8_t)type;
188 p->if_idx = NETIF_NO_INDEX;
229 u16_t offset = (u16_t)layer;
238 struct pbuf *q, *last;
247 PBUF_POOL_IS_EMPTY();
255 qlen = LWIP_MIN(rem_len, (u16_t)(PBUF_POOL_BUFSIZE_ALIGNED -
LWIP_MEM_ALIGN_SIZE(offset)));
256 pbuf_init_alloced_pbuf(q,
LWIP_MEM_ALIGN((
void *)((u8_t *)q + SIZEOF_STRUCT_PBUF + offset)),
257 rem_len, qlen, type, 0);
258 LWIP_ASSERT(
"pbuf_alloc: pbuf q->payload properly aligned",
259 ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
260 LWIP_ASSERT(
"PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT",
270 rem_len = (u16_t)(rem_len - qlen);
272 }
while (rem_len > 0);
277 mem_size_t alloc_len = (mem_size_t)(
LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF) + payload_len);
290 pbuf_init_alloced_pbuf(p,
LWIP_MEM_ALIGN((
void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)),
291 length, length, type, 0);
292 LWIP_ASSERT(
"pbuf_alloc: pbuf->payload properly aligned",
293 ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
297 LWIP_ASSERT(
"pbuf_alloc: erroneous type", 0);
337 (
"pbuf_alloc_reference: Could not allocate MEMP_PBUF for PBUF_%s.\n",
338 (type ==
PBUF_ROM) ?
"ROM" :
"REF"));
341 pbuf_init_alloced_pbuf(p,
payload, length, length, type, 0);
346#if LWIP_SUPPORT_CUSTOM_PBUF
366 void *payload_mem, u16_t payload_mem_len)
368 u16_t offset = (u16_t)l;
377 if (payload_mem != NULL) {
404pbuf_realloc(
struct pbuf *p, u16_t new_len)
410 LWIP_ASSERT(
"pbuf_realloc: p != NULL", p != NULL);
413 if (new_len >= p->tot_len) {
420 shrink = (u16_t)(p->tot_len - new_len);
426 while (rem_len > q->len) {
428 rem_len = (u16_t)(rem_len - q->len);
430 q->tot_len = (u16_t)(q->tot_len - shrink);
433 LWIP_ASSERT(
"pbuf_realloc: q != NULL", q != NULL);
440 if (pbuf_match_allocsrc(q, PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) && (rem_len != q->len)
446 struct pbuf *r = (
struct pbuf *)
mem_trim(q, (mem_size_t)(((u8_t *)q->payload - (u8_t *)q) + rem_len));
447 LWIP_ASSERT(
"mem_trim returned r == NULL", r != NULL);
449 LWIP_ASSERT(
"mem_trim returned r != q", r == q);
457 if (q->next != NULL) {
478pbuf_add_header_impl(
struct pbuf *p,
size_t header_size_increment, u8_t force)
482 u16_t increment_magnitude;
484 LWIP_ASSERT(
"p != NULL", p != NULL);
485 if ((p == NULL) || (header_size_increment > 0xFFFF)) {
488 if (header_size_increment == 0) {
492 increment_magnitude = (u16_t)header_size_increment;
494 if ((u16_t)(increment_magnitude + p->tot_len) < increment_magnitude) {
503 payload = (u8_t *)p->payload - header_size_increment;
505 if ((u8_t *)
payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) {
507 (
"pbuf_add_header: failed as %p < %p (not enough space for new header size)\n",
508 (
void *)
payload, (
void *)((u8_t *)p + SIZEOF_STRUCT_PBUF)));
516 payload = (u8_t *)p->payload - header_size_increment;
524 (
void *)p->payload, (
void *)
payload, increment_magnitude));
528 p->len = (u16_t)(p->len + increment_magnitude);
529 p->tot_len = (u16_t)(p->tot_len + increment_magnitude);
558 return pbuf_add_header_impl(p, header_size_increment, 0);
568 return pbuf_add_header_impl(p, header_size_increment, 1);
590 u16_t increment_magnitude;
592 LWIP_ASSERT(
"p != NULL", p != NULL);
593 if ((p == NULL) || (header_size_decrement > 0xFFFF)) {
596 if (header_size_decrement == 0) {
600 increment_magnitude = (u16_t)header_size_decrement;
602 LWIP_ERROR(
"increment_magnitude <= p->len", (increment_magnitude <= p->
len),
return 1;);
609 p->payload = (u8_t *)p->payload + header_size_decrement;
611 p->len = (u16_t)(p->len - increment_magnitude);
612 p->tot_len = (u16_t)(p->tot_len - increment_magnitude);
615 (
void *)
payload, (
void *)p->payload, increment_magnitude));
621pbuf_header_impl(
struct pbuf *p, s16_t header_size_increment, u8_t force)
623 if (header_size_increment < 0) {
626 return pbuf_add_header_impl(p, (
size_t)header_size_increment, force);
653 return pbuf_header_impl(p, header_size_increment, 0);
663 return pbuf_header_impl(p, header_size_increment, 1);
679 u16_t free_left = size;
680 while (free_left && p) {
681 if (free_left >= p->len) {
683 free_left = (u16_t)(free_left - p->len);
736 LWIP_ASSERT(
"p != NULL", p != NULL);
739 (
"pbuf_free(p == NULL) was called.\n"));
755 SYS_ARCH_PROTECT(old_level);
757 LWIP_ASSERT(
"pbuf_free: p->ref > 0", p->ref > 0);
760 SYS_ARCH_UNPROTECT(old_level);
766 alloc_src = pbuf_get_allocsrc(p);
767#if LWIP_SUPPORT_CUSTOM_PBUF
770 struct pbuf_custom *pc = (
struct pbuf_custom *)p;
771 LWIP_ASSERT(
"pc->custom_free_function != NULL", pc->custom_free_function != NULL);
772 pc->custom_free_function(p);
777 if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) {
780 }
else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) {
783 }
else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) {
787 LWIP_ASSERT(
"invalid pbuf type", 0);
796 LWIP_DEBUGF(
PBUF_DEBUG |
LWIP_DBG_TRACE, (
"pbuf_free: %p has ref %"U16_F
", ending here.\n", (
void *)p, (u16_t)ref));
801 PERF_STOP(
"pbuf_free");
838 LWIP_ASSERT(
"pbuf ref overflow", p->ref > 0);
861 LWIP_ERROR(
"(h != NULL) && (t != NULL) (programmer violates API)",
862 ((h != NULL) && (t != NULL)),
return;);
863 LWIP_ASSERT(
"Creating an infinite loop", h != t);
866 for (p = h; p->next != NULL; p = p->next) {
868 p->tot_len = (u16_t)(p->tot_len + t->tot_len);
871 LWIP_ASSERT(
"p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
872 LWIP_ASSERT(
"p->next == NULL", p->next == NULL);
874 p->tot_len = (u16_t)(p->tot_len + t->tot_len);
926 LWIP_ASSERT(
"p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
928 q->tot_len = (u16_t)(p->tot_len - p->len);
938 (
"pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (
void *)q));
943 LWIP_ASSERT(
"p->tot_len == p->len", p->tot_len == p->len);
944 return ((tail_gone > 0) ? NULL : q);
965 (
const void *)p_to, (
const void *)p_from));
967 LWIP_ERROR(
"pbuf_copy: invalid source", p_from != NULL,
return ERR_ARG;);
991 size_t offset_to = offset, offset_from = 0,
len;
994 (
const void *)p_to, (
const void *)p_from, copy_len, offset));
997 LWIP_ERROR(
"pbuf_copy_partial_pbuf: copy_len bigger than source", ((p_from != NULL) &&
1000 LWIP_ERROR(
"pbuf_copy_partial_pbuf: target not big enough", ((p_to != NULL) &&
1006 if ((p_to->
len - offset_to) >= (p_from->
len - offset_from)) {
1008 len = p_from->
len - offset_from;
1011 len = p_to->
len - offset_to;
1013 len = LWIP_MIN(copy_len,
len);
1017 copy_len = (u16_t)(copy_len -
len);
1018 LWIP_ASSERT(
"offset_to <= p_to->len", offset_to <= p_to->
len);
1019 LWIP_ASSERT(
"offset_from <= p_from->len", offset_from <= p_from->
len);
1020 if (offset_from >= p_from->
len) {
1023 p_from = p_from->
next;
1024 LWIP_ERROR(
"p_from != NULL", (p_from != NULL) || (copy_len == 0),
return ERR_ARG;);
1026 if (offset_to == p_to->
len) {
1030 LWIP_ERROR(
"p_to != NULL", (p_to != NULL) || (copy_len == 0),
return ERR_ARG;);
1033 if ((p_from != NULL) && (p_from->
len == p_from->
tot_len)) {
1035 LWIP_ERROR(
"pbuf_copy_partial_pbuf() does not allow packet queues!",
1038 if ((p_to != NULL) && (p_to->
len == p_to->
tot_len)) {
1040 LWIP_ERROR(
"pbuf_copy_partial_pbuf() does not allow packet queues!",
1063 const struct pbuf *p;
1066 u16_t copied_total = 0;
1068 LWIP_ERROR(
"pbuf_copy_partial: invalid buf", (buf != NULL),
return 0;);
1069 LWIP_ERROR(
"pbuf_copy_partial: invalid dataptr", (dataptr != NULL),
return 0;);
1072 for (p = buf;
len != 0 && p != NULL; p = p->next) {
1073 if ((offset != 0) && (offset >= p->len)) {
1075 offset = (u16_t)(offset - p->len);
1078 buf_copy_len = (u16_t)(p->len - offset);
1079 if (buf_copy_len >
len) {
1083 MEMCPY(&((
char *)dataptr)[left], &((
char *)p->payload)[offset], buf_copy_len);
1084 copied_total = (u16_t)(copied_total + buf_copy_len);
1085 left = (u16_t)(left + buf_copy_len);
1086 len = (u16_t)(
len - buf_copy_len);
1090 return copied_total;
1113 const struct pbuf *q;
1116 LWIP_ERROR(
"pbuf_get_contiguous: invalid buf", (p != NULL),
return NULL;);
1117 LWIP_ERROR(
"pbuf_get_contiguous: invalid bufsize", (buffer == NULL) || (bufsize >=
len),
return NULL;);
1119 q = pbuf_skip_const(p, offset, &out_offset);
1121 if (q->len >= (out_offset +
len)) {
1123 return (u8_t *)q->payload + out_offset;
1125 if (buffer == NULL) {
1140#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
1153void pbuf_split_64k(
struct pbuf *p,
struct pbuf **rest)
1156 if ((p != NULL) && (p->next != NULL)) {
1157 u16_t tot_len_front = p->len;
1162 while ((r != NULL) && ((u16_t)(tot_len_front + r->
len) >= tot_len_front)) {
1163 tot_len_front = (u16_t)(tot_len_front + r->
len);
1173 for (i = p; i != NULL; i = i->
next) {
1175 LWIP_ASSERT(
"tot_len/len mismatch in last pbuf",
1191static const struct pbuf *
1192pbuf_skip_const(
const struct pbuf *in, u16_t in_offset, u16_t *out_offset)
1194 u16_t offset_left = in_offset;
1195 const struct pbuf *q = in;
1198 while ((q != NULL) && (q->len <= offset_left)) {
1199 offset_left = (u16_t)(offset_left - q->len);
1202 if (out_offset != NULL) {
1203 *out_offset = offset_left;
1220 const struct pbuf *out = pbuf_skip_const(in, in_offset, out_offset);
1236pbuf_take(
struct pbuf *buf,
const void *dataptr, u16_t
len)
1239 size_t buf_copy_len;
1240 size_t total_copy_len =
len;
1241 size_t copied_total = 0;
1243 LWIP_ERROR(
"pbuf_take: invalid buf", (buf != NULL),
return ERR_ARG;);
1244 LWIP_ERROR(
"pbuf_take: invalid dataptr", (dataptr != NULL),
return ERR_ARG;);
1245 LWIP_ERROR(
"pbuf_take: buf not large enough", (buf->tot_len >=
len),
return ERR_MEM;);
1247 if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len <
len)) {
1252 for (p = buf; total_copy_len != 0; p = p->next) {
1253 LWIP_ASSERT(
"pbuf_take: invalid pbuf", p != NULL);
1254 buf_copy_len = total_copy_len;
1255 if (buf_copy_len > p->len) {
1257 buf_copy_len = p->len;
1260 MEMCPY(p->payload, &((
const char *)dataptr)[copied_total], buf_copy_len);
1261 total_copy_len -= buf_copy_len;
1262 copied_total += buf_copy_len;
1264 LWIP_ASSERT(
"did not copy all data", total_copy_len == 0 && copied_total ==
len);
1282 u16_t target_offset;
1286 if ((q != NULL) && (q->tot_len >= target_offset +
len)) {
1287 u16_t remaining_len =
len;
1288 const u8_t *src_ptr = (
const u8_t *)dataptr;
1290 u16_t first_copy_len;
1291 LWIP_ASSERT(
"check pbuf_skip result", target_offset < q->
len);
1292 first_copy_len = (u16_t)LWIP_MIN(q->len - target_offset,
len);
1293 MEMCPY(((u8_t *)q->payload) + target_offset, dataptr, first_copy_len);
1294 remaining_len = (u16_t)(remaining_len - first_copy_len);
1295 src_ptr += first_copy_len;
1296 if (remaining_len > 0) {
1297 return pbuf_take(q->next, src_ptr, remaining_len);
1321 if (p->next == NULL) {
1350 q = pbuf_alloc(layer, p->tot_len, type);
1356 LWIP_ASSERT(
"pbuf_copy failed", err ==
ERR_OK);
1360#if LWIP_CHECKSUM_ON_COPY
1374pbuf_fill_chksum(
struct pbuf *p, u16_t start_offset,
const void *dataptr,
1375 u16_t
len, u16_t *chksum)
1380 LWIP_ASSERT(
"p != NULL", p != NULL);
1381 LWIP_ASSERT(
"dataptr != NULL", dataptr != NULL);
1382 LWIP_ASSERT(
"chksum != NULL", chksum != NULL);
1383 LWIP_ASSERT(
"len != 0",
len != 0);
1385 if ((start_offset >= p->len) || (start_offset +
len > p->len)) {
1389 dst_ptr = ((
char *)p->payload) + start_offset;
1390 copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr,
len);
1391 if ((start_offset & 1) != 0) {
1432 const struct pbuf *q = pbuf_skip_const(p, offset, &q_idx);
1435 if ((q != NULL) && (q->len > q_idx)) {
1436 return ((u8_t *)q->payload)[q_idx];
1457 if ((q != NULL) && (q->len > q_idx)) {
1458 ((u8_t *)q->payload)[q_idx] = data;
1476 u16_t start = offset;
1477 const struct pbuf *q = p;
1481 if (p->tot_len < (offset + n)) {
1486 while ((q != NULL) && (q->len <= start)) {
1487 start = (u16_t)(start - q->len);
1492 for (i = 0; i < n; i++) {
1495 u8_t b = ((
const u8_t *)s2)[i];
1497 return (u16_t)LWIP_MIN(i + 1, 0xFFFF);
1519 u16_t max_cmp_start = (u16_t)(p->tot_len - mem_len);
1520 if (p->tot_len >= mem_len + start_offset) {
1521 for (i = start_offset; i <= max_cmp_start; i++) {
1546 if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
1549 substr_len = strlen(substr);
1550 if (substr_len >= 0xFFFF) {
#define LWIP_UNUSED_ARG(x)
#define LWIP_CONST_CAST(target_type, val)
#define LWIP_MEM_ALIGN(addr)
#define LWIP_MEM_ALIGN_SIZE(size)
#define LWIP_DBG_LEVEL_SERIOUS
#define LWIP_DBG_LEVEL_WARNING
#define MEMCPY(dst, src, len)
#define LWIP_PBUF_CUSTOM_DATA_INIT(p)
struct pbuf * pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
u16_t pbuf_memfind(const struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)
u16_t pbuf_memcmp(const struct pbuf *p, u16_t offset, const void *s2, u16_t n)
struct pbuf * pbuf_alloc_reference(void *payload, u16_t length, pbuf_type type)
u8_t pbuf_get_at(const struct pbuf *p, u16_t offset)
void * pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset)
void pbuf_ref(struct pbuf *p)
void pbuf_cat(struct pbuf *head, struct pbuf *tail)
void pbuf_chain(struct pbuf *h, struct pbuf *t)
int pbuf_try_get_at(const struct pbuf *p, u16_t offset)
u8 pbuf_free(struct pbuf *p)
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
struct pbuf * pbuf_skip(struct pbuf *in, u16_t in_offset, u16_t *out_offset)
u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset)
struct pbuf * pbuf_clone(pbuf_layer l, pbuf_type type, struct pbuf *p)
err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
void pbuf_put_at(struct pbuf *p, u16_t offset, u8_t data)
#define SWAP_BYTES_IN_WORD(w)
void * mem_trim(void *mem, mem_size_t size)
void * mem_malloc(mem_size_t size)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
u8_t pbuf_header_force(struct pbuf *p, s16_t header_size)
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
#define PBUF_FLAG_TCP_FIN
#define PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS
#define LWIP_SUPPORT_CUSTOM_PBUF
u16_t pbuf_strstr(const struct pbuf *p, const char *substr)
struct pbuf * pbuf_free_header(struct pbuf *q, u16_t size)
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size)
u8_t pbuf_add_header_force(struct pbuf *p, size_t header_size_increment)
#define PBUF_FLAG_IS_CUSTOM
u8 pbuf_header(struct pbuf *p, s16 header_size)
struct pbuf * pbuf_dechain(struct pbuf *p)
#define SYS_ARCH_DECL_PROTECT(lev)
u32 count
start sector of fragmented bd/file