Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Committer:
iva2k
Date:
Sat Jun 12 06:01:50 2010 +0000
Revision:
0:e614f7875b60

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
iva2k 0:e614f7875b60 1 /**
iva2k 0:e614f7875b60 2 * @file
iva2k 0:e614f7875b60 3 * Implementation of raw protocol PCBs for low-level handling of
iva2k 0:e614f7875b60 4 * different types of protocols besides (or overriding) those
iva2k 0:e614f7875b60 5 * already available in lwIP.
iva2k 0:e614f7875b60 6 *
iva2k 0:e614f7875b60 7 */
iva2k 0:e614f7875b60 8
iva2k 0:e614f7875b60 9 /*
iva2k 0:e614f7875b60 10 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
iva2k 0:e614f7875b60 11 * All rights reserved.
iva2k 0:e614f7875b60 12 *
iva2k 0:e614f7875b60 13 * Redistribution and use in source and binary forms, with or without modification,
iva2k 0:e614f7875b60 14 * are permitted provided that the following conditions are met:
iva2k 0:e614f7875b60 15 *
iva2k 0:e614f7875b60 16 * 1. Redistributions of source code must retain the above copyright notice,
iva2k 0:e614f7875b60 17 * this list of conditions and the following disclaimer.
iva2k 0:e614f7875b60 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
iva2k 0:e614f7875b60 19 * this list of conditions and the following disclaimer in the documentation
iva2k 0:e614f7875b60 20 * and/or other materials provided with the distribution.
iva2k 0:e614f7875b60 21 * 3. The name of the author may not be used to endorse or promote products
iva2k 0:e614f7875b60 22 * derived from this software without specific prior written permission.
iva2k 0:e614f7875b60 23 *
iva2k 0:e614f7875b60 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
iva2k 0:e614f7875b60 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
iva2k 0:e614f7875b60 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
iva2k 0:e614f7875b60 27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
iva2k 0:e614f7875b60 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
iva2k 0:e614f7875b60 29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
iva2k 0:e614f7875b60 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
iva2k 0:e614f7875b60 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
iva2k 0:e614f7875b60 32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
iva2k 0:e614f7875b60 33 * OF SUCH DAMAGE.
iva2k 0:e614f7875b60 34 *
iva2k 0:e614f7875b60 35 * This file is part of the lwIP TCP/IP stack.
iva2k 0:e614f7875b60 36 *
iva2k 0:e614f7875b60 37 * Author: Adam Dunkels <adam@sics.se>
iva2k 0:e614f7875b60 38 *
iva2k 0:e614f7875b60 39 */
iva2k 0:e614f7875b60 40
iva2k 0:e614f7875b60 41 #include "lwip/opt.h"
iva2k 0:e614f7875b60 42
iva2k 0:e614f7875b60 43 #if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
iva2k 0:e614f7875b60 44
iva2k 0:e614f7875b60 45 #include "lwip/def.h"
iva2k 0:e614f7875b60 46 #include "lwip/memp.h"
iva2k 0:e614f7875b60 47 #include "lwip/ip_addr.h"
iva2k 0:e614f7875b60 48 #include "lwip/netif.h"
iva2k 0:e614f7875b60 49 #include "lwip/raw.h"
iva2k 0:e614f7875b60 50 #include "lwip/stats.h"
iva2k 0:e614f7875b60 51 #include "arch/perf.h"
iva2k 0:e614f7875b60 52
iva2k 0:e614f7875b60 53 #include <string.h>
iva2k 0:e614f7875b60 54
iva2k 0:e614f7875b60 55 /** The list of RAW PCBs */
iva2k 0:e614f7875b60 56 static struct raw_pcb *raw_pcbs;
iva2k 0:e614f7875b60 57
iva2k 0:e614f7875b60 58 /**
iva2k 0:e614f7875b60 59 * Determine if in incoming IP packet is covered by a RAW PCB
iva2k 0:e614f7875b60 60 * and if so, pass it to a user-provided receive callback function.
iva2k 0:e614f7875b60 61 *
iva2k 0:e614f7875b60 62 * Given an incoming IP datagram (as a chain of pbufs) this function
iva2k 0:e614f7875b60 63 * finds a corresponding RAW PCB and calls the corresponding receive
iva2k 0:e614f7875b60 64 * callback function.
iva2k 0:e614f7875b60 65 *
iva2k 0:e614f7875b60 66 * @param p pbuf to be demultiplexed to a RAW PCB.
iva2k 0:e614f7875b60 67 * @param inp network interface on which the datagram was received.
iva2k 0:e614f7875b60 68 * @return - 1 if the packet has been eaten by a RAW PCB receive
iva2k 0:e614f7875b60 69 * callback function. The caller MAY NOT not reference the
iva2k 0:e614f7875b60 70 * packet any longer, and MAY NOT call pbuf_free().
iva2k 0:e614f7875b60 71 * @return - 0 if packet is not eaten (pbuf is still referenced by the
iva2k 0:e614f7875b60 72 * caller).
iva2k 0:e614f7875b60 73 *
iva2k 0:e614f7875b60 74 */
iva2k 0:e614f7875b60 75 u8_t
iva2k 0:e614f7875b60 76 raw_input(struct pbuf *p, struct netif *inp)
iva2k 0:e614f7875b60 77 {
iva2k 0:e614f7875b60 78 struct raw_pcb *pcb, *prev;
iva2k 0:e614f7875b60 79 struct ip_hdr *iphdr;
iva2k 0:e614f7875b60 80 s16_t proto;
iva2k 0:e614f7875b60 81 u8_t eaten = 0;
iva2k 0:e614f7875b60 82
iva2k 0:e614f7875b60 83 LWIP_UNUSED_ARG(inp);
iva2k 0:e614f7875b60 84
iva2k 0:e614f7875b60 85 iphdr = (struct ip_hdr *)p->payload;
iva2k 0:e614f7875b60 86 proto = IPH_PROTO(iphdr);
iva2k 0:e614f7875b60 87
iva2k 0:e614f7875b60 88 prev = NULL;
iva2k 0:e614f7875b60 89 pcb = raw_pcbs;
iva2k 0:e614f7875b60 90 /* loop through all raw pcbs until the packet is eaten by one */
iva2k 0:e614f7875b60 91 /* this allows multiple pcbs to match against the packet by design */
iva2k 0:e614f7875b60 92 while ((eaten == 0) && (pcb != NULL)) {
iva2k 0:e614f7875b60 93 if ((pcb->protocol == proto) &&
iva2k 0:e614f7875b60 94 (ip_addr_isany(&pcb->local_ip) ||
iva2k 0:e614f7875b60 95 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
iva2k 0:e614f7875b60 96 #if IP_SOF_BROADCAST_RECV
iva2k 0:e614f7875b60 97 /* broadcast filter? */
iva2k 0:e614f7875b60 98 if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&(iphdr->dest), inp))
iva2k 0:e614f7875b60 99 #endif /* IP_SOF_BROADCAST_RECV */
iva2k 0:e614f7875b60 100 {
iva2k 0:e614f7875b60 101 /* receive callback function available? */
iva2k 0:e614f7875b60 102 if (pcb->recv != NULL) {
iva2k 0:e614f7875b60 103 /* the receive callback function did not eat the packet? */
iva2k 0:e614f7875b60 104 if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) {
iva2k 0:e614f7875b60 105 /* receive function ate the packet */
iva2k 0:e614f7875b60 106 p = NULL;
iva2k 0:e614f7875b60 107 eaten = 1;
iva2k 0:e614f7875b60 108 if (prev != NULL) {
iva2k 0:e614f7875b60 109 /* move the pcb to the front of raw_pcbs so that is
iva2k 0:e614f7875b60 110 found faster next time */
iva2k 0:e614f7875b60 111 prev->next = pcb->next;
iva2k 0:e614f7875b60 112 pcb->next = raw_pcbs;
iva2k 0:e614f7875b60 113 raw_pcbs = pcb;
iva2k 0:e614f7875b60 114 }
iva2k 0:e614f7875b60 115 }
iva2k 0:e614f7875b60 116 }
iva2k 0:e614f7875b60 117 /* no receive callback function was set for this raw PCB */
iva2k 0:e614f7875b60 118 }
iva2k 0:e614f7875b60 119 /* drop the packet */
iva2k 0:e614f7875b60 120 }
iva2k 0:e614f7875b60 121 prev = pcb;
iva2k 0:e614f7875b60 122 pcb = pcb->next;
iva2k 0:e614f7875b60 123 }
iva2k 0:e614f7875b60 124 return eaten;
iva2k 0:e614f7875b60 125 }
iva2k 0:e614f7875b60 126
iva2k 0:e614f7875b60 127 /**
iva2k 0:e614f7875b60 128 * Bind a RAW PCB.
iva2k 0:e614f7875b60 129 *
iva2k 0:e614f7875b60 130 * @param pcb RAW PCB to be bound with a local address ipaddr.
iva2k 0:e614f7875b60 131 * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
iva2k 0:e614f7875b60 132 * bind to all local interfaces.
iva2k 0:e614f7875b60 133 *
iva2k 0:e614f7875b60 134 * @return lwIP error code.
iva2k 0:e614f7875b60 135 * - ERR_OK. Successful. No error occured.
iva2k 0:e614f7875b60 136 * - ERR_USE. The specified IP address is already bound to by
iva2k 0:e614f7875b60 137 * another RAW PCB.
iva2k 0:e614f7875b60 138 *
iva2k 0:e614f7875b60 139 * @see raw_disconnect()
iva2k 0:e614f7875b60 140 */
iva2k 0:e614f7875b60 141 err_t
iva2k 0:e614f7875b60 142 raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
iva2k 0:e614f7875b60 143 {
iva2k 0:e614f7875b60 144 ip_addr_set(&pcb->local_ip, ipaddr);
iva2k 0:e614f7875b60 145 return ERR_OK;
iva2k 0:e614f7875b60 146 }
iva2k 0:e614f7875b60 147
iva2k 0:e614f7875b60 148 /**
iva2k 0:e614f7875b60 149 * Connect an RAW PCB. This function is required by upper layers
iva2k 0:e614f7875b60 150 * of lwip. Using the raw api you could use raw_sendto() instead
iva2k 0:e614f7875b60 151 *
iva2k 0:e614f7875b60 152 * This will associate the RAW PCB with the remote address.
iva2k 0:e614f7875b60 153 *
iva2k 0:e614f7875b60 154 * @param pcb RAW PCB to be connected with remote address ipaddr and port.
iva2k 0:e614f7875b60 155 * @param ipaddr remote IP address to connect with.
iva2k 0:e614f7875b60 156 *
iva2k 0:e614f7875b60 157 * @return lwIP error code
iva2k 0:e614f7875b60 158 *
iva2k 0:e614f7875b60 159 * @see raw_disconnect() and raw_sendto()
iva2k 0:e614f7875b60 160 */
iva2k 0:e614f7875b60 161 err_t
iva2k 0:e614f7875b60 162 raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
iva2k 0:e614f7875b60 163 {
iva2k 0:e614f7875b60 164 ip_addr_set(&pcb->remote_ip, ipaddr);
iva2k 0:e614f7875b60 165 return ERR_OK;
iva2k 0:e614f7875b60 166 }
iva2k 0:e614f7875b60 167
iva2k 0:e614f7875b60 168
iva2k 0:e614f7875b60 169 /**
iva2k 0:e614f7875b60 170 * Set the callback function for received packets that match the
iva2k 0:e614f7875b60 171 * raw PCB's protocol and binding.
iva2k 0:e614f7875b60 172 *
iva2k 0:e614f7875b60 173 * The callback function MUST either
iva2k 0:e614f7875b60 174 * - eat the packet by calling pbuf_free() and returning non-zero. The
iva2k 0:e614f7875b60 175 * packet will not be passed to other raw PCBs or other protocol layers.
iva2k 0:e614f7875b60 176 * - not free the packet, and return zero. The packet will be matched
iva2k 0:e614f7875b60 177 * against further PCBs and/or forwarded to another protocol layers.
iva2k 0:e614f7875b60 178 *
iva2k 0:e614f7875b60 179 * @return non-zero if the packet was free()d, zero if the packet remains
iva2k 0:e614f7875b60 180 * available for others.
iva2k 0:e614f7875b60 181 */
iva2k 0:e614f7875b60 182 void
iva2k 0:e614f7875b60 183 raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
iva2k 0:e614f7875b60 184 {
iva2k 0:e614f7875b60 185 /* remember recv() callback and user data */
iva2k 0:e614f7875b60 186 pcb->recv = recv;
iva2k 0:e614f7875b60 187 pcb->recv_arg = recv_arg;
iva2k 0:e614f7875b60 188 }
iva2k 0:e614f7875b60 189
iva2k 0:e614f7875b60 190 /**
iva2k 0:e614f7875b60 191 * Send the raw IP packet to the given address. Note that actually you cannot
iva2k 0:e614f7875b60 192 * modify the IP headers (this is inconsistent with the receive callback where
iva2k 0:e614f7875b60 193 * you actually get the IP headers), you can only specify the IP payload here.
iva2k 0:e614f7875b60 194 * It requires some more changes in lwIP. (there will be a raw_send() function
iva2k 0:e614f7875b60 195 * then.)
iva2k 0:e614f7875b60 196 *
iva2k 0:e614f7875b60 197 * @param pcb the raw pcb which to send
iva2k 0:e614f7875b60 198 * @param p the IP payload to send
iva2k 0:e614f7875b60 199 * @param ipaddr the destination address of the IP packet
iva2k 0:e614f7875b60 200 *
iva2k 0:e614f7875b60 201 */
iva2k 0:e614f7875b60 202 err_t
iva2k 0:e614f7875b60 203 raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
iva2k 0:e614f7875b60 204 {
iva2k 0:e614f7875b60 205 err_t err;
iva2k 0:e614f7875b60 206 struct netif *netif;
iva2k 0:e614f7875b60 207 ip_addr_t *src_ip;
iva2k 0:e614f7875b60 208 struct pbuf *q; /* q will be sent down the stack */
iva2k 0:e614f7875b60 209
iva2k 0:e614f7875b60 210 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
iva2k 0:e614f7875b60 211
iva2k 0:e614f7875b60 212 /* not enough space to add an IP header to first pbuf in given p chain? */
iva2k 0:e614f7875b60 213 if (pbuf_header(p, IP_HLEN)) {
iva2k 0:e614f7875b60 214 /* allocate header in new pbuf */
iva2k 0:e614f7875b60 215 q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
iva2k 0:e614f7875b60 216 /* new header pbuf could not be allocated? */
iva2k 0:e614f7875b60 217 if (q == NULL) {
iva2k 0:e614f7875b60 218 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
iva2k 0:e614f7875b60 219 return ERR_MEM;
iva2k 0:e614f7875b60 220 }
iva2k 0:e614f7875b60 221 /* chain header q in front of given pbuf p */
iva2k 0:e614f7875b60 222 pbuf_chain(q, p);
iva2k 0:e614f7875b60 223 /* { first pbuf q points to header pbuf } */
iva2k 0:e614f7875b60 224 LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
iva2k 0:e614f7875b60 225 } else {
iva2k 0:e614f7875b60 226 /* first pbuf q equals given pbuf */
iva2k 0:e614f7875b60 227 q = p;
iva2k 0:e614f7875b60 228 if(pbuf_header(q, -IP_HLEN)) {
iva2k 0:e614f7875b60 229 LWIP_ASSERT("Can't restore header we just removed!", 0);
iva2k 0:e614f7875b60 230 return ERR_MEM;
iva2k 0:e614f7875b60 231 }
iva2k 0:e614f7875b60 232 }
iva2k 0:e614f7875b60 233
iva2k 0:e614f7875b60 234 if ((netif = ip_route(ipaddr)) == NULL) {
iva2k 0:e614f7875b60 235 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
iva2k 0:e614f7875b60 236 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
iva2k 0:e614f7875b60 237 /* free any temporary header pbuf allocated by pbuf_header() */
iva2k 0:e614f7875b60 238 if (q != p) {
iva2k 0:e614f7875b60 239 pbuf_free(q);
iva2k 0:e614f7875b60 240 }
iva2k 0:e614f7875b60 241 return ERR_RTE;
iva2k 0:e614f7875b60 242 }
iva2k 0:e614f7875b60 243
iva2k 0:e614f7875b60 244 #if IP_SOF_BROADCAST
iva2k 0:e614f7875b60 245 /* broadcast filter? */
iva2k 0:e614f7875b60 246 if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
iva2k 0:e614f7875b60 247 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
iva2k 0:e614f7875b60 248 /* free any temporary header pbuf allocated by pbuf_header() */
iva2k 0:e614f7875b60 249 if (q != p) {
iva2k 0:e614f7875b60 250 pbuf_free(q);
iva2k 0:e614f7875b60 251 }
iva2k 0:e614f7875b60 252 return ERR_VAL;
iva2k 0:e614f7875b60 253 }
iva2k 0:e614f7875b60 254 #endif /* IP_SOF_BROADCAST */
iva2k 0:e614f7875b60 255
iva2k 0:e614f7875b60 256 if (ip_addr_isany(&pcb->local_ip)) {
iva2k 0:e614f7875b60 257 /* use outgoing network interface IP address as source address */
iva2k 0:e614f7875b60 258 src_ip = &(netif->ip_addr);
iva2k 0:e614f7875b60 259 } else {
iva2k 0:e614f7875b60 260 /* use RAW PCB local IP address as source address */
iva2k 0:e614f7875b60 261 src_ip = &(pcb->local_ip);
iva2k 0:e614f7875b60 262 }
iva2k 0:e614f7875b60 263
iva2k 0:e614f7875b60 264 #if LWIP_NETIF_HWADDRHINT
iva2k 0:e614f7875b60 265 netif->addr_hint = &(pcb->addr_hint);
iva2k 0:e614f7875b60 266 #endif /* LWIP_NETIF_HWADDRHINT*/
iva2k 0:e614f7875b60 267 err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
iva2k 0:e614f7875b60 268 #if LWIP_NETIF_HWADDRHINT
iva2k 0:e614f7875b60 269 netif->addr_hint = NULL;
iva2k 0:e614f7875b60 270 #endif /* LWIP_NETIF_HWADDRHINT*/
iva2k 0:e614f7875b60 271
iva2k 0:e614f7875b60 272 /* did we chain a header earlier? */
iva2k 0:e614f7875b60 273 if (q != p) {
iva2k 0:e614f7875b60 274 /* free the header */
iva2k 0:e614f7875b60 275 pbuf_free(q);
iva2k 0:e614f7875b60 276 }
iva2k 0:e614f7875b60 277 return err;
iva2k 0:e614f7875b60 278 }
iva2k 0:e614f7875b60 279
iva2k 0:e614f7875b60 280 /**
iva2k 0:e614f7875b60 281 * Send the raw IP packet to the address given by raw_connect()
iva2k 0:e614f7875b60 282 *
iva2k 0:e614f7875b60 283 * @param pcb the raw pcb which to send
iva2k 0:e614f7875b60 284 * @param p the IP payload to send
iva2k 0:e614f7875b60 285 *
iva2k 0:e614f7875b60 286 */
iva2k 0:e614f7875b60 287 err_t
iva2k 0:e614f7875b60 288 raw_send(struct raw_pcb *pcb, struct pbuf *p)
iva2k 0:e614f7875b60 289 {
iva2k 0:e614f7875b60 290 return raw_sendto(pcb, p, &pcb->remote_ip);
iva2k 0:e614f7875b60 291 }
iva2k 0:e614f7875b60 292
iva2k 0:e614f7875b60 293 /**
iva2k 0:e614f7875b60 294 * Remove an RAW PCB.
iva2k 0:e614f7875b60 295 *
iva2k 0:e614f7875b60 296 * @param pcb RAW PCB to be removed. The PCB is removed from the list of
iva2k 0:e614f7875b60 297 * RAW PCB's and the data structure is freed from memory.
iva2k 0:e614f7875b60 298 *
iva2k 0:e614f7875b60 299 * @see raw_new()
iva2k 0:e614f7875b60 300 */
iva2k 0:e614f7875b60 301 void
iva2k 0:e614f7875b60 302 raw_remove(struct raw_pcb *pcb)
iva2k 0:e614f7875b60 303 {
iva2k 0:e614f7875b60 304 struct raw_pcb *pcb2;
iva2k 0:e614f7875b60 305 /* pcb to be removed is first in list? */
iva2k 0:e614f7875b60 306 if (raw_pcbs == pcb) {
iva2k 0:e614f7875b60 307 /* make list start at 2nd pcb */
iva2k 0:e614f7875b60 308 raw_pcbs = raw_pcbs->next;
iva2k 0:e614f7875b60 309 /* pcb not 1st in list */
iva2k 0:e614f7875b60 310 } else {
iva2k 0:e614f7875b60 311 for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
iva2k 0:e614f7875b60 312 /* find pcb in raw_pcbs list */
iva2k 0:e614f7875b60 313 if (pcb2->next != NULL && pcb2->next == pcb) {
iva2k 0:e614f7875b60 314 /* remove pcb from list */
iva2k 0:e614f7875b60 315 pcb2->next = pcb->next;
iva2k 0:e614f7875b60 316 }
iva2k 0:e614f7875b60 317 }
iva2k 0:e614f7875b60 318 }
iva2k 0:e614f7875b60 319 memp_free(MEMP_RAW_PCB, pcb);
iva2k 0:e614f7875b60 320 }
iva2k 0:e614f7875b60 321
iva2k 0:e614f7875b60 322 /**
iva2k 0:e614f7875b60 323 * Create a RAW PCB.
iva2k 0:e614f7875b60 324 *
iva2k 0:e614f7875b60 325 * @return The RAW PCB which was created. NULL if the PCB data structure
iva2k 0:e614f7875b60 326 * could not be allocated.
iva2k 0:e614f7875b60 327 *
iva2k 0:e614f7875b60 328 * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
iva2k 0:e614f7875b60 329 *
iva2k 0:e614f7875b60 330 * @see raw_remove()
iva2k 0:e614f7875b60 331 */
iva2k 0:e614f7875b60 332 struct raw_pcb *
iva2k 0:e614f7875b60 333 raw_new(u8_t proto)
iva2k 0:e614f7875b60 334 {
iva2k 0:e614f7875b60 335 struct raw_pcb *pcb;
iva2k 0:e614f7875b60 336
iva2k 0:e614f7875b60 337 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
iva2k 0:e614f7875b60 338
iva2k 0:e614f7875b60 339 pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB);
iva2k 0:e614f7875b60 340 /* could allocate RAW PCB? */
iva2k 0:e614f7875b60 341 if (pcb != NULL) {
iva2k 0:e614f7875b60 342 /* initialize PCB to all zeroes */
iva2k 0:e614f7875b60 343 memset(pcb, 0, sizeof(struct raw_pcb));
iva2k 0:e614f7875b60 344 pcb->protocol = proto;
iva2k 0:e614f7875b60 345 pcb->ttl = RAW_TTL;
iva2k 0:e614f7875b60 346 pcb->next = raw_pcbs;
iva2k 0:e614f7875b60 347 raw_pcbs = pcb;
iva2k 0:e614f7875b60 348 }
iva2k 0:e614f7875b60 349 return pcb;
iva2k 0:e614f7875b60 350 }
iva2k 0:e614f7875b60 351
iva2k 0:e614f7875b60 352 #endif /* LWIP_RAW */