Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed OS 5, lwip has been integrated with built-in networking interfaces. The networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of lwIP v1.4.0

Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
mbed_official
Date:
Mon Mar 14 16:15:36 2016 +0000
Revision:
20:08f08bfc3f3d
Parent:
12:931deec14b08
Synchronized with git revision fec574a5ed6db26aca1b13992ff271bf527d4a0d

Full URL: https://github.com/mbedmicro/mbed/commit/fec574a5ed6db26aca1b13992ff271bf527d4a0d/

Increased allocated netbufs to handle DTLS handshakes

Who changed what in which revision?

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