11734f297SVictor Perevertkin /**
21734f297SVictor Perevertkin * @file
31734f297SVictor Perevertkin * Network buffer management
41734f297SVictor Perevertkin *
5*d6eebaa4SHervé Poussineau * @defgroup netbuf Network buffers
6*d6eebaa4SHervé Poussineau * @ingroup netconn
7*d6eebaa4SHervé Poussineau * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
8*d6eebaa4SHervé Poussineau * to avoid copying data around.<br>
9*d6eebaa4SHervé Poussineau * Buffers must not be shared across multiple threads, all functions except
10*d6eebaa4SHervé Poussineau * netbuf_new() and netbuf_delete() are not thread-safe.
111734f297SVictor Perevertkin */
121734f297SVictor Perevertkin
131734f297SVictor Perevertkin /*
141734f297SVictor Perevertkin * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
151734f297SVictor Perevertkin * All rights reserved.
161734f297SVictor Perevertkin *
171734f297SVictor Perevertkin * Redistribution and use in source and binary forms, with or without modification,
181734f297SVictor Perevertkin * are permitted provided that the following conditions are met:
191734f297SVictor Perevertkin *
201734f297SVictor Perevertkin * 1. Redistributions of source code must retain the above copyright notice,
211734f297SVictor Perevertkin * this list of conditions and the following disclaimer.
221734f297SVictor Perevertkin * 2. Redistributions in binary form must reproduce the above copyright notice,
231734f297SVictor Perevertkin * this list of conditions and the following disclaimer in the documentation
241734f297SVictor Perevertkin * and/or other materials provided with the distribution.
251734f297SVictor Perevertkin * 3. The name of the author may not be used to endorse or promote products
261734f297SVictor Perevertkin * derived from this software without specific prior written permission.
271734f297SVictor Perevertkin *
281734f297SVictor Perevertkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
291734f297SVictor Perevertkin * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
301734f297SVictor Perevertkin * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
311734f297SVictor Perevertkin * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
321734f297SVictor Perevertkin * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
331734f297SVictor Perevertkin * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
341734f297SVictor Perevertkin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
351734f297SVictor Perevertkin * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
361734f297SVictor Perevertkin * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
371734f297SVictor Perevertkin * OF SUCH DAMAGE.
381734f297SVictor Perevertkin *
391734f297SVictor Perevertkin * This file is part of the lwIP TCP/IP stack.
401734f297SVictor Perevertkin *
411734f297SVictor Perevertkin * Author: Adam Dunkels <adam@sics.se>
421734f297SVictor Perevertkin *
431734f297SVictor Perevertkin */
441734f297SVictor Perevertkin
451734f297SVictor Perevertkin #include "lwip/opt.h"
461734f297SVictor Perevertkin
471734f297SVictor Perevertkin #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
481734f297SVictor Perevertkin
491734f297SVictor Perevertkin #include "lwip/netbuf.h"
501734f297SVictor Perevertkin #include "lwip/memp.h"
511734f297SVictor Perevertkin
521734f297SVictor Perevertkin #include <string.h>
531734f297SVictor Perevertkin
541734f297SVictor Perevertkin /**
55*d6eebaa4SHervé Poussineau * @ingroup netbuf
561734f297SVictor Perevertkin * Create (allocate) and initialize a new netbuf.
571734f297SVictor Perevertkin * The netbuf doesn't yet contain a packet buffer!
581734f297SVictor Perevertkin *
591734f297SVictor Perevertkin * @return a pointer to a new netbuf
601734f297SVictor Perevertkin * NULL on lack of memory
611734f297SVictor Perevertkin */
621734f297SVictor Perevertkin struct
netbuf_new(void)631734f297SVictor Perevertkin netbuf *netbuf_new(void)
641734f297SVictor Perevertkin {
651734f297SVictor Perevertkin struct netbuf *buf;
661734f297SVictor Perevertkin
671734f297SVictor Perevertkin buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
681734f297SVictor Perevertkin if (buf != NULL) {
69*d6eebaa4SHervé Poussineau memset(buf, 0, sizeof(struct netbuf));
701734f297SVictor Perevertkin }
71*d6eebaa4SHervé Poussineau return buf;
721734f297SVictor Perevertkin }
731734f297SVictor Perevertkin
741734f297SVictor Perevertkin /**
75*d6eebaa4SHervé Poussineau * @ingroup netbuf
761734f297SVictor Perevertkin * Deallocate a netbuf allocated by netbuf_new().
771734f297SVictor Perevertkin *
781734f297SVictor Perevertkin * @param buf pointer to a netbuf allocated by netbuf_new()
791734f297SVictor Perevertkin */
801734f297SVictor Perevertkin void
netbuf_delete(struct netbuf * buf)811734f297SVictor Perevertkin netbuf_delete(struct netbuf *buf)
821734f297SVictor Perevertkin {
831734f297SVictor Perevertkin if (buf != NULL) {
841734f297SVictor Perevertkin if (buf->p != NULL) {
851734f297SVictor Perevertkin pbuf_free(buf->p);
861734f297SVictor Perevertkin buf->p = buf->ptr = NULL;
871734f297SVictor Perevertkin }
881734f297SVictor Perevertkin memp_free(MEMP_NETBUF, buf);
891734f297SVictor Perevertkin }
901734f297SVictor Perevertkin }
911734f297SVictor Perevertkin
921734f297SVictor Perevertkin /**
93*d6eebaa4SHervé Poussineau * @ingroup netbuf
941734f297SVictor Perevertkin * Allocate memory for a packet buffer for a given netbuf.
951734f297SVictor Perevertkin *
961734f297SVictor Perevertkin * @param buf the netbuf for which to allocate a packet buffer
971734f297SVictor Perevertkin * @param size the size of the packet buffer to allocate
981734f297SVictor Perevertkin * @return pointer to the allocated memory
991734f297SVictor Perevertkin * NULL if no memory could be allocated
1001734f297SVictor Perevertkin */
1011734f297SVictor Perevertkin void *
netbuf_alloc(struct netbuf * buf,u16_t size)1021734f297SVictor Perevertkin netbuf_alloc(struct netbuf *buf, u16_t size)
1031734f297SVictor Perevertkin {
1041734f297SVictor Perevertkin LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
1051734f297SVictor Perevertkin
1061734f297SVictor Perevertkin /* Deallocate any previously allocated memory. */
1071734f297SVictor Perevertkin if (buf->p != NULL) {
1081734f297SVictor Perevertkin pbuf_free(buf->p);
1091734f297SVictor Perevertkin }
1101734f297SVictor Perevertkin buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
1111734f297SVictor Perevertkin if (buf->p == NULL) {
1121734f297SVictor Perevertkin return NULL;
1131734f297SVictor Perevertkin }
1141734f297SVictor Perevertkin LWIP_ASSERT("check that first pbuf can hold size",
1151734f297SVictor Perevertkin (buf->p->len >= size));
1161734f297SVictor Perevertkin buf->ptr = buf->p;
1171734f297SVictor Perevertkin return buf->p->payload;
1181734f297SVictor Perevertkin }
1191734f297SVictor Perevertkin
1201734f297SVictor Perevertkin /**
121*d6eebaa4SHervé Poussineau * @ingroup netbuf
1221734f297SVictor Perevertkin * Free the packet buffer included in a netbuf
1231734f297SVictor Perevertkin *
1241734f297SVictor Perevertkin * @param buf pointer to the netbuf which contains the packet buffer to free
1251734f297SVictor Perevertkin */
1261734f297SVictor Perevertkin void
netbuf_free(struct netbuf * buf)1271734f297SVictor Perevertkin netbuf_free(struct netbuf *buf)
1281734f297SVictor Perevertkin {
1291734f297SVictor Perevertkin LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
1301734f297SVictor Perevertkin if (buf->p != NULL) {
1311734f297SVictor Perevertkin pbuf_free(buf->p);
1321734f297SVictor Perevertkin }
1331734f297SVictor Perevertkin buf->p = buf->ptr = NULL;
134*d6eebaa4SHervé Poussineau #if LWIP_CHECKSUM_ON_COPY
135*d6eebaa4SHervé Poussineau buf->flags = 0;
136*d6eebaa4SHervé Poussineau buf->toport_chksum = 0;
137*d6eebaa4SHervé Poussineau #endif /* LWIP_CHECKSUM_ON_COPY */
1381734f297SVictor Perevertkin }
1391734f297SVictor Perevertkin
1401734f297SVictor Perevertkin /**
141*d6eebaa4SHervé Poussineau * @ingroup netbuf
1421734f297SVictor Perevertkin * Let a netbuf reference existing (non-volatile) data.
1431734f297SVictor Perevertkin *
1441734f297SVictor Perevertkin * @param buf netbuf which should reference the data
1451734f297SVictor Perevertkin * @param dataptr pointer to the data to reference
1461734f297SVictor Perevertkin * @param size size of the data
1471734f297SVictor Perevertkin * @return ERR_OK if data is referenced
1481734f297SVictor Perevertkin * ERR_MEM if data couldn't be referenced due to lack of memory
1491734f297SVictor Perevertkin */
1501734f297SVictor Perevertkin err_t
netbuf_ref(struct netbuf * buf,const void * dataptr,u16_t size)1511734f297SVictor Perevertkin netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
1521734f297SVictor Perevertkin {
1531734f297SVictor Perevertkin LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
1541734f297SVictor Perevertkin if (buf->p != NULL) {
1551734f297SVictor Perevertkin pbuf_free(buf->p);
1561734f297SVictor Perevertkin }
1571734f297SVictor Perevertkin buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
1581734f297SVictor Perevertkin if (buf->p == NULL) {
1591734f297SVictor Perevertkin buf->ptr = NULL;
1601734f297SVictor Perevertkin return ERR_MEM;
1611734f297SVictor Perevertkin }
162*d6eebaa4SHervé Poussineau ((struct pbuf_rom *)buf->p)->payload = dataptr;
1631734f297SVictor Perevertkin buf->p->len = buf->p->tot_len = size;
1641734f297SVictor Perevertkin buf->ptr = buf->p;
1651734f297SVictor Perevertkin return ERR_OK;
1661734f297SVictor Perevertkin }
1671734f297SVictor Perevertkin
1681734f297SVictor Perevertkin /**
169*d6eebaa4SHervé Poussineau * @ingroup netbuf
1701734f297SVictor Perevertkin * Chain one netbuf to another (@see pbuf_chain)
1711734f297SVictor Perevertkin *
1721734f297SVictor Perevertkin * @param head the first netbuf
1731734f297SVictor Perevertkin * @param tail netbuf to chain after head, freed by this function, may not be reference after returning
1741734f297SVictor Perevertkin */
1751734f297SVictor Perevertkin void
netbuf_chain(struct netbuf * head,struct netbuf * tail)1761734f297SVictor Perevertkin netbuf_chain(struct netbuf *head, struct netbuf *tail)
1771734f297SVictor Perevertkin {
178*d6eebaa4SHervé Poussineau LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;);
1791734f297SVictor Perevertkin LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
1801734f297SVictor Perevertkin pbuf_cat(head->p, tail->p);
1811734f297SVictor Perevertkin head->ptr = head->p;
1821734f297SVictor Perevertkin memp_free(MEMP_NETBUF, tail);
1831734f297SVictor Perevertkin }
1841734f297SVictor Perevertkin
1851734f297SVictor Perevertkin /**
186*d6eebaa4SHervé Poussineau * @ingroup netbuf
1871734f297SVictor Perevertkin * Get the data pointer and length of the data inside a netbuf.
1881734f297SVictor Perevertkin *
1891734f297SVictor Perevertkin * @param buf netbuf to get the data from
1901734f297SVictor Perevertkin * @param dataptr pointer to a void pointer where to store the data pointer
1911734f297SVictor Perevertkin * @param len pointer to an u16_t where the length of the data is stored
192*d6eebaa4SHervé Poussineau * @return ERR_OK if the information was retrieved,
1931734f297SVictor Perevertkin * ERR_BUF on error.
1941734f297SVictor Perevertkin */
1951734f297SVictor Perevertkin err_t
netbuf_data(struct netbuf * buf,void ** dataptr,u16_t * len)1961734f297SVictor Perevertkin netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
1971734f297SVictor Perevertkin {
1981734f297SVictor Perevertkin LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
1991734f297SVictor Perevertkin LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
2001734f297SVictor Perevertkin LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
2011734f297SVictor Perevertkin
2021734f297SVictor Perevertkin if (buf->ptr == NULL) {
2031734f297SVictor Perevertkin return ERR_BUF;
2041734f297SVictor Perevertkin }
2051734f297SVictor Perevertkin *dataptr = buf->ptr->payload;
2061734f297SVictor Perevertkin *len = buf->ptr->len;
2071734f297SVictor Perevertkin return ERR_OK;
2081734f297SVictor Perevertkin }
2091734f297SVictor Perevertkin
2101734f297SVictor Perevertkin /**
211*d6eebaa4SHervé Poussineau * @ingroup netbuf
2121734f297SVictor Perevertkin * Move the current data pointer of a packet buffer contained in a netbuf
2131734f297SVictor Perevertkin * to the next part.
2141734f297SVictor Perevertkin * The packet buffer itself is not modified.
2151734f297SVictor Perevertkin *
2161734f297SVictor Perevertkin * @param buf the netbuf to modify
2171734f297SVictor Perevertkin * @return -1 if there is no next part
2181734f297SVictor Perevertkin * 1 if moved to the next part but now there is no next part
2191734f297SVictor Perevertkin * 0 if moved to the next part and there are still more parts
2201734f297SVictor Perevertkin */
2211734f297SVictor Perevertkin s8_t
netbuf_next(struct netbuf * buf)2221734f297SVictor Perevertkin netbuf_next(struct netbuf *buf)
2231734f297SVictor Perevertkin {
224*d6eebaa4SHervé Poussineau LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;);
2251734f297SVictor Perevertkin if (buf->ptr->next == NULL) {
2261734f297SVictor Perevertkin return -1;
2271734f297SVictor Perevertkin }
2281734f297SVictor Perevertkin buf->ptr = buf->ptr->next;
2291734f297SVictor Perevertkin if (buf->ptr->next == NULL) {
2301734f297SVictor Perevertkin return 1;
2311734f297SVictor Perevertkin }
2321734f297SVictor Perevertkin return 0;
2331734f297SVictor Perevertkin }
2341734f297SVictor Perevertkin
2351734f297SVictor Perevertkin /**
236*d6eebaa4SHervé Poussineau * @ingroup netbuf
2371734f297SVictor Perevertkin * Move the current data pointer of a packet buffer contained in a netbuf
2381734f297SVictor Perevertkin * to the beginning of the packet.
2391734f297SVictor Perevertkin * The packet buffer itself is not modified.
2401734f297SVictor Perevertkin *
2411734f297SVictor Perevertkin * @param buf the netbuf to modify
2421734f297SVictor Perevertkin */
2431734f297SVictor Perevertkin void
netbuf_first(struct netbuf * buf)2441734f297SVictor Perevertkin netbuf_first(struct netbuf *buf)
2451734f297SVictor Perevertkin {
246*d6eebaa4SHervé Poussineau LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;);
2471734f297SVictor Perevertkin buf->ptr = buf->p;
2481734f297SVictor Perevertkin }
2491734f297SVictor Perevertkin
2501734f297SVictor Perevertkin #endif /* LWIP_NETCONN */
251