MeterLogger
Macros | Functions
pbuf.c File Reference
#include "lwip/opt.h"
#include "lwip/stats.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "arch/perf.h"
#include <string.h>
Include dependency graph for pbuf.c:

Go to the source code of this file.

Macros

#define EP_OFFSET   0
 
#define SIZEOF_STRUCT_PBUF   LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
 
#define PBUF_POOL_BUFSIZE_ALIGNED   LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
 
#define PBUF_POOL_IS_EMPTY()
 

Functions

struct pbufpbuf_alloc (pbuf_layer layer, u16_t length, pbuf_type type)
 
void pbuf_realloc (struct pbuf *p, u16_t new_len)
 
u8_t pbuf_header (struct pbuf *p, s16_t header_size_increment)
 
u8_t pbuf_free (struct pbuf *p)
 
u8_t pbuf_clen (struct pbuf *p)
 
void pbuf_ref (struct pbuf *p)
 
void pbuf_cat (struct pbuf *h, struct pbuf *t)
 
void pbuf_chain (struct pbuf *h, struct pbuf *t)
 
struct pbufpbuf_dechain (struct pbuf *p)
 
err_t pbuf_copy (struct pbuf *p_to, struct pbuf *p_from)
 
u16_t pbuf_copy_partial (struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
 
err_t pbuf_take (struct pbuf *buf, const void *dataptr, u16_t len)
 
struct pbufpbuf_coalesce (struct pbuf *p, pbuf_layer layer)
 
u8_t pbuf_get_at (struct pbuf *p, u16_t offset)
 
u16_t pbuf_memcmp (struct pbuf *p, u16_t offset, const void *s2, u16_t n)
 
u16_t pbuf_memfind (struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)
 
u16_t pbuf_strstr (struct pbuf *p, const char *substr)
 

Detailed Description

Packet buffer management

Packets are built from the pbuf data structure. It supports dynamic memory allocation for packet contents or can reference externally managed packet contents both in RAM and ROM. Quick allocation for incoming packets is provided through pools with fixed sized pbufs.

A packet may span over multiple pbufs, chained as a singly linked list. This is called a "pbuf chain".

Multiple packets may be queued, also using this singly linked list. This is called a "packet queue".

So, a packet queue consists of one or more pbuf chains, each of which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE NOT SUPPORTED!!! Use helper structs to queue multiple packets.

The differences between a pbuf chain and a packet queue are very precise but subtle.

The last pbuf of a packet has a ->tot_len field that equals the ->len field. It can be found by traversing the list. If the last pbuf of a packet has a ->next field other than NULL, more packets are on the queue.

Therefore, looping through a pbuf of a single packet, has an loop end condition (tot_len == p->len), NOT (next == NULL).

Definition in file pbuf.c.

Macro Definition Documentation

◆ EP_OFFSET

#define EP_OFFSET   0

Definition at line 89 of file pbuf.c.

Referenced by pbuf_alloc(), and pbuf_header().

◆ PBUF_POOL_BUFSIZE_ALIGNED

#define PBUF_POOL_BUFSIZE_ALIGNED   LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)

Definition at line 95 of file pbuf.c.

Referenced by pbuf_alloc().

◆ PBUF_POOL_IS_EMPTY

#define PBUF_POOL_IS_EMPTY ( )

Attempt to reclaim some memory from queued out-of-sequence TCP segments if we run out of pool pbufs. It's better to give priority to new packets if we're running out.

Definition at line 137 of file pbuf.c.

Referenced by pbuf_alloc().

◆ SIZEOF_STRUCT_PBUF

#define SIZEOF_STRUCT_PBUF   LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))

Definition at line 92 of file pbuf.c.

Referenced by pbuf_alloc(), and pbuf_header().

Function Documentation

◆ pbuf_alloc()

struct pbuf* pbuf_alloc ( pbuf_layer  layer,
u16_t  length,
pbuf_type  type 
)

Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).

The actual memory allocated for the pbuf is determined by the layer at which the pbuf is allocated and the requested size (from the size parameter).

Parameters
layerflag to define header size
lengthsize of the pbuf's payload
typethis parameter decides how and where the pbuf should be allocated as follows:
  • PBUF_RAM: buffer memory for pbuf is allocated as one large chunk. This includes protocol headers as well.
  • PBUF_ROM: no buffer memory is allocated for the pbuf, even for protocol headers. Additional headers must be prepended by allocating another pbuf and chain in to the front of the ROM pbuf. It is assumed that the memory used is really similar to ROM in that it is immutable and will not be changed. Memory which is dynamic should generally not be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
  • PBUF_REF: no buffer memory is allocated for the pbuf, even for protocol headers. It is assumed that the pbuf is only being used in a single thread. If the pbuf gets queued, then pbuf_take should be called to copy the buffer.
  • PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from the pbuf pool that is allocated during pbuf_init().
Returns
the allocated pbuf. If multiple pbufs where allocated, this is the first pbuf of a pbuf chain.

Definition at line 234 of file pbuf.c.

References EP_OFFSET, pbuf::flags, pbuf::len, LWIP_ASSERT, LWIP_DBG_LEVEL_SERIOUS, LWIP_DBG_LEVEL_WARNING, LWIP_DBG_TRACE, LWIP_DEBUGF, LWIP_MEM_ALIGN, LWIP_MEM_ALIGN_SIZE, LWIP_MIN, MEM_ALIGNMENT, mem_malloc(), memp_malloc(), pbuf::next, NULL, pbuf::payload, PBUF_DEBUG, PBUF_FLAG_IS_CUSTOM, pbuf_free(), PBUF_IP, PBUF_IP_HLEN, PBUF_LINK, PBUF_LINK_HLEN, PBUF_POOL, PBUF_POOL_BUFSIZE_ALIGNED, PBUF_POOL_IS_EMPTY, PBUF_RAM, PBUF_RAW, PBUF_REF, PBUF_ROM, PBUF_TRANSPORT, PBUF_TRANSPORT_HLEN, pbuf::ref, SIZEOF_STRUCT_PBUF, pbuf::tot_len, pbuf::type, and U16_F.

Referenced by espconn_udp_sendto(), espconn_udp_sent(), netif_set_link_down(), pbuf_coalesce(), send_ack(), send_nak(), and send_offer().

235 {
236  struct pbuf *p, *q, *r;
237  u16_t offset;
238  s32_t rem_len; /* remaining length */
239  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
240 
241  /* determine header offset */
242  offset = 0;
243  switch (layer) {
244  case PBUF_TRANSPORT:
245  /* add room for transport (often TCP) layer header */
246  offset += PBUF_TRANSPORT_HLEN;
247  /* FALLTHROUGH */
248  case PBUF_IP:
249  /* add room for IP layer header */
250  offset += PBUF_IP_HLEN;
251  /* FALLTHROUGH */
252  case PBUF_LINK:
253  /* add room for link layer header */
254  offset += PBUF_LINK_HLEN;
255 
256 #ifdef PBUF_RSV_FOR_WLAN
257  /*
258  * 1. LINK_HLEN 14Byte will be remove in WLAN layer
259  * 2. IEEE80211_HDR_MAX_LEN needs 40 bytes.
260  * 3. encryption needs exra 4 bytes ahead of actual data payload, and require
261  * DAddr and SAddr to be 4-byte aligned.
262  * 4. TRANSPORT and IP are all 20, 4 bytes aligned, nice...
263  * 5. LCC add 6 bytes more, We don't consider WAPI yet...
264  * 6. define LWIP_MEM_ALIGN to be 4 Byte aligned, pbuf struct is 16B, Only thing may be
265  * matter is ether_hdr is not 4B aligned.
266  *
267  * So, we need extra (40 + 4 - 14) = 30 and it's happen to be 4-Byte aligned
268  *
269  * 1. lwip
270  * | empty 30B | eth_hdr (14B) | payload ...|
271  * total: 44B ahead payload
272  * 2. net80211
273  * | max 80211 hdr, 32B | ccmp/tkip iv (8B) | sec rsv(4B) | payload ...|
274  * total: 40B ahead sec_rsv and 44B ahead payload
275  *
276  */
277  offset += EP_OFFSET; //remove LINK hdr in wlan
278 #endif /* PBUF_RSV_FOR_WLAN */
279 
280  break;
281  case PBUF_RAW:
282 #ifdef PBUF_RSV_FOR_WLAN
283  /*
284  * RAW pbuf suppose
285  */
286  offset += EP_OFFSET; //remove LINK hdr in wlan
287 #endif /* PBUF_RAW */
288  break;
289  default:
290  LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
291  return NULL;
292  }
293 
294  switch (type) {
295  case PBUF_POOL:
296  /* allocate head of pbuf chain into p */
297  p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
298  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
299  if (p == NULL) {
301  return NULL;
302  }
303  p->type = type;
304  p->next = NULL;
305 
306  /* make the payload pointer point 'offset' bytes into pbuf data memory */
307  p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)));
308  LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
309  ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
310  /* the total length of the pbuf chain is the requested size */
311  p->tot_len = length;
312  /* set the length of the first pbuf in the chain */
314  LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
315  ((u8_t*)p->payload + p->len <=
317  LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT",
319  /* set reference count (needed here in case we fail) */
320  p->ref = 1;
321 
322  /* now allocate the tail of the pbuf chain */
323 
324  /* remember first pbuf for linkage in next iteration */
325  r = p;
326  /* remaining length to be allocated */
327  rem_len = length - p->len;
328  /* any remaining pbufs to be allocated? */
329  while (rem_len > 0) {
330  q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
331  if (q == NULL) {
333  /* free chain so far allocated */
334  pbuf_free(p);
335  /* bail out unsuccesfully */
336  return NULL;
337  }
338  q->type = type;
339  q->flags = 0;
340  q->next = NULL;
341  /* make previous pbuf point to this pbuf */
342  r->next = q;
343  /* set total length of this pbuf and next in chain */
344  LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff);
345  q->tot_len = (u16_t)rem_len;
346  /* this pbuf length is pool size, unless smaller sized tail */
348  q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF);
349  LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
350  ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
351  LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
352  ((u8_t*)p->payload + p->len <=
354  q->ref = 1;
355  /* calculate remaining length to be allocated */
356  rem_len -= q->len;
357  /* remember this pbuf for linkage in next iteration */
358  r = q;
359  }
360  /* end of chain */
361  /*r->next = NULL;*/
362 
363  break;
364  case PBUF_RAM:
365  /* If pbuf is to be allocated in RAM, allocate memory for it. */
367  if (p == NULL) {
368  return NULL;
369  }
370  /* Set up internal structure of the pbuf. */
371  p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset));
372  p->len = p->tot_len = length;
373  p->next = NULL;
374  p->type = type;
375  p->eb = NULL;
376 
377  LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
378  ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
379  break;
380 #ifdef EBUF_LWIP
381  case PBUF_ESF_RX:
382 #endif /* ESF_LWIP */
383  /* pbuf references existing (non-volatile static constant) ROM payload? */
384  case PBUF_ROM:
385  /* pbuf references existing (externally allocated) RAM payload? */
386  case PBUF_REF:
387  /* only allocate memory for the pbuf structure */
388  p = (struct pbuf *)memp_malloc(MEMP_PBUF);
389  if (p == NULL) {
391  ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
392  (type == PBUF_ROM) ? "ROM" : "REF"));
393  return NULL;
394  }
395  /* caller must set this field properly, afterwards */
396  p->payload = NULL;
397  p->len = p->tot_len = length;
398  p->next = NULL;
399  p->type = type;
400  break;
401  default:
402  LWIP_ASSERT("pbuf_alloc: erroneous type", 0);
403  return NULL;
404  }
405  /* set reference count */
406  p->ref = 1;
407  /* set flags */
408  p->flags = 0;
409  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
410 
411  return p;
412 }
u16_t tot_len
Definition: pbuf.h:90
void * eb
Definition: pbuf.h:109
#define EP_OFFSET
Definition: pbuf.c:89
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define U16_F
Definition: cc.h:61
#define NULL
Definition: def.h:47
#define PBUF_IP_HLEN
Definition: pbuf.h:48
#define LWIP_DBG_TRACE
Definition: debug.h:56
#define MEM_ALIGNMENT
Definition: opt.h:124
void * memp_malloc(memp_t type) ICACHE_FLASH_ATTR
Definition: memp.c:393
void * mem_malloc(mem_size_t size) ICACHE_FLASH_ATTR
Definition: mem.c:493
Definition: pbuf.h:58
Definition: pbuf.h:53
#define PBUF_DEBUG
Definition: opt.h:1826
#define LWIP_MIN(x, y)
Definition: def.h:44
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:685
Definition: pbuf.h:54
#define SIZEOF_STRUCT_PBUF
Definition: pbuf.c:92
#define PBUF_TRANSPORT_HLEN
Definition: pbuf.h:47
u8_t flags
Definition: pbuf.h:99
#define LWIP_MEM_ALIGN_SIZE(size)
Definition: mem.h:144
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
#define PBUF_POOL_BUFSIZE_ALIGNED
Definition: pbuf.c:95
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:46
Definition: pbuf.h:76
Definition: pbuf.h:61
unsigned long mem_ptr_t
Definition: cc.h:58
Definition: pbuf.h:59
Definition: pbuf.h:60
unsigned char u8_t
Definition: cc.h:52
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
#define PBUF_POOL_IS_EMPTY()
Definition: pbuf.c:137
void * payload
Definition: pbuf.h:81
Definition: pbuf.h:52
signed long s32_t
Definition: cc.h:57
u8_t type
Definition: pbuf.h:96
#define PBUF_LINK_HLEN
Definition: opt.h:1061
u16_t ref
Definition: pbuf.h:106
#define LWIP_MEM_ALIGN(addr)
Definition: mem.h:159
unsigned short u16_t
Definition: cc.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pbuf_cat()

void pbuf_cat ( struct pbuf h,
struct pbuf t 
)

Concatenate two pbufs (each may be a pbuf chain) and take over the caller's reference of the tail pbuf.

Note
The caller MAY NOT reference the tail pbuf afterwards. Use pbuf_chain() for that purpose.
See also
pbuf_chain()

Definition at line 823 of file pbuf.c.

References pbuf::len, LWIP_ASSERT, LWIP_ERROR, pbuf::next, NULL, and pbuf::tot_len.

Referenced by pbuf_chain().

824 {
825  struct pbuf *p;
826 
827  LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)",
828  ((h != NULL) && (t != NULL)), return;);
829 
830  /* proceed to last pbuf of chain */
831  for (p = h; p->next != NULL; p = p->next) {
832  /* add total length of second chain to all totals of first chain */
833  p->tot_len += t->tot_len;
834  }
835  /* { p is last pbuf of first h chain, p->next == NULL } */
836  LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
837  LWIP_ASSERT("p->next == NULL", p->next == NULL);
838  /* add total length of second chain to last pbuf total of first chain */
839  p->tot_len += t->tot_len;
840  /* chain last pbuf of head (p) with first of tail (t) */
841  p->next = t;
842  /* p->next now references t, but the caller will drop its reference to t,
843  * so netto there is no change to the reference count of t.
844  */
845 }
u16_t tot_len
Definition: pbuf.h:90
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:73
Definition: pbuf.h:76
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
Here is the caller graph for this function:

◆ pbuf_chain()

void pbuf_chain ( struct pbuf h,
struct pbuf t 
)

Chain two pbufs (or pbuf chains) together.

The caller MUST call pbuf_free(t) once it has stopped using it. Use pbuf_cat() instead if you no longer use t.

Parameters
hhead pbuf (chain)
ttail pbuf (chain)
Note
The pbufs MUST belong to the same packet.
MAY NOT be called on a packet queue.

The ->tot_len fields of all pbufs of the head chain are adjusted. The ->next field of the last pbuf of the head chain is adjusted. The ->ref field of the first pbuf of the tail chain is adjusted.

Definition at line 864 of file pbuf.c.

References LWIP_DBG_TRACE, LWIP_DEBUGF, pbuf_cat(), PBUF_DEBUG, and pbuf_ref().

865 {
866  pbuf_cat(h, t);
867  /* t is now referenced by h */
868  pbuf_ref(t);
869  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
870 }
#define LWIP_DBG_TRACE
Definition: debug.h:56
#define PBUF_DEBUG
Definition: opt.h:1826
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
void pbuf_ref(struct pbuf *p)
Definition: pbuf.c:801
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:823
Here is the call graph for this function:

◆ pbuf_clen()

u8_t pbuf_clen ( struct pbuf p)

Count number of pbufs in a chain

Parameters
pfirst pbuf of chain
Returns
the number of pbufs in a chain

Definition at line 782 of file pbuf.c.

References pbuf::next, and NULL.

Referenced by netif_set_link_down().

783 {
784  u8_t len;
785 
786  len = 0;
787  while (p != NULL) {
788  ++len;
789  p = p->next;
790  }
791  return len;
792 }
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
unsigned char u8_t
Definition: cc.h:52
Here is the caller graph for this function:

◆ pbuf_coalesce()

struct pbuf* pbuf_coalesce ( struct pbuf p,
pbuf_layer  layer 
)

Creates a single pbuf out of a queue of pbufs.

Remarks
: Either the source pbuf 'p' is freed by this function or the original pbuf 'p' is returned, therefore the caller has to check the result!
Parameters
pthe source pbuf
layerpbuf_layer of the new pbuf
Returns
a new, single pbuf (p->next is NULL) or the old pbuf if allocation fails

Definition at line 1088 of file pbuf.c.

References ERR_ARG, ERR_OK, FOLD_U32T, pbuf::len, LWIP_ASSERT, pbuf::next, NULL, pbuf::payload, pbuf_alloc(), pbuf_copy(), pbuf_free(), PBUF_RAM, SWAP_BYTES_IN_WORD, and pbuf::tot_len.

1089 {
1090  struct pbuf *q;
1091  err_t err;
1092  if (p->next == NULL) {
1093  return p;
1094  }
1095  q = pbuf_alloc(layer, p->tot_len, PBUF_RAM);
1096  if (q == NULL) {
1097  /* @todo: what do we do now? */
1098  return p;
1099  }
1100  err = pbuf_copy(q, p);
1101  LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
1102  pbuf_free(p);
1103  return q;
1104 }
u16_t tot_len
Definition: pbuf.h:90
struct pbuf * next
Definition: pbuf.h:78
#define NULL
Definition: def.h:47
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:234
Definition: pbuf.h:58
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:685
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
Definition: pbuf.c:930
#define ERR_OK
Definition: err.h:52
Definition: pbuf.h:76
s8_t err_t
Definition: err.h:47
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
Here is the call graph for this function:

◆ pbuf_copy()

err_t pbuf_copy ( struct pbuf p_to,
struct pbuf p_from 
)

Create PBUF_RAM copies of pbufs.

Used to queue packets on behalf of the lwIP stack, such as ARP based queueing.

Note
You MUST explicitly use p = pbuf_take(p);
Only one packet is copied, no packet queue!
Parameters
p_topbuf destination of the copy
p_frompbuf source of the copy
Returns
ERR_OK if pbuf was copied ERR_ARG if one of the pbufs is NULL or p_to is not big enough to hold p_from

Definition at line 930 of file pbuf.c.

References ERR_ARG, ERR_OK, ERR_VAL, pbuf::len, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, LWIP_ERROR, MEMCPY, NULL, and PBUF_DEBUG.

Referenced by espconn_udp_sendto(), espconn_udp_sent(), netif_set_link_down(), and pbuf_coalesce().

931 {
932  u16_t offset_to=0, offset_from=0, len;
933 
934  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
935  (void*)p_to, (void*)p_from));
936 
937  /* is the target big enough to hold the source? */
938  LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
939  (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);
940 
941  /* iterate through pbuf chain */
942  do
943  {
944  LWIP_ASSERT("p_to != NULL", p_to != NULL);
945  /* copy one part of the original chain */
946  if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
947  /* complete current p_from fits into current p_to */
948  len = p_from->len - offset_from;
949  } else {
950  /* current p_from does not fit into current p_to */
951  len = p_to->len - offset_to;
952  }
953  MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len);
954  offset_to += len;
955  offset_from += len;
956  LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
957  if (offset_to == p_to->len) {
958  /* on to next p_to (if any) */
959  offset_to = 0;
960  p_to = p_to->next;
961  }
962  LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
963  if (offset_from >= p_from->len) {
964  /* on to next p_from (if any) */
965  offset_from = 0;
966  p_from = p_from->next;
967  }
968 
969  if((p_from != NULL) && (p_from->len == p_from->tot_len)) {
970  /* don't copy more than one packet! */
971  LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
972  (p_from->next == NULL), return ERR_VAL;);
973  }
974  if((p_to != NULL) && (p_to->len == p_to->tot_len)) {
975  /* don't copy more than one packet! */
976  LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
977  (p_to->next == NULL), return ERR_VAL;);
978  }
979  } while (p_from);
980  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
981  return ERR_OK;
982 }
u16_t tot_len
Definition: pbuf.h:90
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define ERR_VAL
Definition: err.h:58
#define NULL
Definition: def.h:47
#define LWIP_DBG_TRACE
Definition: debug.h:56
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:73
#define PBUF_DEBUG
Definition: opt.h:1826
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
#define ERR_OK
Definition: err.h:52
#define ERR_ARG
Definition: err.h:68
unsigned char u8_t
Definition: cc.h:52
#define MEMCPY(dst, src, len)
Definition: opt.h:84
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
void * payload
Definition: pbuf.h:81
unsigned short u16_t
Definition: cc.h:54
Here is the caller graph for this function:

◆ pbuf_copy_partial()

u16_t pbuf_copy_partial ( struct pbuf buf,
void *  dataptr,
u16_t  len,
u16_t  offset 
)

Copy (part of) the contents of a packet buffer to an application supplied buffer.

Parameters
bufthe pbuf from which to copy data
dataptrthe application supplied buffer
lenlength of data to copy (dataptr must be big enough). No more than buf->tot_len will be copied, irrespective of len
offsetoffset into the packet buffer from where to begin copying len bytes
Returns
the number of bytes copied, or 0 on failure

Definition at line 996 of file pbuf.c.

References pbuf::len, LWIP_ERROR, MEMCPY, pbuf::next, NULL, and pbuf::payload.

Referenced by espconn_client_recv(), espconn_server_recv(), and espconn_udp_recv().

997 {
998  struct pbuf *p;
999  u16_t left;
1000  u16_t buf_copy_len;
1001  u16_t copied_total = 0;
1002 
1003  LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
1004  LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
1005 
1006  left = 0;
1007 
1008  if((buf == NULL) || (dataptr == NULL)) {
1009  return 0;
1010  }
1011 
1012  /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
1013  for(p = buf; len != 0 && p != NULL; p = p->next) {
1014  if ((offset != 0) && (offset >= p->len)) {
1015  /* don't copy from this buffer -> on to the next */
1016  offset -= p->len;
1017  } else {
1018  /* copy from this buffer. maybe only partially. */
1019  buf_copy_len = p->len - offset;
1020  if (buf_copy_len > len)
1021  buf_copy_len = len;
1022  /* copy the necessary parts of the buffer */
1023  MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);
1024  copied_total += buf_copy_len;
1025  left += buf_copy_len;
1026  len -= buf_copy_len;
1027  offset = 0;
1028  }
1029  }
1030  return copied_total;
1031 }
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:73
Definition: pbuf.h:76
#define MEMCPY(dst, src, len)
Definition: opt.h:84
void * payload
Definition: pbuf.h:81
unsigned short u16_t
Definition: cc.h:54
Here is the caller graph for this function:

◆ pbuf_dechain()

struct pbuf* pbuf_dechain ( struct pbuf p)

Dechains the first pbuf from its succeeding pbufs in the chain.

Makes p->tot_len field equal to p->len.

Parameters
ppbuf to dechain
Returns
remainder of the pbuf chain, or NULL if it was de-allocated.
Note
May not be called on a packet queue.

Definition at line 881 of file pbuf.c.

References pbuf::len, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, pbuf::next, NULL, PBUF_DEBUG, pbuf_free(), and pbuf::tot_len.

882 {
883  struct pbuf *q;
884  u8_t tail_gone = 1;
885  /* tail */
886  q = p->next;
887  /* pbuf has successor in chain? */
888  if (q != NULL) {
889  /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
890  LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
891  /* enforce invariant if assertion is disabled */
892  q->tot_len = p->tot_len - p->len;
893  /* decouple pbuf from remainder */
894  p->next = NULL;
895  /* total length of pbuf p is its own length only */
896  p->tot_len = p->len;
897  /* q is no longer referenced by p, free it */
898  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
899  tail_gone = pbuf_free(q);
900  if (tail_gone > 0) {
902  ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
903  }
904  /* return remaining tail or NULL if deallocated */
905  }
906  /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
907  LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
908  return ((tail_gone > 0) ? NULL : q);
909 }
u16_t tot_len
Definition: pbuf.h:90
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
#define LWIP_DBG_TRACE
Definition: debug.h:56
#define PBUF_DEBUG
Definition: opt.h:1826
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:685
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
Definition: pbuf.h:76
unsigned char u8_t
Definition: cc.h:52
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
Here is the call graph for this function:

◆ pbuf_free()

u8_t pbuf_free ( struct pbuf p)

Dereference a pbuf chain or queue and deallocate any no-longer-used pbufs at the head of this chain or queue.

Decrements the pbuf reference count. If it reaches zero, the pbuf is deallocated.

For a pbuf chain, this is repeated for each pbuf in the chain, up to the first pbuf which has a non-zero reference count after decrementing. So, when all reference counts are one, the whole chain is free'd.

Parameters
pThe pbuf (chain) to be dereferenced.
Returns
the number of pbufs that were de-allocated from the head of the chain.
Note
MUST NOT be called on a packet queue (Not verified to work yet).
the reference counter of a pbuf equals the number of pointers that refer to the pbuf (or into the pbuf).

Definition at line 685 of file pbuf.c.

References LWIP_ASSERT, LWIP_DBG_LEVEL_SERIOUS, LWIP_DBG_TRACE, LWIP_DEBUGF, mem_free(), memp_free(), pbuf::next, NULL, PBUF_DEBUG, PBUF_FLAG_IS_CUSTOM, PBUF_POOL, PBUF_RAM, PBUF_REF, PBUF_ROM, PERF_START, PERF_STOP, pbuf::ref, SYS_ARCH_DECL_PROTECT, SYS_ARCH_PROTECT, SYS_ARCH_UNPROTECT, pbuf::type, and U16_F.

Referenced by espconn_client_recv(), espconn_server_recv(), espconn_udp_recv(), espconn_udp_sendto(), espconn_udp_sent(), handle_dhcp(), ip_input(), my_input_ap(), netif_set_link_down(), pbuf_alloc(), pbuf_coalesce(), pbuf_dechain(), pbuf_free_int(), pbuf_realloc(), send_ack(), send_nak(), and send_offer().

686 {
687  u16_t type;
688  struct pbuf *q;
689  u8_t count;
690 
691  if (p == NULL) {
692  LWIP_ASSERT("p != NULL", p != NULL);
693  /* if assertions are disabled, proceed with debug output */
695  ("pbuf_free(p == NULL) was called.\n"));
696  return 0;
697  }
698  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
699 
700  PERF_START;
701 
702  LWIP_ASSERT("pbuf_free: sane type",
703  p->type == PBUF_RAM || p->type == PBUF_ROM ||
704  p->type == PBUF_REF || p->type == PBUF_POOL
705 #ifdef EBUF_LWIP
706  || p->type == PBUF_ESF_RX
707 #endif //EBUF_LWIP
708  );
709 
710  count = 0;
711  /* de-allocate all consecutive pbufs from the head of the chain that
712  * obtain a zero reference count after decrementing*/
713  while (p != NULL) {
714  u16_t ref;
715  SYS_ARCH_DECL_PROTECT(old_level);
716  /* Since decrementing ref cannot be guaranteed to be a single machine operation
717  * we must protect it. We put the new ref into a local variable to prevent
718  * further protection. */
719  SYS_ARCH_PROTECT(old_level);
720  /* all pbufs in a chain are referenced at least once */
721  LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
722  /* decrease reference count (number of pointers to pbuf) */
723  ref = --(p->ref);
724  SYS_ARCH_UNPROTECT(old_level);
725  /* this pbuf is no longer referenced to? */
726  if (ref == 0) {
727  /* remember next pbuf in chain for next iteration */
728  q = p->next;
729  LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
730  type = p->type;
731 #if LWIP_SUPPORT_CUSTOM_PBUF
732  /* is this a custom pbuf? */
733  if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
734  struct pbuf_custom *pc = (struct pbuf_custom*)p;
735  LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
736  pc->custom_free_function(p);
737  } else
738 #endif /* LWIP_SUPPORT_CUSTOM_PBUF */
739  {
740  /* is this a pbuf from the pool? */
741  if (type == PBUF_POOL) {
742  memp_free(MEMP_PBUF_POOL, p);
743  /* is this a ROM or RAM referencing pbuf? */
744  } else if (type == PBUF_ROM || type == PBUF_REF
745 #ifdef EBUF_LWIP
746  || type == PBUF_ESF_RX
747 #endif //EBUF_LWIP
748  ) {
749 #ifdef EBUF_LWIP
750  system_pp_recycle_rx_pkt(p->eb);
751 #endif //EBUF_LWIP
752  memp_free(MEMP_PBUF, p);
753  /* type == PBUF_RAM */
754  } else {
755  mem_free(p);
756  }
757  }
758  count++;
759  /* proceed to next pbuf */
760  p = q;
761  /* p->ref > 0, this pbuf is still referenced to */
762  /* (and so the remaining pbufs in chain as well) */
763  } else {
764  LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
765  /* stop walking through the chain */
766  p = NULL;
767  }
768  }
769  PERF_STOP("pbuf_free");
770  /* return number of de-allocated pbufs */
771  return count;
772 }
void * eb
Definition: pbuf.h:109
void memp_free(memp_t type, void *mem) ICACHE_FLASH_ATTR
Definition: memp.c:438
struct pbuf * next
Definition: pbuf.h:78
#define U16_F
Definition: cc.h:61
#define NULL
Definition: def.h:47
#define PERF_STOP(x)
Definition: perf.h:38
#define LWIP_DBG_TRACE
Definition: debug.h:56
#define SYS_ARCH_DECL_PROTECT(x)
Definition: cc.h:86
Definition: pbuf.h:58
#define PERF_START
Definition: perf.h:37
#define PBUF_DEBUG
Definition: opt.h:1826
u8_t flags
Definition: pbuf.h:99
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:46
Definition: pbuf.h:76
Definition: pbuf.h:61
Definition: pbuf.h:59
#define SYS_ARCH_PROTECT(x)
Definition: cc.h:87
#define PBUF_FLAG_IS_CUSTOM
Definition: pbuf.h:72
Definition: pbuf.h:60
unsigned char u8_t
Definition: cc.h:52
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
u8_t type
Definition: pbuf.h:96
u16_t ref
Definition: pbuf.h:106
#define SYS_ARCH_UNPROTECT(x)
Definition: cc.h:88
void mem_free(void *mem) ICACHE_FLASH_ATTR
Definition: mem.c:310
unsigned short u16_t
Definition: cc.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pbuf_get_at()

u8_t pbuf_get_at ( struct pbuf p,
u16_t  offset 
)

Get one byte from the specified position in a pbuf WARNING: returns zero for offset >= p->tot_len

Parameters
ppbuf to parse
offsetoffset into p of the byte to return
Returns
byte at an offset into p OR ZERO IF 'offset' >= p->tot_len

Definition at line 1155 of file pbuf.c.

References pbuf::len, pbuf::next, NULL, and pbuf::payload.

Referenced by pbuf_memcmp().

1156 {
1157  u16_t copy_from = offset;
1158  struct pbuf* q = p;
1159 
1160  /* get the correct pbuf */
1161  while ((q != NULL) && (q->len <= copy_from)) {
1162  copy_from -= q->len;
1163  q = q->next;
1164  }
1165  /* return requested data if pbuf is OK */
1166  if ((q != NULL) && (q->len > copy_from)) {
1167  return ((u8_t*)q->payload)[copy_from];
1168  }
1169  return 0;
1170 }
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
Definition: pbuf.h:76
unsigned char u8_t
Definition: cc.h:52
void * payload
Definition: pbuf.h:81
unsigned short u16_t
Definition: cc.h:54
Here is the caller graph for this function:

◆ pbuf_header()

u8_t pbuf_header ( struct pbuf p,
s16_t  header_size_increment 
)

Adjusts the payload pointer to hide or reveal headers in the payload.

Adjusts the ->payload pointer so that space for a header (dis)appears in the pbuf payload.

The ->payload, ->tot_len and ->len fields are adjusted.

Parameters
ppbuf to change the header size.
header_size_incrementNumber of bytes to increment header size which increases the size of the pbuf. New space is on the front. (Using a negative value decreases the header size.) If hdr_size_inc is 0, this function does nothing and returns succesful.

PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so the call will fail. A check is made that the increase in header size does not move the payload pointer in front of the start of the buffer.

Returns
non-zero on failure, zero on success.

Definition at line 573 of file pbuf.c.

References EP_OFFSET, pbuf::len, LWIP_ASSERT, LWIP_DBG_LEVEL_SERIOUS, LWIP_DBG_TRACE, LWIP_DEBUGF, LWIP_ERROR, NULL, pbuf::payload, PBUF_DEBUG, PBUF_POOL, PBUF_RAM, PBUF_REF, PBUF_ROM, S16_F, SIZEOF_STRUCT_PBUF, pbuf::tot_len, and pbuf::type.

Referenced by ip_output_if().

574 {
575  u16_t type;
576  void *payload;
577  u16_t increment_magnitude;
578 
579  LWIP_ASSERT("p != NULL", p != NULL);
580  if ((header_size_increment == 0) || (p == NULL)) {
581  return 0;
582  }
583 
584  if (header_size_increment < 0){
585  increment_magnitude = -header_size_increment;
586  /* Check that we aren't going to move off the end of the pbuf */
587  LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
588  } else {
589  increment_magnitude = header_size_increment;
590 #if 0
591  /* Can't assert these as some callers speculatively call
592  pbuf_header() to see if it's OK. Will return 1 below instead. */
593  /* Check that we've got the correct type of pbuf to work with */
594  LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL",
595  p->type == PBUF_RAM || p->type == PBUF_POOL);
596  /* Check that we aren't going to move off the beginning of the pbuf */
597  LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF",
598  (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF);
599 #endif
600  }
601 
602  type = p->type;
603  /* remember current payload pointer */
604  payload = p->payload;
605 
606  /* pbuf types containing payloads? */
607  if (type == PBUF_RAM || type == PBUF_POOL) {
608  /* set new payload pointer */
609  p->payload = (u8_t *)p->payload - header_size_increment;
610  /* boundary check fails? */
611  if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF + EP_OFFSET) {
613  ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
614  (void *)p->payload, (void *)(p + 1)));
615  /* restore old payload pointer */
616  p->payload = payload;
617  /* bail out unsuccesfully */
618  return 1;
619  }
620  /* pbuf types refering to external payloads? */
621  } else if (type == PBUF_REF || type == PBUF_ROM) {
622  /* hide a header in the payload? */
623  if ((header_size_increment < 0) && (increment_magnitude <= p->len)) {
624  /* increase payload pointer */
625  p->payload = (u8_t *)p->payload - header_size_increment;
626  } else {
627  /* cannot expand payload to front (yet!)
628  * bail out unsuccesfully */
629  if (type == PBUF_REF) {
630  /* increase payload pointer */
631  p->payload = (u8_t *)p->payload - header_size_increment;
632  } else {
633  return 1;
634  }
635  }
636  } else {
637  /* Unknown type */
638  LWIP_ASSERT("bad pbuf type", 0);
639  return 1;
640  }
641  /* modify pbuf length fields */
642  p->len += header_size_increment;
643  p->tot_len += header_size_increment;
644 
645  LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n",
646  (void *)payload, (void *)p->payload, header_size_increment));
647 
648  return 0;
649 }
u16_t tot_len
Definition: pbuf.h:90
#define EP_OFFSET
Definition: pbuf.c:89
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
#define LWIP_DBG_TRACE
Definition: debug.h:56
Definition: pbuf.h:58
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:73
#define PBUF_DEBUG
Definition: opt.h:1826
#define SIZEOF_STRUCT_PBUF
Definition: pbuf.c:92
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:46
Definition: pbuf.h:61
Definition: pbuf.h:59
#define S16_F
Definition: cc.h:60
Definition: pbuf.h:60
unsigned char u8_t
Definition: cc.h:52
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
void * payload
Definition: pbuf.h:81
u8_t type
Definition: pbuf.h:96
unsigned short u16_t
Definition: cc.h:54
Here is the caller graph for this function:

◆ pbuf_memcmp()

u16_t pbuf_memcmp ( struct pbuf p,
u16_t  offset,
const void *  s2,
u16_t  n 
)

Compare pbuf contents at specified offset with memory s2, both of length n

Parameters
ppbuf to compare
offsetoffset into p at wich to start comparing
s2buffer to compare
nlength of buffer to compare
Returns
zero if equal, nonzero otherwise (0xffff if p is too short, diffoffset+1 otherwise)

Definition at line 1182 of file pbuf.c.

References pbuf::len, pbuf::next, NULL, and pbuf_get_at().

Referenced by pbuf_memfind().

1183 {
1184  u16_t start = offset;
1185  struct pbuf* q = p;
1186 
1187  /* get the correct pbuf */
1188  while ((q != NULL) && (q->len <= start)) {
1189  start -= q->len;
1190  q = q->next;
1191  }
1192  /* return requested data if pbuf is OK */
1193  if ((q != NULL) && (q->len > start)) {
1194  u16_t i;
1195  for(i = 0; i < n; i++) {
1196  u8_t a = pbuf_get_at(q, start + i);
1197  u8_t b = ((u8_t*)s2)[i];
1198  if (a != b) {
1199  return i+1;
1200  }
1201  }
1202  return 0;
1203  }
1204  return 0xffff;
1205 }
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
Definition: pbuf.h:76
u8_t pbuf_get_at(struct pbuf *p, u16_t offset)
Definition: pbuf.c:1155
unsigned char u8_t
Definition: cc.h:52
unsigned short u16_t
Definition: cc.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pbuf_memfind()

u16_t pbuf_memfind ( struct pbuf p,
const void *  mem,
u16_t  mem_len,
u16_t  start_offset 
)

Find occurrence of mem (with length mem_len) in pbuf p, starting at offset start_offset.

Parameters
ppbuf to search, maximum length is 0xFFFE since 0xFFFF is used as return value 'not found'
memsearch for the contents of this buffer
mem_lenlength of 'mem'
start_offsetoffset into p at which to start searching
Returns
0xFFFF if substr was not found in p or the index where it was found

Definition at line 1218 of file pbuf.c.

References pbuf_memcmp(), and pbuf::tot_len.

Referenced by pbuf_strstr().

1219 {
1220  u16_t i;
1221  u16_t max = p->tot_len - mem_len;
1222  if (p->tot_len >= mem_len + start_offset) {
1223  for(i = start_offset; i <= max; ) {
1224  u16_t plus = pbuf_memcmp(p, i, mem, mem_len);
1225  if (plus == 0) {
1226  return i;
1227  } else {
1228  i += plus;
1229  }
1230  }
1231  }
1232  return 0xFFFF;
1233 }
u16_t tot_len
Definition: pbuf.h:90
u16_t pbuf_memcmp(struct pbuf *p, u16_t offset, const void *s2, u16_t n)
Definition: pbuf.c:1182
Definition: mem.c:155
unsigned short u16_t
Definition: cc.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pbuf_realloc()

void pbuf_realloc ( struct pbuf p,
u16_t  new_len 
)

Shrink a pbuf chain to a desired length.

Parameters
ppbuf to shrink.
new_lendesired new length of pbuf chain

Depending on the desired length, the first few pbufs in a chain might be skipped and left unchanged. The new last pbuf in the chain will be resized, and any remaining pbufs will be freed.

Note
If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
May not be called on a packet queue.
Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain).

Definition at line 492 of file pbuf.c.

References pbuf::len, LWIP_ASSERT, mem_trim(), pbuf::next, NULL, pbuf::payload, pbuf_free(), PBUF_POOL, PBUF_RAM, PBUF_REF, PBUF_ROM, pbuf::tot_len, and pbuf::type.

Referenced by ip_input().

493 {
494  struct pbuf *q;
495  u16_t rem_len; /* remaining length */
496  s32_t grow;
497 
498  LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL);
499  LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL ||
500  p->type == PBUF_ROM ||
501  p->type == PBUF_RAM ||
502  p->type == PBUF_REF);
503 
504  /* desired length larger than current length? */
505  if (new_len >= p->tot_len) {
506  /* enlarging not yet supported */
507  return;
508  }
509 
510  /* the pbuf chain grows by (new_len - p->tot_len) bytes
511  * (which may be negative in case of shrinking) */
512  grow = new_len - p->tot_len;
513 
514  /* first, step over any pbufs that should remain in the chain */
515  rem_len = new_len;
516  q = p;
517  /* should this pbuf be kept? */
518  while (rem_len > q->len) {
519  /* decrease remaining length by pbuf length */
520  rem_len -= q->len;
521  /* decrease total length indicator */
522  LWIP_ASSERT("grow < max_u16_t", grow < 0xffff);
523  q->tot_len += (u16_t)grow;
524  /* proceed to next pbuf in chain */
525  q = q->next;
526  LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL);
527  }
528  /* we have now reached the new last pbuf (in q) */
529  /* rem_len == desired length for pbuf q */
530 
531  /* shrink allocated memory for PBUF_RAM */
532  /* (other types merely adjust their length fields */
533  if ((q->type == PBUF_RAM) && (rem_len != q->len)) {
534  /* reallocate and adjust the length of the pbuf that will be split */
535  q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len);
536  LWIP_ASSERT("mem_trim returned q == NULL", q != NULL);
537  }
538  /* adjust length fields for new last pbuf */
539  q->len = rem_len;
540  q->tot_len = q->len;
541 
542  /* any remaining pbufs in chain? */
543  if (q->next != NULL) {
544  /* free remaining pbufs in chain */
545  pbuf_free(q->next);
546  }
547  /* q is last packet in chain */
548  q->next = NULL;
549 
550 }
u16_t tot_len
Definition: pbuf.h:90
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
Definition: pbuf.h:58
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:685
Definition: pbuf.h:76
Definition: pbuf.h:61
Definition: pbuf.h:59
void * mem_trim(void *mem, mem_size_t size) ICACHE_FLASH_ATTR
Definition: mem.c:368
Definition: pbuf.h:60
unsigned char u8_t
Definition: cc.h:52
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
void * payload
Definition: pbuf.h:81
signed long s32_t
Definition: cc.h:57
u8_t type
Definition: pbuf.h:96
unsigned short u16_t
Definition: cc.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pbuf_ref()

void pbuf_ref ( struct pbuf p)

Increment the reference count of the pbuf.

Parameters
ppbuf to increase reference counter of

Definition at line 801 of file pbuf.c.

References NULL, pbuf::ref, SYS_ARCH_DECL_PROTECT, SYS_ARCH_PROTECT, and SYS_ARCH_UNPROTECT.

Referenced by pbuf_chain().

802 {
803  SYS_ARCH_DECL_PROTECT(old_level);
804  /* pbuf given? */
805  if (p != NULL) {
806  SYS_ARCH_PROTECT(old_level);
807  ++(p->ref);
808  SYS_ARCH_UNPROTECT(old_level);
809  }
810 }
#define NULL
Definition: def.h:47
#define SYS_ARCH_DECL_PROTECT(x)
Definition: cc.h:86
#define SYS_ARCH_PROTECT(x)
Definition: cc.h:87
u16_t ref
Definition: pbuf.h:106
#define SYS_ARCH_UNPROTECT(x)
Definition: cc.h:88
Here is the caller graph for this function:

◆ pbuf_strstr()

u16_t pbuf_strstr ( struct pbuf p,
const char *  substr 
)

Find occurrence of substr with length substr_len in pbuf p, start at offset start_offset WARNING: in contrast to strstr(), this one does not stop at the first \0 in the pbuf/source string!

Parameters
ppbuf to search, maximum length is 0xFFFE since 0xFFFF is used as return value 'not found'
substrstring to search for in p, maximum length is 0xFFFE
Returns
0xFFFF if substr was not found in p or the index where it was found

Definition at line 1246 of file pbuf.c.

References NULL, os_strlen, pbuf_memfind(), and pbuf::tot_len.

1247 {
1248  size_t substr_len;
1249  if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
1250  return 0xFFFF;
1251  }
1252  substr_len = os_strlen(substr);
1253  if (substr_len >= 0xFFFF) {
1254  return 0xFFFF;
1255  }
1256  return pbuf_memfind(p, substr, (u16_t)substr_len, 0);
1257 }
u16_t tot_len
Definition: pbuf.h:90
#define NULL
Definition: def.h:47
#define os_strlen
Definition: osapi.h:43
u16_t pbuf_memfind(struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)
Definition: pbuf.c:1218
unsigned short u16_t
Definition: cc.h:54
Here is the call graph for this function:

◆ pbuf_take()

err_t pbuf_take ( struct pbuf buf,
const void *  dataptr,
u16_t  len 
)

Copy application supplied data into a pbuf. This function can only be used to copy the equivalent of buf->tot_len data.

Parameters
bufpbuf to fill with data
dataptrapplication supplied data buffer
lenlength of the application supplied data buffer
Returns
ERR_OK if successful, ERR_MEM if the pbuf is not big enough

Definition at line 1044 of file pbuf.c.

References ERR_ARG, ERR_OK, pbuf::len, LWIP_ASSERT, LWIP_ERROR, MEMCPY, pbuf::next, NULL, pbuf::payload, and pbuf::tot_len.

1045 {
1046  struct pbuf *p;
1047  u16_t buf_copy_len;
1048  u16_t total_copy_len = len;
1049  u16_t copied_total = 0;
1050 
1051  LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;);
1052  LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;);
1053 
1054  if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {
1055  return ERR_ARG;
1056  }
1057 
1058  /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
1059  for(p = buf; total_copy_len != 0; p = p->next) {
1060  LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);
1061  buf_copy_len = total_copy_len;
1062  if (buf_copy_len > p->len) {
1063  /* this pbuf cannot hold all remaining data */
1064  buf_copy_len = p->len;
1065  }
1066  /* copy the necessary parts of the buffer */
1067  MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len);
1068  total_copy_len -= buf_copy_len;
1069  copied_total += buf_copy_len;
1070  }
1071  LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);
1072  return ERR_OK;
1073 }
u16_t tot_len
Definition: pbuf.h:90
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
#define NULL
Definition: def.h:47
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:73
#define ERR_OK
Definition: err.h:52
Definition: pbuf.h:76
#define ERR_ARG
Definition: err.h:68
#define MEMCPY(dst, src, len)
Definition: opt.h:84
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
void * payload
Definition: pbuf.h:81
unsigned short u16_t
Definition: cc.h:54