1*5d5fbe79SDavid van Moolenbroek /**
2*5d5fbe79SDavid van Moolenbroek * @file
3*5d5fbe79SDavid van Moolenbroek * Network buffer management
4*5d5fbe79SDavid van Moolenbroek *
5*5d5fbe79SDavid van Moolenbroek * @defgroup netbuf Network buffers
6*5d5fbe79SDavid van Moolenbroek * @ingroup netconn
7*5d5fbe79SDavid van Moolenbroek * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally
8*5d5fbe79SDavid van Moolenbroek * to avoid copying data around.\n
9*5d5fbe79SDavid van Moolenbroek * Buffers must not be shared accross multiple threads, all functions except
10*5d5fbe79SDavid van Moolenbroek * netbuf_new() and netbuf_delete() are not thread-safe.
11*5d5fbe79SDavid van Moolenbroek */
12*5d5fbe79SDavid van Moolenbroek
13*5d5fbe79SDavid van Moolenbroek /*
14*5d5fbe79SDavid van Moolenbroek * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
15*5d5fbe79SDavid van Moolenbroek * All rights reserved.
16*5d5fbe79SDavid van Moolenbroek *
17*5d5fbe79SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without modification,
18*5d5fbe79SDavid van Moolenbroek * are permitted provided that the following conditions are met:
19*5d5fbe79SDavid van Moolenbroek *
20*5d5fbe79SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright notice,
21*5d5fbe79SDavid van Moolenbroek * this list of conditions and the following disclaimer.
22*5d5fbe79SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright notice,
23*5d5fbe79SDavid van Moolenbroek * this list of conditions and the following disclaimer in the documentation
24*5d5fbe79SDavid van Moolenbroek * and/or other materials provided with the distribution.
25*5d5fbe79SDavid van Moolenbroek * 3. The name of the author may not be used to endorse or promote products
26*5d5fbe79SDavid van Moolenbroek * derived from this software without specific prior written permission.
27*5d5fbe79SDavid van Moolenbroek *
28*5d5fbe79SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
29*5d5fbe79SDavid van Moolenbroek * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30*5d5fbe79SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
31*5d5fbe79SDavid van Moolenbroek * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32*5d5fbe79SDavid van Moolenbroek * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
33*5d5fbe79SDavid van Moolenbroek * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*5d5fbe79SDavid van Moolenbroek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*5d5fbe79SDavid van Moolenbroek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36*5d5fbe79SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37*5d5fbe79SDavid van Moolenbroek * OF SUCH DAMAGE.
38*5d5fbe79SDavid van Moolenbroek *
39*5d5fbe79SDavid van Moolenbroek * This file is part of the lwIP TCP/IP stack.
40*5d5fbe79SDavid van Moolenbroek *
41*5d5fbe79SDavid van Moolenbroek * Author: Adam Dunkels <adam@sics.se>
42*5d5fbe79SDavid van Moolenbroek *
43*5d5fbe79SDavid van Moolenbroek */
44*5d5fbe79SDavid van Moolenbroek
45*5d5fbe79SDavid van Moolenbroek #include "lwip/opt.h"
46*5d5fbe79SDavid van Moolenbroek
47*5d5fbe79SDavid van Moolenbroek #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
48*5d5fbe79SDavid van Moolenbroek
49*5d5fbe79SDavid van Moolenbroek #include "lwip/netbuf.h"
50*5d5fbe79SDavid van Moolenbroek #include "lwip/memp.h"
51*5d5fbe79SDavid van Moolenbroek
52*5d5fbe79SDavid van Moolenbroek #include <string.h>
53*5d5fbe79SDavid van Moolenbroek
54*5d5fbe79SDavid van Moolenbroek /**
55*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
56*5d5fbe79SDavid van Moolenbroek * Create (allocate) and initialize a new netbuf.
57*5d5fbe79SDavid van Moolenbroek * The netbuf doesn't yet contain a packet buffer!
58*5d5fbe79SDavid van Moolenbroek *
59*5d5fbe79SDavid van Moolenbroek * @return a pointer to a new netbuf
60*5d5fbe79SDavid van Moolenbroek * NULL on lack of memory
61*5d5fbe79SDavid van Moolenbroek */
62*5d5fbe79SDavid van Moolenbroek struct
netbuf_new(void)63*5d5fbe79SDavid van Moolenbroek netbuf *netbuf_new(void)
64*5d5fbe79SDavid van Moolenbroek {
65*5d5fbe79SDavid van Moolenbroek struct netbuf *buf;
66*5d5fbe79SDavid van Moolenbroek
67*5d5fbe79SDavid van Moolenbroek buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
68*5d5fbe79SDavid van Moolenbroek if (buf != NULL) {
69*5d5fbe79SDavid van Moolenbroek memset(buf, 0, sizeof(struct netbuf));
70*5d5fbe79SDavid van Moolenbroek }
71*5d5fbe79SDavid van Moolenbroek return buf;
72*5d5fbe79SDavid van Moolenbroek }
73*5d5fbe79SDavid van Moolenbroek
74*5d5fbe79SDavid van Moolenbroek /**
75*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
76*5d5fbe79SDavid van Moolenbroek * Deallocate a netbuf allocated by netbuf_new().
77*5d5fbe79SDavid van Moolenbroek *
78*5d5fbe79SDavid van Moolenbroek * @param buf pointer to a netbuf allocated by netbuf_new()
79*5d5fbe79SDavid van Moolenbroek */
80*5d5fbe79SDavid van Moolenbroek void
netbuf_delete(struct netbuf * buf)81*5d5fbe79SDavid van Moolenbroek netbuf_delete(struct netbuf *buf)
82*5d5fbe79SDavid van Moolenbroek {
83*5d5fbe79SDavid van Moolenbroek if (buf != NULL) {
84*5d5fbe79SDavid van Moolenbroek if (buf->p != NULL) {
85*5d5fbe79SDavid van Moolenbroek pbuf_free(buf->p);
86*5d5fbe79SDavid van Moolenbroek buf->p = buf->ptr = NULL;
87*5d5fbe79SDavid van Moolenbroek }
88*5d5fbe79SDavid van Moolenbroek memp_free(MEMP_NETBUF, buf);
89*5d5fbe79SDavid van Moolenbroek }
90*5d5fbe79SDavid van Moolenbroek }
91*5d5fbe79SDavid van Moolenbroek
92*5d5fbe79SDavid van Moolenbroek /**
93*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
94*5d5fbe79SDavid van Moolenbroek * Allocate memory for a packet buffer for a given netbuf.
95*5d5fbe79SDavid van Moolenbroek *
96*5d5fbe79SDavid van Moolenbroek * @param buf the netbuf for which to allocate a packet buffer
97*5d5fbe79SDavid van Moolenbroek * @param size the size of the packet buffer to allocate
98*5d5fbe79SDavid van Moolenbroek * @return pointer to the allocated memory
99*5d5fbe79SDavid van Moolenbroek * NULL if no memory could be allocated
100*5d5fbe79SDavid van Moolenbroek */
101*5d5fbe79SDavid van Moolenbroek void *
netbuf_alloc(struct netbuf * buf,u16_t size)102*5d5fbe79SDavid van Moolenbroek netbuf_alloc(struct netbuf *buf, u16_t size)
103*5d5fbe79SDavid van Moolenbroek {
104*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
105*5d5fbe79SDavid van Moolenbroek
106*5d5fbe79SDavid van Moolenbroek /* Deallocate any previously allocated memory. */
107*5d5fbe79SDavid van Moolenbroek if (buf->p != NULL) {
108*5d5fbe79SDavid van Moolenbroek pbuf_free(buf->p);
109*5d5fbe79SDavid van Moolenbroek }
110*5d5fbe79SDavid van Moolenbroek buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
111*5d5fbe79SDavid van Moolenbroek if (buf->p == NULL) {
112*5d5fbe79SDavid van Moolenbroek return NULL;
113*5d5fbe79SDavid van Moolenbroek }
114*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("check that first pbuf can hold size",
115*5d5fbe79SDavid van Moolenbroek (buf->p->len >= size));
116*5d5fbe79SDavid van Moolenbroek buf->ptr = buf->p;
117*5d5fbe79SDavid van Moolenbroek return buf->p->payload;
118*5d5fbe79SDavid van Moolenbroek }
119*5d5fbe79SDavid van Moolenbroek
120*5d5fbe79SDavid van Moolenbroek /**
121*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
122*5d5fbe79SDavid van Moolenbroek * Free the packet buffer included in a netbuf
123*5d5fbe79SDavid van Moolenbroek *
124*5d5fbe79SDavid van Moolenbroek * @param buf pointer to the netbuf which contains the packet buffer to free
125*5d5fbe79SDavid van Moolenbroek */
126*5d5fbe79SDavid van Moolenbroek void
netbuf_free(struct netbuf * buf)127*5d5fbe79SDavid van Moolenbroek netbuf_free(struct netbuf *buf)
128*5d5fbe79SDavid van Moolenbroek {
129*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
130*5d5fbe79SDavid van Moolenbroek if (buf->p != NULL) {
131*5d5fbe79SDavid van Moolenbroek pbuf_free(buf->p);
132*5d5fbe79SDavid van Moolenbroek }
133*5d5fbe79SDavid van Moolenbroek buf->p = buf->ptr = NULL;
134*5d5fbe79SDavid van Moolenbroek #if LWIP_CHECKSUM_ON_COPY
135*5d5fbe79SDavid van Moolenbroek buf->flags = 0;
136*5d5fbe79SDavid van Moolenbroek buf->toport_chksum = 0;
137*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_CHECKSUM_ON_COPY */
138*5d5fbe79SDavid van Moolenbroek }
139*5d5fbe79SDavid van Moolenbroek
140*5d5fbe79SDavid van Moolenbroek /**
141*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
142*5d5fbe79SDavid van Moolenbroek * Let a netbuf reference existing (non-volatile) data.
143*5d5fbe79SDavid van Moolenbroek *
144*5d5fbe79SDavid van Moolenbroek * @param buf netbuf which should reference the data
145*5d5fbe79SDavid van Moolenbroek * @param dataptr pointer to the data to reference
146*5d5fbe79SDavid van Moolenbroek * @param size size of the data
147*5d5fbe79SDavid van Moolenbroek * @return ERR_OK if data is referenced
148*5d5fbe79SDavid van Moolenbroek * ERR_MEM if data couldn't be referenced due to lack of memory
149*5d5fbe79SDavid van Moolenbroek */
150*5d5fbe79SDavid van Moolenbroek err_t
netbuf_ref(struct netbuf * buf,const void * dataptr,u16_t size)151*5d5fbe79SDavid van Moolenbroek netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
152*5d5fbe79SDavid van Moolenbroek {
153*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
154*5d5fbe79SDavid van Moolenbroek if (buf->p != NULL) {
155*5d5fbe79SDavid van Moolenbroek pbuf_free(buf->p);
156*5d5fbe79SDavid van Moolenbroek }
157*5d5fbe79SDavid van Moolenbroek buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
158*5d5fbe79SDavid van Moolenbroek if (buf->p == NULL) {
159*5d5fbe79SDavid van Moolenbroek buf->ptr = NULL;
160*5d5fbe79SDavid van Moolenbroek return ERR_MEM;
161*5d5fbe79SDavid van Moolenbroek }
162*5d5fbe79SDavid van Moolenbroek ((struct pbuf_rom*)buf->p)->payload = dataptr;
163*5d5fbe79SDavid van Moolenbroek buf->p->len = buf->p->tot_len = size;
164*5d5fbe79SDavid van Moolenbroek buf->ptr = buf->p;
165*5d5fbe79SDavid van Moolenbroek return ERR_OK;
166*5d5fbe79SDavid van Moolenbroek }
167*5d5fbe79SDavid van Moolenbroek
168*5d5fbe79SDavid van Moolenbroek /**
169*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
170*5d5fbe79SDavid van Moolenbroek * Chain one netbuf to another (@see pbuf_chain)
171*5d5fbe79SDavid van Moolenbroek *
172*5d5fbe79SDavid van Moolenbroek * @param head the first netbuf
173*5d5fbe79SDavid van Moolenbroek * @param tail netbuf to chain after head, freed by this function, may not be reference after returning
174*5d5fbe79SDavid van Moolenbroek */
175*5d5fbe79SDavid van Moolenbroek void
netbuf_chain(struct netbuf * head,struct netbuf * tail)176*5d5fbe79SDavid van Moolenbroek netbuf_chain(struct netbuf *head, struct netbuf *tail)
177*5d5fbe79SDavid van Moolenbroek {
178*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;);
179*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
180*5d5fbe79SDavid van Moolenbroek pbuf_cat(head->p, tail->p);
181*5d5fbe79SDavid van Moolenbroek head->ptr = head->p;
182*5d5fbe79SDavid van Moolenbroek memp_free(MEMP_NETBUF, tail);
183*5d5fbe79SDavid van Moolenbroek }
184*5d5fbe79SDavid van Moolenbroek
185*5d5fbe79SDavid van Moolenbroek /**
186*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
187*5d5fbe79SDavid van Moolenbroek * Get the data pointer and length of the data inside a netbuf.
188*5d5fbe79SDavid van Moolenbroek *
189*5d5fbe79SDavid van Moolenbroek * @param buf netbuf to get the data from
190*5d5fbe79SDavid van Moolenbroek * @param dataptr pointer to a void pointer where to store the data pointer
191*5d5fbe79SDavid van Moolenbroek * @param len pointer to an u16_t where the length of the data is stored
192*5d5fbe79SDavid van Moolenbroek * @return ERR_OK if the information was retrieved,
193*5d5fbe79SDavid van Moolenbroek * ERR_BUF on error.
194*5d5fbe79SDavid van Moolenbroek */
195*5d5fbe79SDavid van Moolenbroek err_t
netbuf_data(struct netbuf * buf,void ** dataptr,u16_t * len)196*5d5fbe79SDavid van Moolenbroek netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
197*5d5fbe79SDavid van Moolenbroek {
198*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
199*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
200*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
201*5d5fbe79SDavid van Moolenbroek
202*5d5fbe79SDavid van Moolenbroek if (buf->ptr == NULL) {
203*5d5fbe79SDavid van Moolenbroek return ERR_BUF;
204*5d5fbe79SDavid van Moolenbroek }
205*5d5fbe79SDavid van Moolenbroek *dataptr = buf->ptr->payload;
206*5d5fbe79SDavid van Moolenbroek *len = buf->ptr->len;
207*5d5fbe79SDavid van Moolenbroek return ERR_OK;
208*5d5fbe79SDavid van Moolenbroek }
209*5d5fbe79SDavid van Moolenbroek
210*5d5fbe79SDavid van Moolenbroek /**
211*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
212*5d5fbe79SDavid van Moolenbroek * Move the current data pointer of a packet buffer contained in a netbuf
213*5d5fbe79SDavid van Moolenbroek * to the next part.
214*5d5fbe79SDavid van Moolenbroek * The packet buffer itself is not modified.
215*5d5fbe79SDavid van Moolenbroek *
216*5d5fbe79SDavid van Moolenbroek * @param buf the netbuf to modify
217*5d5fbe79SDavid van Moolenbroek * @return -1 if there is no next part
218*5d5fbe79SDavid van Moolenbroek * 1 if moved to the next part but now there is no next part
219*5d5fbe79SDavid van Moolenbroek * 0 if moved to the next part and there are still more parts
220*5d5fbe79SDavid van Moolenbroek */
221*5d5fbe79SDavid van Moolenbroek s8_t
netbuf_next(struct netbuf * buf)222*5d5fbe79SDavid van Moolenbroek netbuf_next(struct netbuf *buf)
223*5d5fbe79SDavid van Moolenbroek {
224*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;);
225*5d5fbe79SDavid van Moolenbroek if (buf->ptr->next == NULL) {
226*5d5fbe79SDavid van Moolenbroek return -1;
227*5d5fbe79SDavid van Moolenbroek }
228*5d5fbe79SDavid van Moolenbroek buf->ptr = buf->ptr->next;
229*5d5fbe79SDavid van Moolenbroek if (buf->ptr->next == NULL) {
230*5d5fbe79SDavid van Moolenbroek return 1;
231*5d5fbe79SDavid van Moolenbroek }
232*5d5fbe79SDavid van Moolenbroek return 0;
233*5d5fbe79SDavid van Moolenbroek }
234*5d5fbe79SDavid van Moolenbroek
235*5d5fbe79SDavid van Moolenbroek /**
236*5d5fbe79SDavid van Moolenbroek * @ingroup netbuf
237*5d5fbe79SDavid van Moolenbroek * Move the current data pointer of a packet buffer contained in a netbuf
238*5d5fbe79SDavid van Moolenbroek * to the beginning of the packet.
239*5d5fbe79SDavid van Moolenbroek * The packet buffer itself is not modified.
240*5d5fbe79SDavid van Moolenbroek *
241*5d5fbe79SDavid van Moolenbroek * @param buf the netbuf to modify
242*5d5fbe79SDavid van Moolenbroek */
243*5d5fbe79SDavid van Moolenbroek void
netbuf_first(struct netbuf * buf)244*5d5fbe79SDavid van Moolenbroek netbuf_first(struct netbuf *buf)
245*5d5fbe79SDavid van Moolenbroek {
246*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;);
247*5d5fbe79SDavid van Moolenbroek buf->ptr = buf->p;
248*5d5fbe79SDavid van Moolenbroek }
249*5d5fbe79SDavid van Moolenbroek
250*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_NETCONN */
251