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