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