pbuf.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. /**
  2. * @file
  3. * Packet buffer management
  4. *
  5. * Packets are built from the pbuf data structure. It supports dynamic
  6. * memory allocation for packet contents or can reference externally
  7. * managed packet contents both in RAM and ROM. Quick allocation for
  8. * incoming packets is provided through pools with fixed sized pbufs.
  9. *
  10. * A packet may span over multiple pbufs, chained as a singly linked
  11. * list. This is called a "pbuf chain".
  12. *
  13. * Multiple packets may be queued, also using this singly linked list.
  14. * This is called a "packet queue".
  15. *
  16. * So, a packet queue consists of one or more pbuf chains, each of
  17. * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE
  18. * NOT SUPPORTED!!! Use helper structs to queue multiple packets.
  19. *
  20. * The differences between a pbuf chain and a packet queue are very
  21. * precise but subtle.
  22. *
  23. * The last pbuf of a packet has a ->tot_len field that equals the
  24. * ->len field. It can be found by traversing the list. If the last
  25. * pbuf of a packet has a ->next field other than NULL, more packets
  26. * are on the queue.
  27. *
  28. * Therefore, looping through a pbuf of a single packet, has an
  29. * loop end condition (tot_len == p->len), NOT (next == NULL).
  30. */
  31. /*
  32. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  33. * All rights reserved.
  34. *
  35. * Redistribution and use in source and binary forms, with or without modification,
  36. * are permitted provided that the following conditions are met:
  37. *
  38. * 1. Redistributions of source code must retain the above copyright notice,
  39. * this list of conditions and the following disclaimer.
  40. * 2. Redistributions in binary form must reproduce the above copyright notice,
  41. * this list of conditions and the following disclaimer in the documentation
  42. * and/or other materials provided with the distribution.
  43. * 3. The name of the author may not be used to endorse or promote products
  44. * derived from this software without specific prior written permission.
  45. *
  46. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  47. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  48. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  49. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  50. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  51. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  52. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  53. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  54. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  55. * OF SUCH DAMAGE.
  56. *
  57. * This file is part of the lwIP TCP/IP stack.
  58. *
  59. * Author: Adam Dunkels <adam@sics.se>
  60. *
  61. */
  62. #include "lwip/opt.h"
  63. #include "lwip/stats.h"
  64. #include "lwip/def.h"
  65. #include "lwip/mem.h"
  66. #include "lwip/memp.h"
  67. #include "lwip/pbuf.h"
  68. #include "lwip/sys.h"
  69. #include "arch/perf.h"
  70. #if TCP_QUEUE_OOSEQ
  71. #include "lwip/tcp_impl.h"
  72. #endif
  73. #if LWIP_CHECKSUM_ON_COPY
  74. #include "lwip/inet_chksum.h"
  75. #endif
  76. #include <string.h>
  77. #define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
  78. /* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically
  79. aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
  80. #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
  81. #if !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS
  82. #define PBUF_POOL_IS_EMPTY()
  83. #else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
  84. /** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
  85. #ifndef PBUF_POOL_FREE_OOSEQ
  86. #define PBUF_POOL_FREE_OOSEQ 1
  87. #endif /* PBUF_POOL_FREE_OOSEQ */
  88. #if PBUF_POOL_FREE_OOSEQ
  89. #include "lwip/tcpip.h"
  90. #define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
  91. static u8_t pbuf_free_ooseq_queued;
  92. /**
  93. * Attempt to reclaim some memory from queued out-of-sequence TCP segments
  94. * if we run out of pool pbufs. It's better to give priority to new packets
  95. * if we're running out.
  96. *
  97. * This must be done in the correct thread context therefore this function
  98. * can only be used with NO_SYS=0 and through tcpip_callback.
  99. */
  100. static void
  101. pbuf_free_ooseq(void* arg)
  102. {
  103. struct tcp_pcb* pcb;
  104. SYS_ARCH_DECL_PROTECT(old_level);
  105. LWIP_UNUSED_ARG(arg);
  106. SYS_ARCH_PROTECT(old_level);
  107. pbuf_free_ooseq_queued = 0;
  108. SYS_ARCH_UNPROTECT(old_level);
  109. for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
  110. if (NULL != pcb->ooseq) {
  111. /** Free the ooseq pbufs of one PCB only */
  112. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
  113. tcp_segs_free(pcb->ooseq);
  114. pcb->ooseq = NULL;
  115. return;
  116. }
  117. }
  118. }
  119. /** Queue a call to pbuf_free_ooseq if not already queued. */
  120. static void
  121. pbuf_pool_is_empty(void)
  122. {
  123. u8_t queued;
  124. SYS_ARCH_DECL_PROTECT(old_level);
  125. SYS_ARCH_PROTECT(old_level);
  126. queued = pbuf_free_ooseq_queued;
  127. pbuf_free_ooseq_queued = 1;
  128. SYS_ARCH_UNPROTECT(old_level);
  129. if(!queued) {
  130. /* queue a call to pbuf_free_ooseq if not already queued */
  131. if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) {
  132. SYS_ARCH_PROTECT(old_level);
  133. pbuf_free_ooseq_queued = 0;
  134. SYS_ARCH_UNPROTECT(old_level);
  135. }
  136. }
  137. }
  138. #endif /* PBUF_POOL_FREE_OOSEQ */
  139. #endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
  140. /**
  141. * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
  142. *
  143. * The actual memory allocated for the pbuf is determined by the
  144. * layer at which the pbuf is allocated and the requested size
  145. * (from the size parameter).
  146. *
  147. * @param layer flag to define header size
  148. * @param length size of the pbuf's payload
  149. * @param type this parameter decides how and where the pbuf
  150. * should be allocated as follows:
  151. *
  152. * - PBUF_RAM: buffer memory for pbuf is allocated as one large
  153. * chunk. This includes protocol headers as well.
  154. * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for
  155. * protocol headers. Additional headers must be prepended
  156. * by allocating another pbuf and chain in to the front of
  157. * the ROM pbuf. It is assumed that the memory used is really
  158. * similar to ROM in that it is immutable and will not be
  159. * changed. Memory which is dynamic should generally not
  160. * be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
  161. * - PBUF_REF: no buffer memory is allocated for the pbuf, even for
  162. * protocol headers. It is assumed that the pbuf is only
  163. * being used in a single thread. If the pbuf gets queued,
  164. * then pbuf_take should be called to copy the buffer.
  165. * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
  166. * the pbuf pool that is allocated during pbuf_init().
  167. *
  168. * @return the allocated pbuf. If multiple pbufs where allocated, this
  169. * is the first pbuf of a pbuf chain.
  170. */
  171. struct pbuf *
  172. pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
  173. {
  174. struct pbuf *p, *q, *r;
  175. u16_t offset;
  176. s32_t rem_len; /* remaining length */
  177. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
  178. /* determine header offset */
  179. offset = 0;
  180. switch (layer) {
  181. case PBUF_TRANSPORT:
  182. /* add room for transport (often TCP) layer header */
  183. offset += PBUF_TRANSPORT_HLEN;
  184. /* FALLTHROUGH */
  185. case PBUF_IP:
  186. /* add room for IP layer header */
  187. offset += PBUF_IP_HLEN;
  188. /* FALLTHROUGH */
  189. case PBUF_LINK:
  190. /* add room for link layer header */
  191. offset += PBUF_LINK_HLEN;
  192. break;
  193. case PBUF_RAW:
  194. break;
  195. default:
  196. LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
  197. return NULL;
  198. }
  199. switch (type) {
  200. case PBUF_POOL:
  201. /* allocate head of pbuf chain into p */
  202. p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
  203. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
  204. if (p == NULL) {
  205. PBUF_POOL_IS_EMPTY();
  206. return NULL;
  207. }
  208. p->type = type;
  209. p->next = NULL;
  210. /* make the payload pointer point 'offset' bytes into pbuf data memory */
  211. p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)));
  212. LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
  213. ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
  214. /* the total length of the pbuf chain is the requested size */
  215. p->tot_len = length;
  216. /* set the length of the first pbuf in the chain */
  217. p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset));
  218. LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
  219. ((u8_t*)p->payload + p->len <=
  220. (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED));
  221. LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT",
  222. (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 );
  223. /* set reference count (needed here in case we fail) */
  224. p->ref = 1;
  225. /* now allocate the tail of the pbuf chain */
  226. /* remember first pbuf for linkage in next iteration */
  227. r = p;
  228. /* remaining length to be allocated */
  229. rem_len = length - p->len;
  230. /* any remaining pbufs to be allocated? */
  231. while (rem_len > 0) {
  232. q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
  233. if (q == NULL) {
  234. PBUF_POOL_IS_EMPTY();
  235. /* free chain so far allocated */
  236. pbuf_free(p);
  237. /* bail out unsuccesfully */
  238. return NULL;
  239. }
  240. q->type = type;
  241. q->flags = 0;
  242. q->next = NULL;
  243. /* make previous pbuf point to this pbuf */
  244. r->next = q;
  245. /* set total length of this pbuf and next in chain */
  246. LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff);
  247. q->tot_len = (u16_t)rem_len;
  248. /* this pbuf length is pool size, unless smaller sized tail */
  249. q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED);
  250. q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF);
  251. LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
  252. ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
  253. LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
  254. ((u8_t*)p->payload + p->len <=
  255. (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED));
  256. q->ref = 1;
  257. /* calculate remaining length to be allocated */
  258. rem_len -= q->len;
  259. /* remember this pbuf for linkage in next iteration */
  260. r = q;
  261. }
  262. /* end of chain */
  263. /*r->next = NULL;*/
  264. break;
  265. case PBUF_RAM:
  266. /* If pbuf is to be allocated in RAM, allocate memory for it. */
  267. p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
  268. if (p == NULL) {
  269. return NULL;
  270. }
  271. /* Set up internal structure of the pbuf. */
  272. p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset));
  273. p->len = p->tot_len = length;
  274. p->next = NULL;
  275. p->type = type;
  276. LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
  277. ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
  278. break;
  279. /* pbuf references existing (non-volatile static constant) ROM payload? */
  280. case PBUF_ROM:
  281. /* pbuf references existing (externally allocated) RAM payload? */
  282. case PBUF_REF:
  283. /* only allocate memory for the pbuf structure */
  284. p = (struct pbuf *)memp_malloc(MEMP_PBUF);
  285. if (p == NULL) {
  286. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
  287. ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
  288. (type == PBUF_ROM) ? "ROM" : "REF"));
  289. return NULL;
  290. }
  291. /* caller must set this field properly, afterwards */
  292. p->payload = NULL;
  293. p->len = p->tot_len = length;
  294. p->next = NULL;
  295. p->type = type;
  296. break;
  297. default:
  298. LWIP_ASSERT("pbuf_alloc: erroneous type", 0);
  299. return NULL;
  300. }
  301. /* set reference count */
  302. p->ref = 1;
  303. /* set flags */
  304. p->flags = 0;
  305. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
  306. return p;
  307. }
  308. #if LWIP_SUPPORT_CUSTOM_PBUF
  309. /** Initialize a custom pbuf (already allocated).
  310. *
  311. * @param layer flag to define header size
  312. * @param length size of the pbuf's payload
  313. * @param type type of the pbuf (only used to treat the pbuf accordingly, as
  314. * this function allocates no memory)
  315. * @param p pointer to the custom pbuf to initialize (already allocated)
  316. * @param payload_mem pointer to the buffer that is used for payload and headers,
  317. * must be at least big enough to hold 'length' plus the header size,
  318. * may be NULL if set later
  319. * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least
  320. * big enough to hold 'length' plus the header size
  321. */
  322. struct pbuf*
  323. pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p,
  324. void *payload_mem, u16_t payload_mem_len)
  325. {
  326. u16_t offset;
  327. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
  328. /* determine header offset */
  329. offset = 0;
  330. switch (l) {
  331. case PBUF_TRANSPORT:
  332. /* add room for transport (often TCP) layer header */
  333. offset += PBUF_TRANSPORT_HLEN;
  334. /* FALLTHROUGH */
  335. case PBUF_IP:
  336. /* add room for IP layer header */
  337. offset += PBUF_IP_HLEN;
  338. /* FALLTHROUGH */
  339. case PBUF_LINK:
  340. /* add room for link layer header */
  341. offset += PBUF_LINK_HLEN;
  342. break;
  343. case PBUF_RAW:
  344. break;
  345. default:
  346. LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
  347. return NULL;
  348. }
  349. if (LWIP_MEM_ALIGN_SIZE(offset) + length < payload_mem_len) {
  350. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length));
  351. return NULL;
  352. }
  353. p->pbuf.next = NULL;
  354. if (payload_mem != NULL) {
  355. p->pbuf.payload = LWIP_MEM_ALIGN((void *)((u8_t *)payload_mem + offset));
  356. } else {
  357. p->pbuf.payload = NULL;
  358. }
  359. p->pbuf.flags = PBUF_FLAG_IS_CUSTOM;
  360. p->pbuf.len = p->pbuf.tot_len = length;
  361. p->pbuf.type = type;
  362. p->pbuf.ref = 1;
  363. return &p->pbuf;
  364. }
  365. #endif /* LWIP_SUPPORT_CUSTOM_PBUF */
  366. /**
  367. * Shrink a pbuf chain to a desired length.
  368. *
  369. * @param p pbuf to shrink.
  370. * @param new_len desired new length of pbuf chain
  371. *
  372. * Depending on the desired length, the first few pbufs in a chain might
  373. * be skipped and left unchanged. The new last pbuf in the chain will be
  374. * resized, and any remaining pbufs will be freed.
  375. *
  376. * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
  377. * @note May not be called on a packet queue.
  378. *
  379. * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain).
  380. */
  381. void
  382. pbuf_realloc(struct pbuf *p, u16_t new_len)
  383. {
  384. struct pbuf *q;
  385. u16_t rem_len; /* remaining length */
  386. s32_t grow;
  387. LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL);
  388. LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL ||
  389. p->type == PBUF_ROM ||
  390. p->type == PBUF_RAM ||
  391. p->type == PBUF_REF);
  392. /* desired length larger than current length? */
  393. if (new_len >= p->tot_len) {
  394. /* enlarging not yet supported */
  395. return;
  396. }
  397. /* the pbuf chain grows by (new_len - p->tot_len) bytes
  398. * (which may be negative in case of shrinking) */
  399. grow = new_len - p->tot_len;
  400. /* first, step over any pbufs that should remain in the chain */
  401. rem_len = new_len;
  402. q = p;
  403. /* should this pbuf be kept? */
  404. while (rem_len > q->len) {
  405. /* decrease remaining length by pbuf length */
  406. rem_len -= q->len;
  407. /* decrease total length indicator */
  408. LWIP_ASSERT("grow < max_u16_t", grow < 0xffff);
  409. q->tot_len += (u16_t)grow;
  410. /* proceed to next pbuf in chain */
  411. q = q->next;
  412. LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL);
  413. }
  414. /* we have now reached the new last pbuf (in q) */
  415. /* rem_len == desired length for pbuf q */
  416. /* shrink allocated memory for PBUF_RAM */
  417. /* (other types merely adjust their length fields */
  418. if ((q->type == PBUF_RAM) && (rem_len != q->len)) {
  419. /* reallocate and adjust the length of the pbuf that will be split */
  420. q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len);
  421. LWIP_ASSERT("mem_trim returned q == NULL", q != NULL);
  422. }
  423. /* adjust length fields for new last pbuf */
  424. q->len = rem_len;
  425. q->tot_len = q->len;
  426. /* any remaining pbufs in chain? */
  427. if (q->next != NULL) {
  428. /* free remaining pbufs in chain */
  429. pbuf_free(q->next);
  430. }
  431. /* q is last packet in chain */
  432. q->next = NULL;
  433. }
  434. /**
  435. * Adjusts the payload pointer to hide or reveal headers in the payload.
  436. *
  437. * Adjusts the ->payload pointer so that space for a header
  438. * (dis)appears in the pbuf payload.
  439. *
  440. * The ->payload, ->tot_len and ->len fields are adjusted.
  441. *
  442. * @param p pbuf to change the header size.
  443. * @param header_size_increment Number of bytes to increment header size which
  444. * increases the size of the pbuf. New space is on the front.
  445. * (Using a negative value decreases the header size.)
  446. * If hdr_size_inc is 0, this function does nothing and returns succesful.
  447. *
  448. * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
  449. * the call will fail. A check is made that the increase in header size does
  450. * not move the payload pointer in front of the start of the buffer.
  451. * @return non-zero on failure, zero on success.
  452. *
  453. */
  454. u8_t
  455. pbuf_header(struct pbuf *p, s16_t header_size_increment)
  456. {
  457. u16_t type;
  458. void *payload;
  459. u16_t increment_magnitude;
  460. LWIP_ASSERT("p != NULL", p != NULL);
  461. if ((header_size_increment == 0) || (p == NULL)) {
  462. return 0;
  463. }
  464. if (header_size_increment < 0){
  465. increment_magnitude = -header_size_increment;
  466. /* Check that we aren't going to move off the end of the pbuf */
  467. LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
  468. } else {
  469. increment_magnitude = header_size_increment;
  470. #if 0
  471. /* Can't assert these as some callers speculatively call
  472. pbuf_header() to see if it's OK. Will return 1 below instead. */
  473. /* Check that we've got the correct type of pbuf to work with */
  474. LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL",
  475. p->type == PBUF_RAM || p->type == PBUF_POOL);
  476. /* Check that we aren't going to move off the beginning of the pbuf */
  477. LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF",
  478. (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF);
  479. #endif
  480. }
  481. type = p->type;
  482. /* remember current payload pointer */
  483. payload = p->payload;
  484. /* pbuf types containing payloads? */
  485. if (type == PBUF_RAM || type == PBUF_POOL) {
  486. /* set new payload pointer */
  487. p->payload = (u8_t *)p->payload - header_size_increment;
  488. /* boundary check fails? */
  489. if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) {
  490. LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
  491. ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
  492. (void *)p->payload, (void *)(p + 1)));
  493. /* restore old payload pointer */
  494. p->payload = payload;
  495. /* bail out unsuccesfully */
  496. return 1;
  497. }
  498. /* pbuf types refering to external payloads? */
  499. } else if (type == PBUF_REF || type == PBUF_ROM) {
  500. /* hide a header in the payload? */
  501. if ((header_size_increment < 0) && (increment_magnitude <= p->len)) {
  502. /* increase payload pointer */
  503. p->payload = (u8_t *)p->payload - header_size_increment;
  504. } else {
  505. /* cannot expand payload to front (yet!)
  506. * bail out unsuccesfully */
  507. return 1;
  508. }
  509. } else {
  510. /* Unknown type */
  511. LWIP_ASSERT("bad pbuf type", 0);
  512. return 1;
  513. }
  514. /* modify pbuf length fields */
  515. p->len += header_size_increment;
  516. p->tot_len += header_size_increment;
  517. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n",
  518. (void *)payload, (void *)p->payload, header_size_increment));
  519. return 0;
  520. }
  521. /**
  522. * Dereference a pbuf chain or queue and deallocate any no-longer-used
  523. * pbufs at the head of this chain or queue.
  524. *
  525. * Decrements the pbuf reference count. If it reaches zero, the pbuf is
  526. * deallocated.
  527. *
  528. * For a pbuf chain, this is repeated for each pbuf in the chain,
  529. * up to the first pbuf which has a non-zero reference count after
  530. * decrementing. So, when all reference counts are one, the whole
  531. * chain is free'd.
  532. *
  533. * @param p The pbuf (chain) to be dereferenced.
  534. *
  535. * @return the number of pbufs that were de-allocated
  536. * from the head of the chain.
  537. *
  538. * @note MUST NOT be called on a packet queue (Not verified to work yet).
  539. * @note the reference counter of a pbuf equals the number of pointers
  540. * that refer to the pbuf (or into the pbuf).
  541. *
  542. * @internal examples:
  543. *
  544. * Assuming existing chains a->b->c with the following reference
  545. * counts, calling pbuf_free(a) results in:
  546. *
  547. * 1->2->3 becomes ...1->3
  548. * 3->3->3 becomes 2->3->3
  549. * 1->1->2 becomes ......1
  550. * 2->1->1 becomes 1->1->1
  551. * 1->1->1 becomes .......
  552. *
  553. */
  554. u8_t
  555. pbuf_free(struct pbuf *p)
  556. {
  557. u16_t type;
  558. struct pbuf *q;
  559. u8_t count;
  560. if (p == NULL) {
  561. LWIP_ASSERT("p != NULL", p != NULL);
  562. /* if assertions are disabled, proceed with debug output */
  563. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
  564. ("pbuf_free(p == NULL) was called.\n"));
  565. return 0;
  566. }
  567. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
  568. PERF_START;
  569. LWIP_ASSERT("pbuf_free: sane type",
  570. p->type == PBUF_RAM || p->type == PBUF_ROM ||
  571. p->type == PBUF_REF || p->type == PBUF_POOL);
  572. count = 0;
  573. /* de-allocate all consecutive pbufs from the head of the chain that
  574. * obtain a zero reference count after decrementing*/
  575. while (p != NULL) {
  576. u16_t ref;
  577. SYS_ARCH_DECL_PROTECT(old_level);
  578. /* Since decrementing ref cannot be guaranteed to be a single machine operation
  579. * we must protect it. We put the new ref into a local variable to prevent
  580. * further protection. */
  581. SYS_ARCH_PROTECT(old_level);
  582. /* all pbufs in a chain are referenced at least once */
  583. LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
  584. /* decrease reference count (number of pointers to pbuf) */
  585. ref = --(p->ref);
  586. SYS_ARCH_UNPROTECT(old_level);
  587. /* this pbuf is no longer referenced to? */
  588. if (ref == 0) {
  589. /* remember next pbuf in chain for next iteration */
  590. q = p->next;
  591. LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
  592. type = p->type;
  593. #if LWIP_SUPPORT_CUSTOM_PBUF
  594. /* is this a custom pbuf? */
  595. if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
  596. struct pbuf_custom *pc = (struct pbuf_custom*)p;
  597. LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
  598. pc->custom_free_function(p);
  599. } else
  600. #endif /* LWIP_SUPPORT_CUSTOM_PBUF */
  601. {
  602. /* is this a pbuf from the pool? */
  603. if (type == PBUF_POOL) {
  604. memp_free(MEMP_PBUF_POOL, p);
  605. /* is this a ROM or RAM referencing pbuf? */
  606. } else if (type == PBUF_ROM || type == PBUF_REF) {
  607. memp_free(MEMP_PBUF, p);
  608. /* type == PBUF_RAM */
  609. } else {
  610. mem_free(p);
  611. }
  612. }
  613. count++;
  614. /* proceed to next pbuf */
  615. p = q;
  616. /* p->ref > 0, this pbuf is still referenced to */
  617. /* (and so the remaining pbufs in chain as well) */
  618. } else {
  619. LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
  620. /* stop walking through the chain */
  621. p = NULL;
  622. }
  623. }
  624. PERF_STOP("pbuf_free");
  625. /* return number of de-allocated pbufs */
  626. return count;
  627. }
  628. /**
  629. * Count number of pbufs in a chain
  630. *
  631. * @param p first pbuf of chain
  632. * @return the number of pbufs in a chain
  633. */
  634. u8_t
  635. pbuf_clen(struct pbuf *p)
  636. {
  637. u8_t len;
  638. len = 0;
  639. while (p != NULL) {
  640. ++len;
  641. p = p->next;
  642. }
  643. return len;
  644. }
  645. /**
  646. * Increment the reference count of the pbuf.
  647. *
  648. * @param p pbuf to increase reference counter of
  649. *
  650. */
  651. void
  652. pbuf_ref(struct pbuf *p)
  653. {
  654. SYS_ARCH_DECL_PROTECT(old_level);
  655. /* pbuf given? */
  656. if (p != NULL) {
  657. SYS_ARCH_PROTECT(old_level);
  658. ++(p->ref);
  659. SYS_ARCH_UNPROTECT(old_level);
  660. }
  661. }
  662. /**
  663. * Concatenate two pbufs (each may be a pbuf chain) and take over
  664. * the caller's reference of the tail pbuf.
  665. *
  666. * @note The caller MAY NOT reference the tail pbuf afterwards.
  667. * Use pbuf_chain() for that purpose.
  668. *
  669. * @see pbuf_chain()
  670. */
  671. void
  672. pbuf_cat(struct pbuf *h, struct pbuf *t)
  673. {
  674. struct pbuf *p;
  675. LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)",
  676. ((h != NULL) && (t != NULL)), return;);
  677. /* proceed to last pbuf of chain */
  678. for (p = h; p->next != NULL; p = p->next) {
  679. /* add total length of second chain to all totals of first chain */
  680. p->tot_len += t->tot_len;
  681. }
  682. /* { p is last pbuf of first h chain, p->next == NULL } */
  683. LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
  684. LWIP_ASSERT("p->next == NULL", p->next == NULL);
  685. /* add total length of second chain to last pbuf total of first chain */
  686. p->tot_len += t->tot_len;
  687. /* chain last pbuf of head (p) with first of tail (t) */
  688. p->next = t;
  689. /* p->next now references t, but the caller will drop its reference to t,
  690. * so netto there is no change to the reference count of t.
  691. */
  692. }
  693. /**
  694. * Chain two pbufs (or pbuf chains) together.
  695. *
  696. * The caller MUST call pbuf_free(t) once it has stopped
  697. * using it. Use pbuf_cat() instead if you no longer use t.
  698. *
  699. * @param h head pbuf (chain)
  700. * @param t tail pbuf (chain)
  701. * @note The pbufs MUST belong to the same packet.
  702. * @note MAY NOT be called on a packet queue.
  703. *
  704. * The ->tot_len fields of all pbufs of the head chain are adjusted.
  705. * The ->next field of the last pbuf of the head chain is adjusted.
  706. * The ->ref field of the first pbuf of the tail chain is adjusted.
  707. *
  708. */
  709. void
  710. pbuf_chain(struct pbuf *h, struct pbuf *t)
  711. {
  712. pbuf_cat(h, t);
  713. /* t is now referenced by h */
  714. pbuf_ref(t);
  715. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
  716. }
  717. /**
  718. * Dechains the first pbuf from its succeeding pbufs in the chain.
  719. *
  720. * Makes p->tot_len field equal to p->len.
  721. * @param p pbuf to dechain
  722. * @return remainder of the pbuf chain, or NULL if it was de-allocated.
  723. * @note May not be called on a packet queue.
  724. */
  725. struct pbuf *
  726. pbuf_dechain(struct pbuf *p)
  727. {
  728. struct pbuf *q;
  729. u8_t tail_gone = 1;
  730. /* tail */
  731. q = p->next;
  732. /* pbuf has successor in chain? */
  733. if (q != NULL) {
  734. /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
  735. LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
  736. /* enforce invariant if assertion is disabled */
  737. q->tot_len = p->tot_len - p->len;
  738. /* decouple pbuf from remainder */
  739. p->next = NULL;
  740. /* total length of pbuf p is its own length only */
  741. p->tot_len = p->len;
  742. /* q is no longer referenced by p, free it */
  743. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
  744. tail_gone = pbuf_free(q);
  745. if (tail_gone > 0) {
  746. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE,
  747. ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
  748. }
  749. /* return remaining tail or NULL if deallocated */
  750. }
  751. /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
  752. LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
  753. return ((tail_gone > 0) ? NULL : q);
  754. }
  755. /**
  756. *
  757. * Create PBUF_RAM copies of pbufs.
  758. *
  759. * Used to queue packets on behalf of the lwIP stack, such as
  760. * ARP based queueing.
  761. *
  762. * @note You MUST explicitly use p = pbuf_take(p);
  763. *
  764. * @note Only one packet is copied, no packet queue!
  765. *
  766. * @param p_to pbuf destination of the copy
  767. * @param p_from pbuf source of the copy
  768. *
  769. * @return ERR_OK if pbuf was copied
  770. * ERR_ARG if one of the pbufs is NULL or p_to is not big
  771. * enough to hold p_from
  772. */
  773. err_t
  774. pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
  775. {
  776. u16_t offset_to=0, offset_from=0, len;
  777. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
  778. (void*)p_to, (void*)p_from));
  779. /* is the target big enough to hold the source? */
  780. LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
  781. (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);
  782. /* iterate through pbuf chain */
  783. do
  784. {
  785. LWIP_ASSERT("p_to != NULL", p_to != NULL);
  786. /* copy one part of the original chain */
  787. if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
  788. /* complete current p_from fits into current p_to */
  789. len = p_from->len - offset_from;
  790. } else {
  791. /* current p_from does not fit into current p_to */
  792. len = p_to->len - offset_to;
  793. }
  794. MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len);
  795. offset_to += len;
  796. offset_from += len;
  797. LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
  798. if (offset_to == p_to->len) {
  799. /* on to next p_to (if any) */
  800. offset_to = 0;
  801. p_to = p_to->next;
  802. }
  803. LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
  804. if (offset_from >= p_from->len) {
  805. /* on to next p_from (if any) */
  806. offset_from = 0;
  807. p_from = p_from->next;
  808. }
  809. if((p_from != NULL) && (p_from->len == p_from->tot_len)) {
  810. /* don't copy more than one packet! */
  811. LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
  812. (p_from->next == NULL), return ERR_VAL;);
  813. }
  814. if((p_to != NULL) && (p_to->len == p_to->tot_len)) {
  815. /* don't copy more than one packet! */
  816. LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
  817. (p_to->next == NULL), return ERR_VAL;);
  818. }
  819. } while (p_from);
  820. LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
  821. return ERR_OK;
  822. }
  823. /**
  824. * Copy (part of) the contents of a packet buffer
  825. * to an application supplied buffer.
  826. *
  827. * @param buf the pbuf from which to copy data
  828. * @param dataptr the application supplied buffer
  829. * @param len length of data to copy (dataptr must be big enough). No more
  830. * than buf->tot_len will be copied, irrespective of len
  831. * @param offset offset into the packet buffer from where to begin copying len bytes
  832. * @return the number of bytes copied, or 0 on failure
  833. */
  834. u16_t
  835. pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
  836. {
  837. struct pbuf *p;
  838. u16_t left;
  839. u16_t buf_copy_len;
  840. u16_t copied_total = 0;
  841. LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
  842. LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
  843. left = 0;
  844. if((buf == NULL) || (dataptr == NULL)) {
  845. return 0;
  846. }
  847. /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
  848. for(p = buf; len != 0 && p != NULL; p = p->next) {
  849. if ((offset != 0) && (offset >= p->len)) {
  850. /* don't copy from this buffer -> on to the next */
  851. offset -= p->len;
  852. } else {
  853. /* copy from this buffer. maybe only partially. */
  854. buf_copy_len = p->len - offset;
  855. if (buf_copy_len > len)
  856. buf_copy_len = len;
  857. /* copy the necessary parts of the buffer */
  858. MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);
  859. copied_total += buf_copy_len;
  860. left += buf_copy_len;
  861. len -= buf_copy_len;
  862. offset = 0;
  863. }
  864. }
  865. return copied_total;
  866. }
  867. /**
  868. * Copy application supplied data into a pbuf.
  869. * This function can only be used to copy the equivalent of buf->tot_len data.
  870. *
  871. * @param buf pbuf to fill with data
  872. * @param dataptr application supplied data buffer
  873. * @param len length of the application supplied data buffer
  874. *
  875. * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough
  876. */
  877. err_t
  878. pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
  879. {
  880. struct pbuf *p;
  881. u16_t buf_copy_len;
  882. u16_t total_copy_len = len;
  883. u16_t copied_total = 0;
  884. LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;);
  885. LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;);
  886. if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {
  887. return ERR_ARG;
  888. }
  889. /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
  890. for(p = buf; total_copy_len != 0; p = p->next) {
  891. LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);
  892. buf_copy_len = total_copy_len;
  893. if (buf_copy_len > p->len) {
  894. /* this pbuf cannot hold all remaining data */
  895. buf_copy_len = p->len;
  896. }
  897. /* copy the necessary parts of the buffer */
  898. MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len);
  899. total_copy_len -= buf_copy_len;
  900. copied_total += buf_copy_len;
  901. }
  902. LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);
  903. return ERR_OK;
  904. }
  905. /**
  906. * Creates a single pbuf out of a queue of pbufs.
  907. *
  908. * @remark: Either the source pbuf 'p' is freed by this function or the original
  909. * pbuf 'p' is returned, therefore the caller has to check the result!
  910. *
  911. * @param p the source pbuf
  912. * @param layer pbuf_layer of the new pbuf
  913. *
  914. * @return a new, single pbuf (p->next is NULL)
  915. * or the old pbuf if allocation fails
  916. */
  917. struct pbuf*
  918. pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
  919. {
  920. struct pbuf *q;
  921. err_t err;
  922. if (p->next == NULL) {
  923. return p;
  924. }
  925. q = pbuf_alloc(layer, p->tot_len, PBUF_RAM);
  926. if (q == NULL) {
  927. /* @todo: what do we do now? */
  928. return p;
  929. }
  930. err = pbuf_copy(q, p);
  931. LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
  932. pbuf_free(p);
  933. return q;
  934. }
  935. #if LWIP_CHECKSUM_ON_COPY
  936. /**
  937. * Copies data into a single pbuf (*not* into a pbuf queue!) and updates
  938. * the checksum while copying
  939. *
  940. * @param p the pbuf to copy data into
  941. * @param start_offset offset of p->payload where to copy the data to
  942. * @param dataptr data to copy into the pbuf
  943. * @param len length of data to copy into the pbuf
  944. * @param chksum pointer to the checksum which is updated
  945. * @return ERR_OK if successful, another error if the data does not fit
  946. * within the (first) pbuf (no pbuf queues!)
  947. */
  948. err_t
  949. pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
  950. u16_t len, u16_t *chksum)
  951. {
  952. u32_t acc;
  953. u16_t copy_chksum;
  954. char *dst_ptr;
  955. LWIP_ASSERT("p != NULL", p != NULL);
  956. LWIP_ASSERT("dataptr != NULL", dataptr != NULL);
  957. LWIP_ASSERT("chksum != NULL", chksum != NULL);
  958. LWIP_ASSERT("len != 0", len != 0);
  959. if ((start_offset >= p->len) || (start_offset + len > p->len)) {
  960. return ERR_ARG;
  961. }
  962. dst_ptr = ((char*)p->payload) + start_offset;
  963. copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);
  964. if ((start_offset & 1) != 0) {
  965. copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);
  966. }
  967. acc = *chksum;
  968. acc += copy_chksum;
  969. *chksum = FOLD_U32T(acc);
  970. return ERR_OK;
  971. }
  972. #endif /* LWIP_CHECKSUM_ON_COPY */
  973. /** Get one byte from the specified position in a pbuf
  974. * WARNING: returns zero for offset >= p->tot_len
  975. *
  976. * @param p pbuf to parse
  977. * @param offset offset into p of the byte to return
  978. * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len
  979. */
  980. u8_t
  981. pbuf_get_at(struct pbuf* p, u16_t offset)
  982. {
  983. u16_t copy_from = offset;
  984. struct pbuf* q = p;
  985. /* get the correct pbuf */
  986. while ((q != NULL) && (q->len <= copy_from)) {
  987. copy_from -= q->len;
  988. q = q->next;
  989. }
  990. /* return requested data if pbuf is OK */
  991. if ((q != NULL) && (q->len > copy_from)) {
  992. return ((u8_t*)q->payload)[copy_from];
  993. }
  994. return 0;
  995. }
  996. /** Compare pbuf contents at specified offset with memory s2, both of length n
  997. *
  998. * @param p pbuf to compare
  999. * @param offset offset into p at wich to start comparing
  1000. * @param s2 buffer to compare
  1001. * @param n length of buffer to compare
  1002. * @return zero if equal, nonzero otherwise
  1003. * (0xffff if p is too short, diffoffset+1 otherwise)
  1004. */
  1005. u16_t
  1006. pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
  1007. {
  1008. u16_t start = offset;
  1009. struct pbuf* q = p;
  1010. /* get the correct pbuf */
  1011. while ((q != NULL) && (q->len <= start)) {
  1012. start -= q->len;
  1013. q = q->next;
  1014. }
  1015. /* return requested data if pbuf is OK */
  1016. if ((q != NULL) && (q->len > start)) {
  1017. u16_t i;
  1018. for(i = 0; i < n; i++) {
  1019. u8_t a = pbuf_get_at(q, start + i);
  1020. u8_t b = ((u8_t*)s2)[i];
  1021. if (a != b) {
  1022. return i+1;
  1023. }
  1024. }
  1025. return 0;
  1026. }
  1027. return 0xffff;
  1028. }
  1029. /** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset
  1030. * start_offset.
  1031. *
  1032. * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
  1033. * return value 'not found'
  1034. * @param mem search for the contents of this buffer
  1035. * @param mem_len length of 'mem'
  1036. * @param start_offset offset into p at which to start searching
  1037. * @return 0xFFFF if substr was not found in p or the index where it was found
  1038. */
  1039. u16_t
  1040. pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
  1041. {
  1042. u16_t i;
  1043. u16_t max = p->tot_len - mem_len;
  1044. if (p->tot_len >= mem_len + start_offset) {
  1045. for(i = start_offset; i <= max; ) {
  1046. u16_t plus = pbuf_memcmp(p, i, mem, mem_len);
  1047. if (plus == 0) {
  1048. return i;
  1049. } else {
  1050. i += plus;
  1051. }
  1052. }
  1053. }
  1054. return 0xFFFF;
  1055. }
  1056. /** Find occurrence of substr with length substr_len in pbuf p, start at offset
  1057. * start_offset
  1058. * WARNING: in contrast to strstr(), this one does not stop at the first \0 in
  1059. * the pbuf/source string!
  1060. *
  1061. * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
  1062. * return value 'not found'
  1063. * @param substr string to search for in p, maximum length is 0xFFFE
  1064. * @return 0xFFFF if substr was not found in p or the index where it was found
  1065. */
  1066. u16_t
  1067. pbuf_strstr(struct pbuf* p, const char* substr)
  1068. {
  1069. size_t substr_len;
  1070. if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
  1071. return 0xFFFF;
  1072. }
  1073. substr_len = strlen(substr);
  1074. if (substr_len >= 0xFFFF) {
  1075. return 0xFFFF;
  1076. }
  1077. return pbuf_memfind(p, substr, (u16_t)substr_len, 0);
  1078. }