Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pbuf.c Source File

pbuf.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Packet buffer management
00004  *
00005  * Packets are built from the pbuf data structure. It supports dynamic
00006  * memory allocation for packet contents or can reference externally
00007  * managed packet contents both in RAM and ROM. Quick allocation for
00008  * incoming packets is provided through pools with fixed sized pbufs.
00009  *
00010  * A packet may span over multiple pbufs, chained as a singly linked
00011  * list. This is called a "pbuf chain".
00012  *
00013  * Multiple packets may be queued, also using this singly linked list.
00014  * This is called a "packet queue".
00015  * 
00016  * So, a packet queue consists of one or more pbuf chains, each of
00017  * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE
00018  * NOT SUPPORTED!!! Use helper structs to queue multiple packets.
00019  * 
00020  * The differences between a pbuf chain and a packet queue are very
00021  * precise but subtle. 
00022  *
00023  * The last pbuf of a packet has a ->tot_len field that equals the
00024  * ->len field. It can be found by traversing the list. If the last
00025  * pbuf of a packet has a ->next field other than NULL, more packets
00026  * are on the queue.
00027  *
00028  * Therefore, looping through a pbuf of a single packet, has an
00029  * loop end condition (tot_len == p->len), NOT (next == NULL).
00030  */
00031 
00032 /*
00033  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00034  * All rights reserved.
00035  *
00036  * Redistribution and use in source and binary forms, with or without modification,
00037  * are permitted provided that the following conditions are met:
00038  *
00039  * 1. Redistributions of source code must retain the above copyright notice,
00040  *    this list of conditions and the following disclaimer.
00041  * 2. Redistributions in binary form must reproduce the above copyright notice,
00042  *    this list of conditions and the following disclaimer in the documentation
00043  *    and/or other materials provided with the distribution.
00044  * 3. The name of the author may not be used to endorse or promote products
00045  *    derived from this software without specific prior written permission.
00046  *
00047  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00048  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00049  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00050  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00051  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00052  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00053  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00054  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00055  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00056  * OF SUCH DAMAGE.
00057  *
00058  * This file is part of the lwIP TCP/IP stack.
00059  *
00060  * Author: Adam Dunkels <adam@sics.se>
00061  *
00062  */
00063 
00064 #include "lwip/opt.h"
00065 
00066 #include "lwip/stats.h"
00067 #include "lwip/def.h"
00068 #include "lwip/mem.h"
00069 #include "lwip/memp.h"
00070 #include "lwip/pbuf.h"
00071 #include "lwip/sys.h"
00072 #include "arch/perf.h"
00073 #if TCP_QUEUE_OOSEQ
00074 #include "lwip/tcp_impl.h"
00075 #endif
00076 
00077 #include <string.h>
00078 
00079 #define SIZEOF_STRUCT_PBUF        LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
00080 /* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically
00081    aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
00082 #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
00083 
00084 #if !TCP_QUEUE_OOSEQ || NO_SYS
00085 #define PBUF_POOL_IS_EMPTY()
00086 #else /* !TCP_QUEUE_OOSEQ || NO_SYS */
00087 /** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
00088 #ifndef PBUF_POOL_FREE_OOSEQ
00089 #define PBUF_POOL_FREE_OOSEQ 1
00090 #endif /* PBUF_POOL_FREE_OOSEQ */
00091 
00092 #if PBUF_POOL_FREE_OOSEQ
00093 #include "lwip/tcpip.h"
00094 #define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
00095 static u8_t pbuf_free_ooseq_queued;
00096 /**
00097  * Attempt to reclaim some memory from queued out-of-sequence TCP segments
00098  * if we run out of pool pbufs. It's better to give priority to new packets
00099  * if we're running out.
00100  *
00101  * This must be done in the correct thread context therefore this function
00102  * can only be used with NO_SYS=0 and through tcpip_callback.
00103  */
00104 static void
00105 pbuf_free_ooseq(void* arg)
00106 {
00107   struct tcp_pcb* pcb;
00108   SYS_ARCH_DECL_PROTECT(old_level);
00109   LWIP_UNUSED_ARG(arg);
00110 
00111   SYS_ARCH_PROTECT(old_level);
00112   pbuf_free_ooseq_queued = 0;
00113   SYS_ARCH_UNPROTECT(old_level);
00114 
00115   for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
00116     if (NULL != pcb->ooseq) {
00117       /** Free the ooseq pbufs of one PCB only */
00118       LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
00119       tcp_segs_free(pcb->ooseq);
00120       pcb->ooseq = NULL;
00121       return;
00122     }
00123   }
00124 }
00125 
00126 /** Queue a call to pbuf_free_ooseq if not already queued. */
00127 static void
00128 pbuf_pool_is_empty(void)
00129 {
00130   u8_t queued;
00131   SYS_ARCH_DECL_PROTECT(old_level);
00132 
00133   SYS_ARCH_PROTECT(old_level);
00134   queued = pbuf_free_ooseq_queued;
00135   pbuf_free_ooseq_queued = 1;
00136   SYS_ARCH_UNPROTECT(old_level);
00137 
00138   if(!queued) {
00139     /* queue a call to pbuf_free_ooseq if not already queued */
00140     if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) {
00141       SYS_ARCH_PROTECT(old_level);
00142       pbuf_free_ooseq_queued = 0;
00143       SYS_ARCH_UNPROTECT(old_level);
00144     }
00145   }
00146 }
00147 #endif /* PBUF_POOL_FREE_OOSEQ */
00148 #endif /* !TCP_QUEUE_OOSEQ || NO_SYS */
00149 
00150 /**
00151  * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
00152  *
00153  * The actual memory allocated for the pbuf is determined by the
00154  * layer at which the pbuf is allocated and the requested size
00155  * (from the size parameter).
00156  *
00157  * @param layer flag to define header size
00158  * @param length size of the pbuf's payload
00159  * @param type this parameter decides how and where the pbuf
00160  * should be allocated as follows:
00161  *
00162  * - PBUF_RAM: buffer memory for pbuf is allocated as one large
00163  *             chunk. This includes protocol headers as well.
00164  * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for
00165  *             protocol headers. Additional headers must be prepended
00166  *             by allocating another pbuf and chain in to the front of
00167  *             the ROM pbuf. It is assumed that the memory used is really
00168  *             similar to ROM in that it is immutable and will not be
00169  *             changed. Memory which is dynamic should generally not
00170  *             be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
00171  * - PBUF_REF: no buffer memory is allocated for the pbuf, even for
00172  *             protocol headers. It is assumed that the pbuf is only
00173  *             being used in a single thread. If the pbuf gets queued,
00174  *             then pbuf_take should be called to copy the buffer.
00175  * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
00176  *              the pbuf pool that is allocated during pbuf_init().
00177  *
00178  * @return the allocated pbuf. If multiple pbufs where allocated, this
00179  * is the first pbuf of a pbuf chain.
00180  */
00181 struct pbuf *
00182 pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
00183 {
00184   struct pbuf *p, *q, *r;
00185   u16_t offset;
00186   s32_t rem_len; /* remaining length */
00187   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
00188 
00189   /* determine header offset */
00190   offset = 0;
00191   switch (layer) {
00192   case PBUF_TRANSPORT:
00193     /* add room for transport (often TCP) layer header */
00194     offset += PBUF_TRANSPORT_HLEN;
00195     /* FALLTHROUGH */
00196   case PBUF_IP:
00197     /* add room for IP layer header */
00198     offset += PBUF_IP_HLEN;
00199     /* FALLTHROUGH */
00200   case PBUF_LINK:
00201     /* add room for link layer header */
00202     offset += PBUF_LINK_HLEN;
00203     break;
00204   case PBUF_RAW:
00205     break;
00206   default:
00207     LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
00208     return NULL;
00209   }
00210 
00211   switch (type) {
00212   case PBUF_POOL:
00213     /* allocate head of pbuf chain into p */
00214     p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
00215     LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
00216     if (p == NULL) {
00217       PBUF_POOL_IS_EMPTY();
00218       return NULL;
00219     }
00220     p->type = type;
00221     p->next = NULL;
00222 
00223     /* make the payload pointer point 'offset' bytes into pbuf data memory */
00224     p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset)));
00225     LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
00226             ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
00227     /* the total length of the pbuf chain is the requested size */
00228     p->tot_len = length;
00229     /* set the length of the first pbuf in the chain */
00230     p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset));
00231     LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
00232                 ((u8_t*)p->payload + p->len <=
00233                  (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED));
00234     LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT",
00235       (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 );
00236     /* set reference count (needed here in case we fail) */
00237     p->ref = 1;
00238 
00239     /* now allocate the tail of the pbuf chain */
00240 
00241     /* remember first pbuf for linkage in next iteration */
00242     r = p;
00243     /* remaining length to be allocated */
00244     rem_len = length - p->len;
00245     /* any remaining pbufs to be allocated? */
00246     while (rem_len > 0) {
00247       q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
00248       if (q == NULL) {
00249         PBUF_POOL_IS_EMPTY();
00250         /* free chain so far allocated */
00251         pbuf_free(p);
00252         /* bail out unsuccesfully */
00253         return NULL;
00254       }
00255       q->type = type;
00256       q->flags = 0;
00257       q->next = NULL;
00258       /* make previous pbuf point to this pbuf */
00259       r->next = q;
00260       /* set total length of this pbuf and next in chain */
00261       LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff);
00262       q->tot_len = (u16_t)rem_len;
00263       /* this pbuf length is pool size, unless smaller sized tail */
00264       q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED);
00265       q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF);
00266       LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
00267               ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
00268       LWIP_ASSERT("check p->payload + p->len does not overflow pbuf",
00269                   ((u8_t*)p->payload + p->len <=
00270                    (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED));
00271       q->ref = 1;
00272       /* calculate remaining length to be allocated */
00273       rem_len -= q->len;
00274       /* remember this pbuf for linkage in next iteration */
00275       r = q;
00276     }
00277     /* end of chain */
00278     /*r->next = NULL;*/
00279 
00280     break;
00281   case PBUF_RAM:
00282     /* If pbuf is to be allocated in RAM, allocate memory for it. */
00283     p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
00284     if (p == NULL) {
00285       return NULL;
00286     }
00287     /* Set up internal structure of the pbuf. */
00288     p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset));
00289     p->len = p->tot_len = length;
00290     p->next = NULL;
00291     p->type = type;
00292 
00293     LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
00294            ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
00295     break;
00296   /* pbuf references existing (non-volatile static constant) ROM payload? */
00297   case PBUF_ROM:
00298   /* pbuf references existing (externally allocated) RAM payload? */
00299   case PBUF_REF:
00300     /* only allocate memory for the pbuf structure */
00301     p = (struct pbuf *)memp_malloc(MEMP_PBUF);
00302     if (p == NULL) {
00303       LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00304                   ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
00305                   (type == PBUF_ROM) ? "ROM" : "REF"));
00306       return NULL;
00307     }
00308     /* caller must set this field properly, afterwards */
00309     p->payload = NULL;
00310     p->len = p->tot_len = length;
00311     p->next = NULL;
00312     p->type = type;
00313     break;
00314   default:
00315     LWIP_ASSERT("pbuf_alloc: erroneous type", 0);
00316     return NULL;
00317   }
00318   /* set reference count */
00319   p->ref = 1;
00320   /* set flags */
00321   p->flags = 0;
00322   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
00323   return p;
00324 }
00325 
00326 
00327 /**
00328  * Shrink a pbuf chain to a desired length.
00329  *
00330  * @param p pbuf to shrink.
00331  * @param new_len desired new length of pbuf chain
00332  *
00333  * Depending on the desired length, the first few pbufs in a chain might
00334  * be skipped and left unchanged. The new last pbuf in the chain will be
00335  * resized, and any remaining pbufs will be freed.
00336  *
00337  * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
00338  * @note May not be called on a packet queue.
00339  *
00340  * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain).
00341  */
00342 void
00343 pbuf_realloc(struct pbuf *p, u16_t new_len)
00344 {
00345   struct pbuf *q;
00346   u16_t rem_len; /* remaining length */
00347   s32_t grow;
00348 
00349   LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL);
00350   LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL ||
00351               p->type == PBUF_ROM ||
00352               p->type == PBUF_RAM ||
00353               p->type == PBUF_REF);
00354 
00355   /* desired length larger than current length? */
00356   if (new_len >= p->tot_len) {
00357     /* enlarging not yet supported */
00358     return;
00359   }
00360 
00361   /* the pbuf chain grows by (new_len - p->tot_len) bytes
00362    * (which may be negative in case of shrinking) */
00363   grow = new_len - p->tot_len;
00364 
00365   /* first, step over any pbufs that should remain in the chain */
00366   rem_len = new_len;
00367   q = p;
00368   /* should this pbuf be kept? */
00369   while (rem_len > q->len) {
00370     /* decrease remaining length by pbuf length */
00371     rem_len -= q->len;
00372     /* decrease total length indicator */
00373     LWIP_ASSERT("grow < max_u16_t", grow < 0xffff);
00374     q->tot_len += (u16_t)grow;
00375     /* proceed to next pbuf in chain */
00376     q = q->next;
00377     LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL);
00378   }
00379   /* we have now reached the new last pbuf (in q) */
00380   /* rem_len == desired length for pbuf q */
00381 
00382   /* shrink allocated memory for PBUF_RAM */
00383   /* (other types merely adjust their length fields */
00384   if ((q->type == PBUF_RAM) && (rem_len != q->len)) {
00385     /* reallocate and adjust the length of the pbuf that will be split */
00386     q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len);
00387     LWIP_ASSERT("mem_trim returned q == NULL", q != NULL);
00388   }
00389   /* adjust length fields for new last pbuf */
00390   q->len = rem_len;
00391   q->tot_len = q->len;
00392 
00393   /* any remaining pbufs in chain? */
00394   if (q->next != NULL) {
00395     /* free remaining pbufs in chain */
00396     pbuf_free(q->next);
00397   }
00398   /* q is last packet in chain */
00399   q->next = NULL;
00400 
00401 }
00402 
00403 /**
00404  * Adjusts the payload pointer to hide or reveal headers in the payload.
00405  *
00406  * Adjusts the ->payload pointer so that space for a header
00407  * (dis)appears in the pbuf payload.
00408  *
00409  * The ->payload, ->tot_len and ->len fields are adjusted.
00410  *
00411  * @param p pbuf to change the header size.
00412  * @param header_size_increment Number of bytes to increment header size which
00413  * increases the size of the pbuf. New space is on the front.
00414  * (Using a negative value decreases the header size.)
00415  * If hdr_size_inc is 0, this function does nothing and returns succesful.
00416  *
00417  * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
00418  * the call will fail. A check is made that the increase in header size does
00419  * not move the payload pointer in front of the start of the buffer.
00420  * @return non-zero on failure, zero on success.
00421  *
00422  */
00423 u8_t
00424 pbuf_header(struct pbuf *p, s16_t header_size_increment)
00425 {
00426   u16_t type;
00427   void *payload;
00428   u16_t increment_magnitude;
00429 
00430   LWIP_ASSERT("p != NULL", p != NULL);
00431   if ((header_size_increment == 0) || (p == NULL))
00432     return 0;
00433  
00434   if (header_size_increment < 0){
00435     increment_magnitude = -header_size_increment;
00436     /* Check that we aren't going to move off the end of the pbuf */
00437     LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
00438   } else {
00439     increment_magnitude = header_size_increment;
00440 #if 0
00441     /* Can't assert these as some callers speculatively call
00442          pbuf_header() to see if it's OK.  Will return 1 below instead. */
00443     /* Check that we've got the correct type of pbuf to work with */
00444     LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", 
00445                 p->type == PBUF_RAM || p->type == PBUF_POOL);
00446     /* Check that we aren't going to move off the beginning of the pbuf */
00447     LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF",
00448                 (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF);
00449 #endif
00450   }
00451 
00452   type = p->type;
00453   /* remember current payload pointer */
00454   payload = p->payload;
00455 
00456   /* pbuf types containing payloads? */
00457   if (type == PBUF_RAM || type == PBUF_POOL) {
00458     /* set new payload pointer */
00459     p->payload = (u8_t *)p->payload - header_size_increment;
00460     /* boundary check fails? */
00461     if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) {
00462       LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00463         ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
00464         (void *)p->payload, (void *)(p + 1)));
00465       /* restore old payload pointer */
00466       p->payload = payload;
00467       /* bail out unsuccesfully */
00468       return 1;
00469     }
00470   /* pbuf types refering to external payloads? */
00471   } else if (type == PBUF_REF || type == PBUF_ROM) {
00472     /* hide a header in the payload? */
00473     if ((header_size_increment < 0) && (increment_magnitude <= p->len)) {
00474       /* increase payload pointer */
00475       p->payload = (u8_t *)p->payload - header_size_increment;
00476     } else {
00477       /* cannot expand payload to front (yet!)
00478        * bail out unsuccesfully */
00479       return 1;
00480     }
00481   }
00482   else {
00483     /* Unknown type */
00484     LWIP_ASSERT("bad pbuf type", 0);
00485     return 1;
00486   }
00487   /* modify pbuf length fields */
00488   p->len += header_size_increment;
00489   p->tot_len += header_size_increment;
00490 
00491   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n",
00492     (void *)payload, (void *)p->payload, header_size_increment));
00493 
00494   return 0;
00495 }
00496 
00497 /**
00498  * Dereference a pbuf chain or queue and deallocate any no-longer-used
00499  * pbufs at the head of this chain or queue.
00500  *
00501  * Decrements the pbuf reference count. If it reaches zero, the pbuf is
00502  * deallocated.
00503  *
00504  * For a pbuf chain, this is repeated for each pbuf in the chain,
00505  * up to the first pbuf which has a non-zero reference count after
00506  * decrementing. So, when all reference counts are one, the whole
00507  * chain is free'd.
00508  *
00509  * @param p The pbuf (chain) to be dereferenced.
00510  *
00511  * @return the number of pbufs that were de-allocated
00512  * from the head of the chain.
00513  *
00514  * @note MUST NOT be called on a packet queue (Not verified to work yet).
00515  * @note the reference counter of a pbuf equals the number of pointers
00516  * that refer to the pbuf (or into the pbuf).
00517  *
00518  * @internal examples:
00519  *
00520  * Assuming existing chains a->b->c with the following reference
00521  * counts, calling pbuf_free(a) results in:
00522  * 
00523  * 1->2->3 becomes ...1->3
00524  * 3->3->3 becomes 2->3->3
00525  * 1->1->2 becomes ......1
00526  * 2->1->1 becomes 1->1->1
00527  * 1->1->1 becomes .......
00528  *
00529  */
00530 u8_t
00531 pbuf_free(struct pbuf *p)
00532 {
00533   u16_t type;
00534   struct pbuf *q;
00535   u8_t count;
00536 
00537   if (p == NULL) {
00538     LWIP_ASSERT("p != NULL", p != NULL);
00539     /* if assertions are disabled, proceed with debug output */
00540     LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00541       ("pbuf_free(p == NULL) was called.\n"));
00542     return 0;
00543   }
00544   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
00545 
00546   PERF_START;
00547 
00548   LWIP_ASSERT("pbuf_free: sane type",
00549     p->type == PBUF_RAM || p->type == PBUF_ROM ||
00550     p->type == PBUF_REF || p->type == PBUF_POOL);
00551 
00552   count = 0;
00553   /* de-allocate all consecutive pbufs from the head of the chain that
00554    * obtain a zero reference count after decrementing*/
00555   while (p != NULL) {
00556     u16_t ref;
00557     SYS_ARCH_DECL_PROTECT(old_level);
00558     /* Since decrementing ref cannot be guaranteed to be a single machine operation
00559      * we must protect it. We put the new ref into a local variable to prevent
00560      * further protection. */
00561     SYS_ARCH_PROTECT(old_level);
00562     /* all pbufs in a chain are referenced at least once */
00563     LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
00564     /* decrease reference count (number of pointers to pbuf) */
00565     ref = --(p->ref);
00566     SYS_ARCH_UNPROTECT(old_level);
00567     /* this pbuf is no longer referenced to? */
00568     if (ref == 0) {
00569       /* remember next pbuf in chain for next iteration */
00570       q = p->next;
00571       LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
00572       type = p->type;
00573       /* is this a pbuf from the pool? */
00574       if (type == PBUF_POOL) {
00575         memp_free(MEMP_PBUF_POOL, p);
00576       /* is this a ROM or RAM referencing pbuf? */
00577       } else if (type == PBUF_ROM || type == PBUF_REF) {
00578         memp_free(MEMP_PBUF, p);
00579       /* type == PBUF_RAM */
00580       } else {
00581         mem_free(p);
00582       }
00583       count++;
00584       /* proceed to next pbuf */
00585       p = q;
00586     /* p->ref > 0, this pbuf is still referenced to */
00587     /* (and so the remaining pbufs in chain as well) */
00588     } else {
00589       LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref));
00590       /* stop walking through the chain */
00591       p = NULL;
00592     }
00593   }
00594   PERF_STOP("pbuf_free");
00595   /* return number of de-allocated pbufs */
00596   return count;
00597 }
00598 
00599 /**
00600  * Count number of pbufs in a chain
00601  *
00602  * @param p first pbuf of chain
00603  * @return the number of pbufs in a chain
00604  */
00605 
00606 u8_t
00607 pbuf_clen(struct pbuf *p)
00608 {
00609   u8_t len;
00610 
00611   len = 0;
00612   while (p != NULL) {
00613     ++len;
00614     p = p->next;
00615   }
00616   return len;
00617 }
00618 
00619 /**
00620  * Increment the reference count of the pbuf.
00621  *
00622  * @param p pbuf to increase reference counter of
00623  *
00624  */
00625 void
00626 pbuf_ref(struct pbuf *p)
00627 {
00628   SYS_ARCH_DECL_PROTECT(old_level);
00629   /* pbuf given? */
00630   if (p != NULL) {
00631     SYS_ARCH_PROTECT(old_level);
00632     ++(p->ref);
00633     SYS_ARCH_UNPROTECT(old_level);
00634   }
00635 }
00636 
00637 /**
00638  * Concatenate two pbufs (each may be a pbuf chain) and take over
00639  * the caller's reference of the tail pbuf.
00640  * 
00641  * @note The caller MAY NOT reference the tail pbuf afterwards.
00642  * Use pbuf_chain() for that purpose.
00643  * 
00644  * @see pbuf_chain()
00645  */
00646 
00647 void
00648 pbuf_cat(struct pbuf *h, struct pbuf *t)
00649 {
00650   struct pbuf *p;
00651 
00652   LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)",
00653              ((h != NULL) && (t != NULL)), return;);
00654 
00655   /* proceed to last pbuf of chain */
00656   for (p = h; p->next != NULL; p = p->next) {
00657     /* add total length of second chain to all totals of first chain */
00658     p->tot_len += t->tot_len;
00659   }
00660   /* { p is last pbuf of first h chain, p->next == NULL } */
00661   LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
00662   LWIP_ASSERT("p->next == NULL", p->next == NULL);
00663   /* add total length of second chain to last pbuf total of first chain */
00664   p->tot_len += t->tot_len;
00665   /* chain last pbuf of head (p) with first of tail (t) */
00666   p->next = t;
00667   /* p->next now references t, but the caller will drop its reference to t,
00668    * so netto there is no change to the reference count of t.
00669    */
00670 }
00671 
00672 /**
00673  * Chain two pbufs (or pbuf chains) together.
00674  * 
00675  * The caller MUST call pbuf_free(t) once it has stopped
00676  * using it. Use pbuf_cat() instead if you no longer use t.
00677  * 
00678  * @param h head pbuf (chain)
00679  * @param t tail pbuf (chain)
00680  * @note The pbufs MUST belong to the same packet.
00681  * @note MAY NOT be called on a packet queue.
00682  *
00683  * The ->tot_len fields of all pbufs of the head chain are adjusted.
00684  * The ->next field of the last pbuf of the head chain is adjusted.
00685  * The ->ref field of the first pbuf of the tail chain is adjusted.
00686  *
00687  */
00688 void
00689 pbuf_chain(struct pbuf *h, struct pbuf *t)
00690 {
00691   pbuf_cat(h, t);
00692   /* t is now referenced by h */
00693   pbuf_ref(t);
00694   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
00695 }
00696 
00697 /**
00698  * Dechains the first pbuf from its succeeding pbufs in the chain.
00699  *
00700  * Makes p->tot_len field equal to p->len.
00701  * @param p pbuf to dechain
00702  * @return remainder of the pbuf chain, or NULL if it was de-allocated.
00703  * @note May not be called on a packet queue.
00704  */
00705 struct pbuf *
00706 pbuf_dechain(struct pbuf *p)
00707 {
00708   struct pbuf *q;
00709   u8_t tail_gone = 1;
00710   /* tail */
00711   q = p->next;
00712   /* pbuf has successor in chain? */
00713   if (q != NULL) {
00714     /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
00715     LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
00716     /* enforce invariant if assertion is disabled */
00717     q->tot_len = p->tot_len - p->len;
00718     /* decouple pbuf from remainder */
00719     p->next = NULL;
00720     /* total length of pbuf p is its own length only */
00721     p->tot_len = p->len;
00722     /* q is no longer referenced by p, free it */
00723     LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
00724     tail_gone = pbuf_free(q);
00725     if (tail_gone > 0) {
00726       LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE,
00727                   ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
00728     }
00729     /* return remaining tail or NULL if deallocated */
00730   }
00731   /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
00732   LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
00733   return ((tail_gone > 0) ? NULL : q);
00734 }
00735 
00736 /**
00737  *
00738  * Create PBUF_RAM copies of pbufs.
00739  *
00740  * Used to queue packets on behalf of the lwIP stack, such as
00741  * ARP based queueing.
00742  *
00743  * @note You MUST explicitly use p = pbuf_take(p);
00744  *
00745  * @note Only one packet is copied, no packet queue!
00746  *
00747  * @param p_to pbuf destination of the copy
00748  * @param p_from pbuf source of the copy
00749  *
00750  * @return ERR_OK if pbuf was copied
00751  *         ERR_ARG if one of the pbufs is NULL or p_to is not big
00752  *                 enough to hold p_from
00753  */
00754 err_t
00755 pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
00756 {
00757   u16_t offset_to=0, offset_from=0, len;
00758 
00759   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
00760     (void*)p_to, (void*)p_from));
00761 
00762   /* is the target big enough to hold the source? */
00763   LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
00764              (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);
00765 
00766   /* iterate through pbuf chain */
00767   do
00768   {
00769     LWIP_ASSERT("p_to != NULL", p_to != NULL);
00770     /* copy one part of the original chain */
00771     if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
00772       /* complete current p_from fits into current p_to */
00773       len = p_from->len - offset_from;
00774     } else {
00775       /* current p_from does not fit into current p_to */
00776       len = p_to->len - offset_to;
00777     }
00778     MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len);
00779     offset_to += len;
00780     offset_from += len;
00781     LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
00782     if (offset_to == p_to->len) {
00783       /* on to next p_to (if any) */
00784       offset_to = 0;
00785       p_to = p_to->next;
00786     }
00787     LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
00788     if (offset_from >= p_from->len) {
00789       /* on to next p_from (if any) */
00790       offset_from = 0;
00791       p_from = p_from->next;
00792     }
00793 
00794     if((p_from != NULL) && (p_from->len == p_from->tot_len)) {
00795       /* don't copy more than one packet! */
00796       LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
00797                  (p_from->next == NULL), return ERR_VAL;);
00798     }
00799     if((p_to != NULL) && (p_to->len == p_to->tot_len)) {
00800       /* don't copy more than one packet! */
00801       LWIP_ERROR("pbuf_copy() does not allow packet queues!\n",
00802                   (p_to->next == NULL), return ERR_VAL;);
00803     }
00804   } while (p_from);
00805   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
00806   return ERR_OK;
00807 }
00808 
00809 /**
00810  * Copy (part of) the contents of a packet buffer
00811  * to an application supplied buffer.
00812  *
00813  * @param buf the pbuf from which to copy data
00814  * @param dataptr the application supplied buffer
00815  * @param len length of data to copy (dataptr must be big enough). No more 
00816  * than buf->tot_len will be copied, irrespective of len
00817  * @param offset offset into the packet buffer from where to begin copying len bytes
00818  * @return the number of bytes copied, or 0 on failure
00819  */
00820 u16_t
00821 pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
00822 {
00823   struct pbuf *p;
00824   u16_t left;
00825   u16_t buf_copy_len;
00826   u16_t copied_total = 0;
00827 
00828   LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;);
00829   LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;);
00830 
00831   left = 0;
00832 
00833   if((buf == NULL) || (dataptr == NULL)) {
00834     return 0;
00835   }
00836 
00837   /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
00838   for(p = buf; len != 0 && p != NULL; p = p->next) {
00839     if ((offset != 0) && (offset >= p->len)) {
00840       /* don't copy from this buffer -> on to the next */
00841       offset -= p->len;
00842     } else {
00843       /* copy from this buffer. maybe only partially. */
00844       buf_copy_len = p->len - offset;
00845       if (buf_copy_len > len)
00846           buf_copy_len = len;
00847       /* copy the necessary parts of the buffer */
00848       MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len);
00849       copied_total += buf_copy_len;
00850       left += buf_copy_len;
00851       len -= buf_copy_len;
00852       offset = 0;
00853     }
00854   }
00855   return copied_total;
00856 }
00857 
00858 /**
00859  * Copy application supplied data into a pbuf.
00860  * This function can only be used to copy the equivalent of buf->tot_len data.
00861  *
00862  * @param buf pbuf to fill with data
00863  * @param dataptr application supplied data buffer
00864  * @param len length of the application supplied data buffer
00865  *
00866  * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough
00867  */
00868 err_t
00869 pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
00870 {
00871   struct pbuf *p;
00872   u16_t buf_copy_len;
00873   u16_t total_copy_len = len;
00874   u16_t copied_total = 0;
00875 
00876   LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return 0;);
00877   LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return 0;);
00878 
00879   if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) {
00880     return ERR_ARG;
00881   }
00882 
00883   /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
00884   for(p = buf; total_copy_len != 0; p = p->next) {
00885     LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL);
00886     buf_copy_len = total_copy_len;
00887     if (buf_copy_len > p->len) {
00888       /* this pbuf cannot hold all remaining data */
00889       buf_copy_len = p->len;
00890     }
00891     /* copy the necessary parts of the buffer */
00892     MEMCPY(p->payload, &((char*)dataptr)[copied_total], buf_copy_len);
00893     total_copy_len -= buf_copy_len;
00894     copied_total += buf_copy_len;
00895   }
00896   LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len);
00897   return ERR_OK;
00898 }
00899 
00900 /**
00901  * Creates a single pbuf out of a queue of pbufs.
00902  *
00903  * @remark: The source pbuf 'p' is not freed by this function because that can
00904  *          be illegal in some places!
00905  *
00906  * @param p the source pbuf
00907  * @param layer pbuf_layer of the new pbuf
00908  *
00909  * @return a new, single pbuf (p->next is NULL)
00910  *         or the old pbuf if allocation fails
00911  */
00912 struct pbuf*
00913 pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
00914 {
00915   struct pbuf *q;
00916   err_t err;
00917   if (p->next == NULL) {
00918     return p;
00919   }
00920   q = pbuf_alloc(layer, p->tot_len, PBUF_RAM);
00921   if (q == NULL) {
00922     /* @todo: what do we do now? */
00923     return p;
00924   }
00925   err = pbuf_copy(q, p);
00926   LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
00927   pbuf_free(p);
00928   return q;
00929 }