1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * Network buffer management 4195972f6Sopenharmony_ci * 5195972f6Sopenharmony_ci * @defgroup netbuf Network buffers 6195972f6Sopenharmony_ci * @ingroup netconn 7195972f6Sopenharmony_ci * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally 8195972f6Sopenharmony_ci * to avoid copying data around.\n 9195972f6Sopenharmony_ci * Buffers must not be shared accross multiple threads, all functions except 10195972f6Sopenharmony_ci * netbuf_new() and netbuf_delete() are not thread-safe. 11195972f6Sopenharmony_ci */ 12195972f6Sopenharmony_ci 13195972f6Sopenharmony_ci/* 14195972f6Sopenharmony_ci * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 15195972f6Sopenharmony_ci * All rights reserved. 16195972f6Sopenharmony_ci * 17195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 18195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 19195972f6Sopenharmony_ci * 20195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 21195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 22195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 23195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 24195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 25195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 26195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 27195972f6Sopenharmony_ci * 28195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 29195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 30195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 31195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 32195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 33195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 36195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 37195972f6Sopenharmony_ci * OF SUCH DAMAGE. 38195972f6Sopenharmony_ci * 39195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack. 40195972f6Sopenharmony_ci * 41195972f6Sopenharmony_ci * Author: Adam Dunkels <adam@sics.se> 42195972f6Sopenharmony_ci * 43195972f6Sopenharmony_ci */ 44195972f6Sopenharmony_ci 45195972f6Sopenharmony_ci#include "lwip/opt.h" 46195972f6Sopenharmony_ci 47195972f6Sopenharmony_ci#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ 48195972f6Sopenharmony_ci 49195972f6Sopenharmony_ci#include "lwip/netbuf.h" 50195972f6Sopenharmony_ci#include "lwip/memp.h" 51195972f6Sopenharmony_ci 52195972f6Sopenharmony_ci#include <string.h> 53195972f6Sopenharmony_ci 54195972f6Sopenharmony_ci/** 55195972f6Sopenharmony_ci * @ingroup netbuf 56195972f6Sopenharmony_ci * Create (allocate) and initialize a new netbuf. 57195972f6Sopenharmony_ci * The netbuf doesn't yet contain a packet buffer! 58195972f6Sopenharmony_ci * 59195972f6Sopenharmony_ci * @return a pointer to a new netbuf 60195972f6Sopenharmony_ci * NULL on lack of memory 61195972f6Sopenharmony_ci */ 62195972f6Sopenharmony_cistruct 63195972f6Sopenharmony_cinetbuf *netbuf_new(void) 64195972f6Sopenharmony_ci{ 65195972f6Sopenharmony_ci struct netbuf *buf; 66195972f6Sopenharmony_ci 67195972f6Sopenharmony_ci buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); 68195972f6Sopenharmony_ci if (buf != NULL) { 69195972f6Sopenharmony_ci memset(buf, 0, sizeof(struct netbuf)); 70195972f6Sopenharmony_ci } 71195972f6Sopenharmony_ci return buf; 72195972f6Sopenharmony_ci} 73195972f6Sopenharmony_ci 74195972f6Sopenharmony_ci/** 75195972f6Sopenharmony_ci * @ingroup netbuf 76195972f6Sopenharmony_ci * Deallocate a netbuf allocated by netbuf_new(). 77195972f6Sopenharmony_ci * 78195972f6Sopenharmony_ci * @param buf pointer to a netbuf allocated by netbuf_new() 79195972f6Sopenharmony_ci */ 80195972f6Sopenharmony_civoid 81195972f6Sopenharmony_cinetbuf_delete(struct netbuf *buf) 82195972f6Sopenharmony_ci{ 83195972f6Sopenharmony_ci if (buf != NULL) { 84195972f6Sopenharmony_ci if (buf->p != NULL) { 85195972f6Sopenharmony_ci pbuf_free(buf->p); 86195972f6Sopenharmony_ci buf->p = buf->ptr = NULL; 87195972f6Sopenharmony_ci } 88195972f6Sopenharmony_ci memp_free(MEMP_NETBUF, buf); 89195972f6Sopenharmony_ci } 90195972f6Sopenharmony_ci} 91195972f6Sopenharmony_ci 92195972f6Sopenharmony_ci/** 93195972f6Sopenharmony_ci * @ingroup netbuf 94195972f6Sopenharmony_ci * Allocate memory for a packet buffer for a given netbuf. 95195972f6Sopenharmony_ci * 96195972f6Sopenharmony_ci * @param buf the netbuf for which to allocate a packet buffer 97195972f6Sopenharmony_ci * @param size the size of the packet buffer to allocate 98195972f6Sopenharmony_ci * @return pointer to the allocated memory 99195972f6Sopenharmony_ci * NULL if no memory could be allocated 100195972f6Sopenharmony_ci */ 101195972f6Sopenharmony_civoid * 102195972f6Sopenharmony_cinetbuf_alloc(struct netbuf *buf, u16_t size) 103195972f6Sopenharmony_ci{ 104195972f6Sopenharmony_ci LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); 105195972f6Sopenharmony_ci 106195972f6Sopenharmony_ci /* Deallocate any previously allocated memory. */ 107195972f6Sopenharmony_ci if (buf->p != NULL) { 108195972f6Sopenharmony_ci pbuf_free(buf->p); 109195972f6Sopenharmony_ci } 110195972f6Sopenharmony_ci buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); 111195972f6Sopenharmony_ci if (buf->p == NULL) { 112195972f6Sopenharmony_ci return NULL; 113195972f6Sopenharmony_ci } 114195972f6Sopenharmony_ci LWIP_ASSERT("check that first pbuf can hold size", 115195972f6Sopenharmony_ci (buf->p->len >= size)); 116195972f6Sopenharmony_ci buf->ptr = buf->p; 117195972f6Sopenharmony_ci return buf->p->payload; 118195972f6Sopenharmony_ci} 119195972f6Sopenharmony_ci 120195972f6Sopenharmony_ci/** 121195972f6Sopenharmony_ci * @ingroup netbuf 122195972f6Sopenharmony_ci * Free the packet buffer included in a netbuf 123195972f6Sopenharmony_ci * 124195972f6Sopenharmony_ci * @param buf pointer to the netbuf which contains the packet buffer to free 125195972f6Sopenharmony_ci */ 126195972f6Sopenharmony_civoid 127195972f6Sopenharmony_cinetbuf_free(struct netbuf *buf) 128195972f6Sopenharmony_ci{ 129195972f6Sopenharmony_ci LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); 130195972f6Sopenharmony_ci if (buf->p != NULL) { 131195972f6Sopenharmony_ci pbuf_free(buf->p); 132195972f6Sopenharmony_ci } 133195972f6Sopenharmony_ci buf->p = buf->ptr = NULL; 134195972f6Sopenharmony_ci#if LWIP_CHECKSUM_ON_COPY 135195972f6Sopenharmony_ci buf->flags = 0; 136195972f6Sopenharmony_ci buf->toport_chksum = 0; 137195972f6Sopenharmony_ci#endif /* LWIP_CHECKSUM_ON_COPY */ 138195972f6Sopenharmony_ci} 139195972f6Sopenharmony_ci 140195972f6Sopenharmony_ci/** 141195972f6Sopenharmony_ci * @ingroup netbuf 142195972f6Sopenharmony_ci * Let a netbuf reference existing (non-volatile) data. 143195972f6Sopenharmony_ci * 144195972f6Sopenharmony_ci * @param buf netbuf which should reference the data 145195972f6Sopenharmony_ci * @param dataptr pointer to the data to reference 146195972f6Sopenharmony_ci * @param size size of the data 147195972f6Sopenharmony_ci * @return ERR_OK if data is referenced 148195972f6Sopenharmony_ci * ERR_MEM if data couldn't be referenced due to lack of memory 149195972f6Sopenharmony_ci */ 150195972f6Sopenharmony_cierr_t 151195972f6Sopenharmony_cinetbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) 152195972f6Sopenharmony_ci{ 153195972f6Sopenharmony_ci LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); 154195972f6Sopenharmony_ci if (buf->p != NULL) { 155195972f6Sopenharmony_ci pbuf_free(buf->p); 156195972f6Sopenharmony_ci } 157195972f6Sopenharmony_ci buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); 158195972f6Sopenharmony_ci if (buf->p == NULL) { 159195972f6Sopenharmony_ci buf->ptr = NULL; 160195972f6Sopenharmony_ci return ERR_MEM; 161195972f6Sopenharmony_ci } 162195972f6Sopenharmony_ci ((struct pbuf_rom *)buf->p)->payload = dataptr; 163195972f6Sopenharmony_ci buf->p->len = buf->p->tot_len = size; 164195972f6Sopenharmony_ci buf->ptr = buf->p; 165195972f6Sopenharmony_ci return ERR_OK; 166195972f6Sopenharmony_ci} 167195972f6Sopenharmony_ci 168195972f6Sopenharmony_ci/** 169195972f6Sopenharmony_ci * @ingroup netbuf 170195972f6Sopenharmony_ci * Chain one netbuf to another (@see pbuf_chain) 171195972f6Sopenharmony_ci * 172195972f6Sopenharmony_ci * @param head the first netbuf 173195972f6Sopenharmony_ci * @param tail netbuf to chain after head, freed by this function, may not be reference after returning 174195972f6Sopenharmony_ci */ 175195972f6Sopenharmony_civoid 176195972f6Sopenharmony_cinetbuf_chain(struct netbuf *head, struct netbuf *tail) 177195972f6Sopenharmony_ci{ 178195972f6Sopenharmony_ci LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;); 179195972f6Sopenharmony_ci LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); 180195972f6Sopenharmony_ci pbuf_cat(head->p, tail->p); 181195972f6Sopenharmony_ci head->ptr = head->p; 182195972f6Sopenharmony_ci memp_free(MEMP_NETBUF, tail); 183195972f6Sopenharmony_ci} 184195972f6Sopenharmony_ci 185195972f6Sopenharmony_ci/** 186195972f6Sopenharmony_ci * @ingroup netbuf 187195972f6Sopenharmony_ci * Get the data pointer and length of the data inside a netbuf. 188195972f6Sopenharmony_ci * 189195972f6Sopenharmony_ci * @param buf netbuf to get the data from 190195972f6Sopenharmony_ci * @param dataptr pointer to a void pointer where to store the data pointer 191195972f6Sopenharmony_ci * @param len pointer to an u16_t where the length of the data is stored 192195972f6Sopenharmony_ci * @return ERR_OK if the information was retrieved, 193195972f6Sopenharmony_ci * ERR_BUF on error. 194195972f6Sopenharmony_ci */ 195195972f6Sopenharmony_cierr_t 196195972f6Sopenharmony_cinetbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) 197195972f6Sopenharmony_ci{ 198195972f6Sopenharmony_ci LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); 199195972f6Sopenharmony_ci LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); 200195972f6Sopenharmony_ci LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); 201195972f6Sopenharmony_ci 202195972f6Sopenharmony_ci if (buf->ptr == NULL) { 203195972f6Sopenharmony_ci return ERR_BUF; 204195972f6Sopenharmony_ci } 205195972f6Sopenharmony_ci *dataptr = buf->ptr->payload; 206195972f6Sopenharmony_ci *len = buf->ptr->len; 207195972f6Sopenharmony_ci return ERR_OK; 208195972f6Sopenharmony_ci} 209195972f6Sopenharmony_ci 210195972f6Sopenharmony_ci/** 211195972f6Sopenharmony_ci * @ingroup netbuf 212195972f6Sopenharmony_ci * Move the current data pointer of a packet buffer contained in a netbuf 213195972f6Sopenharmony_ci * to the next part. 214195972f6Sopenharmony_ci * The packet buffer itself is not modified. 215195972f6Sopenharmony_ci * 216195972f6Sopenharmony_ci * @param buf the netbuf to modify 217195972f6Sopenharmony_ci * @return -1 if there is no next part 218195972f6Sopenharmony_ci * 1 if moved to the next part but now there is no next part 219195972f6Sopenharmony_ci * 0 if moved to the next part and there are still more parts 220195972f6Sopenharmony_ci */ 221195972f6Sopenharmony_cis8_t 222195972f6Sopenharmony_cinetbuf_next(struct netbuf *buf) 223195972f6Sopenharmony_ci{ 224195972f6Sopenharmony_ci LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;); 225195972f6Sopenharmony_ci if (buf->ptr->next == NULL) { 226195972f6Sopenharmony_ci return -1; 227195972f6Sopenharmony_ci } 228195972f6Sopenharmony_ci buf->ptr = buf->ptr->next; 229195972f6Sopenharmony_ci if (buf->ptr->next == NULL) { 230195972f6Sopenharmony_ci return 1; 231195972f6Sopenharmony_ci } 232195972f6Sopenharmony_ci return 0; 233195972f6Sopenharmony_ci} 234195972f6Sopenharmony_ci 235195972f6Sopenharmony_ci/** 236195972f6Sopenharmony_ci * @ingroup netbuf 237195972f6Sopenharmony_ci * Move the current data pointer of a packet buffer contained in a netbuf 238195972f6Sopenharmony_ci * to the beginning of the packet. 239195972f6Sopenharmony_ci * The packet buffer itself is not modified. 240195972f6Sopenharmony_ci * 241195972f6Sopenharmony_ci * @param buf the netbuf to modify 242195972f6Sopenharmony_ci */ 243195972f6Sopenharmony_civoid 244195972f6Sopenharmony_cinetbuf_first(struct netbuf *buf) 245195972f6Sopenharmony_ci{ 246195972f6Sopenharmony_ci LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;); 247195972f6Sopenharmony_ci buf->ptr = buf->p; 248195972f6Sopenharmony_ci} 249195972f6Sopenharmony_ci 250195972f6Sopenharmony_ci#endif /* LWIP_NETCONN */ 251