Contains example code to connect the mbed LPC1768 or FRDM-K64F devices to the IBM Internet of Things Cloud service via ethernet.

Dependencies:   C12832 MQTT LM75B MMA7660

Dependents:   MFT_IoT_demo_USB400 IBM_RFID

Committer:
samdanbury
Date:
Wed Aug 20 12:45:14 2014 +0000
Revision:
6:37b6d0d56190
Code completely changed to improve the structure, flow and memory usage of the application

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samdanbury 6:37b6d0d56190 1 /**
samdanbury 6:37b6d0d56190 2 * @file
samdanbury 6:37b6d0d56190 3 * Sequential API External module
samdanbury 6:37b6d0d56190 4 *
samdanbury 6:37b6d0d56190 5 */
samdanbury 6:37b6d0d56190 6
samdanbury 6:37b6d0d56190 7 /*
samdanbury 6:37b6d0d56190 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
samdanbury 6:37b6d0d56190 9 * All rights reserved.
samdanbury 6:37b6d0d56190 10 *
samdanbury 6:37b6d0d56190 11 * Redistribution and use in source and binary forms, with or without modification,
samdanbury 6:37b6d0d56190 12 * are permitted provided that the following conditions are met:
samdanbury 6:37b6d0d56190 13 *
samdanbury 6:37b6d0d56190 14 * 1. Redistributions of source code must retain the above copyright notice,
samdanbury 6:37b6d0d56190 15 * this list of conditions and the following disclaimer.
samdanbury 6:37b6d0d56190 16 * 2. Redistributions in binary form must reproduce the above copyright notice,
samdanbury 6:37b6d0d56190 17 * this list of conditions and the following disclaimer in the documentation
samdanbury 6:37b6d0d56190 18 * and/or other materials provided with the distribution.
samdanbury 6:37b6d0d56190 19 * 3. The name of the author may not be used to endorse or promote products
samdanbury 6:37b6d0d56190 20 * derived from this software without specific prior written permission.
samdanbury 6:37b6d0d56190 21 *
samdanbury 6:37b6d0d56190 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
samdanbury 6:37b6d0d56190 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
samdanbury 6:37b6d0d56190 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
samdanbury 6:37b6d0d56190 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
samdanbury 6:37b6d0d56190 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
samdanbury 6:37b6d0d56190 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
samdanbury 6:37b6d0d56190 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
samdanbury 6:37b6d0d56190 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
samdanbury 6:37b6d0d56190 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
samdanbury 6:37b6d0d56190 31 * OF SUCH DAMAGE.
samdanbury 6:37b6d0d56190 32 *
samdanbury 6:37b6d0d56190 33 * This file is part of the lwIP TCP/IP stack.
samdanbury 6:37b6d0d56190 34 *
samdanbury 6:37b6d0d56190 35 * Author: Adam Dunkels <adam@sics.se>
samdanbury 6:37b6d0d56190 36 *
samdanbury 6:37b6d0d56190 37 */
samdanbury 6:37b6d0d56190 38
samdanbury 6:37b6d0d56190 39 /* This is the part of the API that is linked with
samdanbury 6:37b6d0d56190 40 the application */
samdanbury 6:37b6d0d56190 41
samdanbury 6:37b6d0d56190 42 #include "lwip/opt.h"
samdanbury 6:37b6d0d56190 43
samdanbury 6:37b6d0d56190 44 #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
samdanbury 6:37b6d0d56190 45
samdanbury 6:37b6d0d56190 46 #include "lwip/api.h"
samdanbury 6:37b6d0d56190 47 #include "lwip/tcpip.h"
samdanbury 6:37b6d0d56190 48 #include "lwip/memp.h"
samdanbury 6:37b6d0d56190 49
samdanbury 6:37b6d0d56190 50 #include "lwip/ip.h"
samdanbury 6:37b6d0d56190 51 #include "lwip/raw.h"
samdanbury 6:37b6d0d56190 52 #include "lwip/udp.h"
samdanbury 6:37b6d0d56190 53 #include "lwip/tcp.h"
samdanbury 6:37b6d0d56190 54
samdanbury 6:37b6d0d56190 55 #include <string.h>
samdanbury 6:37b6d0d56190 56
samdanbury 6:37b6d0d56190 57 /**
samdanbury 6:37b6d0d56190 58 * Create a new netconn (of a specific type) that has a callback function.
samdanbury 6:37b6d0d56190 59 * The corresponding pcb is also created.
samdanbury 6:37b6d0d56190 60 *
samdanbury 6:37b6d0d56190 61 * @param t the type of 'connection' to create (@see enum netconn_type)
samdanbury 6:37b6d0d56190 62 * @param proto the IP protocol for RAW IP pcbs
samdanbury 6:37b6d0d56190 63 * @param callback a function to call on status changes (RX available, TX'ed)
samdanbury 6:37b6d0d56190 64 * @return a newly allocated struct netconn or
samdanbury 6:37b6d0d56190 65 * NULL on memory error
samdanbury 6:37b6d0d56190 66 */
samdanbury 6:37b6d0d56190 67 struct netconn*
samdanbury 6:37b6d0d56190 68 netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
samdanbury 6:37b6d0d56190 69 {
samdanbury 6:37b6d0d56190 70 struct netconn *conn;
samdanbury 6:37b6d0d56190 71 struct api_msg msg;
samdanbury 6:37b6d0d56190 72
samdanbury 6:37b6d0d56190 73 conn = netconn_alloc(t, callback);
samdanbury 6:37b6d0d56190 74 if (conn != NULL) {
samdanbury 6:37b6d0d56190 75 msg.function = do_newconn;
samdanbury 6:37b6d0d56190 76 msg.msg.msg.n.proto = proto;
samdanbury 6:37b6d0d56190 77 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 78 if (TCPIP_APIMSG(&msg) != ERR_OK) {
samdanbury 6:37b6d0d56190 79 LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
samdanbury 6:37b6d0d56190 80 LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
samdanbury 6:37b6d0d56190 81 LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
samdanbury 6:37b6d0d56190 82 #if LWIP_TCP
samdanbury 6:37b6d0d56190 83 LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
samdanbury 6:37b6d0d56190 84 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 85 sys_sem_free(&conn->op_completed);
samdanbury 6:37b6d0d56190 86 sys_mbox_free(&conn->recvmbox);
samdanbury 6:37b6d0d56190 87 memp_free(MEMP_NETCONN, conn);
samdanbury 6:37b6d0d56190 88 return NULL;
samdanbury 6:37b6d0d56190 89 }
samdanbury 6:37b6d0d56190 90 }
samdanbury 6:37b6d0d56190 91 return conn;
samdanbury 6:37b6d0d56190 92 }
samdanbury 6:37b6d0d56190 93
samdanbury 6:37b6d0d56190 94 /**
samdanbury 6:37b6d0d56190 95 * Close a netconn 'connection' and free its resources.
samdanbury 6:37b6d0d56190 96 * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
samdanbury 6:37b6d0d56190 97 * after this returns.
samdanbury 6:37b6d0d56190 98 *
samdanbury 6:37b6d0d56190 99 * @param conn the netconn to delete
samdanbury 6:37b6d0d56190 100 * @return ERR_OK if the connection was deleted
samdanbury 6:37b6d0d56190 101 */
samdanbury 6:37b6d0d56190 102 err_t
samdanbury 6:37b6d0d56190 103 netconn_delete(struct netconn *conn)
samdanbury 6:37b6d0d56190 104 {
samdanbury 6:37b6d0d56190 105 struct api_msg msg;
samdanbury 6:37b6d0d56190 106
samdanbury 6:37b6d0d56190 107 /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
samdanbury 6:37b6d0d56190 108 if (conn == NULL) {
samdanbury 6:37b6d0d56190 109 return ERR_OK;
samdanbury 6:37b6d0d56190 110 }
samdanbury 6:37b6d0d56190 111
samdanbury 6:37b6d0d56190 112 msg.function = do_delconn;
samdanbury 6:37b6d0d56190 113 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 114 tcpip_apimsg(&msg);
samdanbury 6:37b6d0d56190 115
samdanbury 6:37b6d0d56190 116 netconn_free(conn);
samdanbury 6:37b6d0d56190 117
samdanbury 6:37b6d0d56190 118 /* don't care for return value of do_delconn since it only calls void functions */
samdanbury 6:37b6d0d56190 119
samdanbury 6:37b6d0d56190 120 return ERR_OK;
samdanbury 6:37b6d0d56190 121 }
samdanbury 6:37b6d0d56190 122
samdanbury 6:37b6d0d56190 123 /**
samdanbury 6:37b6d0d56190 124 * Get the local or remote IP address and port of a netconn.
samdanbury 6:37b6d0d56190 125 * For RAW netconns, this returns the protocol instead of a port!
samdanbury 6:37b6d0d56190 126 *
samdanbury 6:37b6d0d56190 127 * @param conn the netconn to query
samdanbury 6:37b6d0d56190 128 * @param addr a pointer to which to save the IP address
samdanbury 6:37b6d0d56190 129 * @param port a pointer to which to save the port (or protocol for RAW)
samdanbury 6:37b6d0d56190 130 * @param local 1 to get the local IP address, 0 to get the remote one
samdanbury 6:37b6d0d56190 131 * @return ERR_CONN for invalid connections
samdanbury 6:37b6d0d56190 132 * ERR_OK if the information was retrieved
samdanbury 6:37b6d0d56190 133 */
samdanbury 6:37b6d0d56190 134 err_t
samdanbury 6:37b6d0d56190 135 netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
samdanbury 6:37b6d0d56190 136 {
samdanbury 6:37b6d0d56190 137 struct api_msg msg;
samdanbury 6:37b6d0d56190 138 err_t err;
samdanbury 6:37b6d0d56190 139
samdanbury 6:37b6d0d56190 140 LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 141 LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 142 LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 143
samdanbury 6:37b6d0d56190 144 msg.function = do_getaddr;
samdanbury 6:37b6d0d56190 145 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 146 msg.msg.msg.ad.ipaddr = addr;
samdanbury 6:37b6d0d56190 147 msg.msg.msg.ad.port = port;
samdanbury 6:37b6d0d56190 148 msg.msg.msg.ad.local = local;
samdanbury 6:37b6d0d56190 149 err = TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 150
samdanbury 6:37b6d0d56190 151 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 152 return err;
samdanbury 6:37b6d0d56190 153 }
samdanbury 6:37b6d0d56190 154
samdanbury 6:37b6d0d56190 155 /**
samdanbury 6:37b6d0d56190 156 * Bind a netconn to a specific local IP address and port.
samdanbury 6:37b6d0d56190 157 * Binding one netconn twice might not always be checked correctly!
samdanbury 6:37b6d0d56190 158 *
samdanbury 6:37b6d0d56190 159 * @param conn the netconn to bind
samdanbury 6:37b6d0d56190 160 * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY
samdanbury 6:37b6d0d56190 161 * to bind to all addresses)
samdanbury 6:37b6d0d56190 162 * @param port the local port to bind the netconn to (not used for RAW)
samdanbury 6:37b6d0d56190 163 * @return ERR_OK if bound, any other err_t on failure
samdanbury 6:37b6d0d56190 164 */
samdanbury 6:37b6d0d56190 165 err_t
samdanbury 6:37b6d0d56190 166 netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
samdanbury 6:37b6d0d56190 167 {
samdanbury 6:37b6d0d56190 168 struct api_msg msg;
samdanbury 6:37b6d0d56190 169 err_t err;
samdanbury 6:37b6d0d56190 170
samdanbury 6:37b6d0d56190 171 LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 172
samdanbury 6:37b6d0d56190 173 msg.function = do_bind;
samdanbury 6:37b6d0d56190 174 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 175 msg.msg.msg.bc.ipaddr = addr;
samdanbury 6:37b6d0d56190 176 msg.msg.msg.bc.port = port;
samdanbury 6:37b6d0d56190 177 err = TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 178
samdanbury 6:37b6d0d56190 179 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 180 return err;
samdanbury 6:37b6d0d56190 181 }
samdanbury 6:37b6d0d56190 182
samdanbury 6:37b6d0d56190 183 /**
samdanbury 6:37b6d0d56190 184 * Connect a netconn to a specific remote IP address and port.
samdanbury 6:37b6d0d56190 185 *
samdanbury 6:37b6d0d56190 186 * @param conn the netconn to connect
samdanbury 6:37b6d0d56190 187 * @param addr the remote IP address to connect to
samdanbury 6:37b6d0d56190 188 * @param port the remote port to connect to (no used for RAW)
samdanbury 6:37b6d0d56190 189 * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
samdanbury 6:37b6d0d56190 190 */
samdanbury 6:37b6d0d56190 191 err_t
samdanbury 6:37b6d0d56190 192 netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
samdanbury 6:37b6d0d56190 193 {
samdanbury 6:37b6d0d56190 194 struct api_msg msg;
samdanbury 6:37b6d0d56190 195 err_t err;
samdanbury 6:37b6d0d56190 196
samdanbury 6:37b6d0d56190 197 LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 198
samdanbury 6:37b6d0d56190 199 msg.function = do_connect;
samdanbury 6:37b6d0d56190 200 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 201 msg.msg.msg.bc.ipaddr = addr;
samdanbury 6:37b6d0d56190 202 msg.msg.msg.bc.port = port;
samdanbury 6:37b6d0d56190 203 /* This is the only function which need to not block tcpip_thread */
samdanbury 6:37b6d0d56190 204 err = tcpip_apimsg(&msg);
samdanbury 6:37b6d0d56190 205
samdanbury 6:37b6d0d56190 206 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 207 return err;
samdanbury 6:37b6d0d56190 208 }
samdanbury 6:37b6d0d56190 209
samdanbury 6:37b6d0d56190 210 /**
samdanbury 6:37b6d0d56190 211 * Disconnect a netconn from its current peer (only valid for UDP netconns).
samdanbury 6:37b6d0d56190 212 *
samdanbury 6:37b6d0d56190 213 * @param conn the netconn to disconnect
samdanbury 6:37b6d0d56190 214 * @return TODO: return value is not set here...
samdanbury 6:37b6d0d56190 215 */
samdanbury 6:37b6d0d56190 216 err_t
samdanbury 6:37b6d0d56190 217 netconn_disconnect(struct netconn *conn)
samdanbury 6:37b6d0d56190 218 {
samdanbury 6:37b6d0d56190 219 struct api_msg msg;
samdanbury 6:37b6d0d56190 220 err_t err;
samdanbury 6:37b6d0d56190 221
samdanbury 6:37b6d0d56190 222 LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 223
samdanbury 6:37b6d0d56190 224 msg.function = do_disconnect;
samdanbury 6:37b6d0d56190 225 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 226 err = TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 227
samdanbury 6:37b6d0d56190 228 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 229 return err;
samdanbury 6:37b6d0d56190 230 }
samdanbury 6:37b6d0d56190 231
samdanbury 6:37b6d0d56190 232 /**
samdanbury 6:37b6d0d56190 233 * Set a TCP netconn into listen mode
samdanbury 6:37b6d0d56190 234 *
samdanbury 6:37b6d0d56190 235 * @param conn the tcp netconn to set to listen mode
samdanbury 6:37b6d0d56190 236 * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1
samdanbury 6:37b6d0d56190 237 * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns
samdanbury 6:37b6d0d56190 238 * don't return any error (yet?))
samdanbury 6:37b6d0d56190 239 */
samdanbury 6:37b6d0d56190 240 err_t
samdanbury 6:37b6d0d56190 241 netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
samdanbury 6:37b6d0d56190 242 {
samdanbury 6:37b6d0d56190 243 #if LWIP_TCP
samdanbury 6:37b6d0d56190 244 struct api_msg msg;
samdanbury 6:37b6d0d56190 245 err_t err;
samdanbury 6:37b6d0d56190 246
samdanbury 6:37b6d0d56190 247 /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
samdanbury 6:37b6d0d56190 248 LWIP_UNUSED_ARG(backlog);
samdanbury 6:37b6d0d56190 249
samdanbury 6:37b6d0d56190 250 LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 251
samdanbury 6:37b6d0d56190 252 msg.function = do_listen;
samdanbury 6:37b6d0d56190 253 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 254 #if TCP_LISTEN_BACKLOG
samdanbury 6:37b6d0d56190 255 msg.msg.msg.lb.backlog = backlog;
samdanbury 6:37b6d0d56190 256 #endif /* TCP_LISTEN_BACKLOG */
samdanbury 6:37b6d0d56190 257 err = TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 258
samdanbury 6:37b6d0d56190 259 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 260 return err;
samdanbury 6:37b6d0d56190 261 #else /* LWIP_TCP */
samdanbury 6:37b6d0d56190 262 LWIP_UNUSED_ARG(conn);
samdanbury 6:37b6d0d56190 263 LWIP_UNUSED_ARG(backlog);
samdanbury 6:37b6d0d56190 264 return ERR_ARG;
samdanbury 6:37b6d0d56190 265 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 266 }
samdanbury 6:37b6d0d56190 267
samdanbury 6:37b6d0d56190 268 /**
samdanbury 6:37b6d0d56190 269 * Accept a new connection on a TCP listening netconn.
samdanbury 6:37b6d0d56190 270 *
samdanbury 6:37b6d0d56190 271 * @param conn the TCP listen netconn
samdanbury 6:37b6d0d56190 272 * @param new_conn pointer where the new connection is stored
samdanbury 6:37b6d0d56190 273 * @return ERR_OK if a new connection has been received or an error
samdanbury 6:37b6d0d56190 274 * code otherwise
samdanbury 6:37b6d0d56190 275 */
samdanbury 6:37b6d0d56190 276 err_t
samdanbury 6:37b6d0d56190 277 netconn_accept(struct netconn *conn, struct netconn **new_conn)
samdanbury 6:37b6d0d56190 278 {
samdanbury 6:37b6d0d56190 279 #if LWIP_TCP
samdanbury 6:37b6d0d56190 280 struct netconn *newconn;
samdanbury 6:37b6d0d56190 281 err_t err;
samdanbury 6:37b6d0d56190 282 #if TCP_LISTEN_BACKLOG
samdanbury 6:37b6d0d56190 283 struct api_msg msg;
samdanbury 6:37b6d0d56190 284 #endif /* TCP_LISTEN_BACKLOG */
samdanbury 6:37b6d0d56190 285
samdanbury 6:37b6d0d56190 286 LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 287 *new_conn = NULL;
samdanbury 6:37b6d0d56190 288 LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 289 LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;);
samdanbury 6:37b6d0d56190 290
samdanbury 6:37b6d0d56190 291 err = conn->last_err;
samdanbury 6:37b6d0d56190 292 if (ERR_IS_FATAL(err)) {
samdanbury 6:37b6d0d56190 293 /* don't recv on fatal errors: this might block the application task
samdanbury 6:37b6d0d56190 294 waiting on acceptmbox forever! */
samdanbury 6:37b6d0d56190 295 return err;
samdanbury 6:37b6d0d56190 296 }
samdanbury 6:37b6d0d56190 297
samdanbury 6:37b6d0d56190 298 #if LWIP_SO_RCVTIMEO
samdanbury 6:37b6d0d56190 299 if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
samdanbury 6:37b6d0d56190 300 NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
samdanbury 6:37b6d0d56190 301 return ERR_TIMEOUT;
samdanbury 6:37b6d0d56190 302 }
samdanbury 6:37b6d0d56190 303 #else
samdanbury 6:37b6d0d56190 304 sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
samdanbury 6:37b6d0d56190 305 #endif /* LWIP_SO_RCVTIMEO*/
samdanbury 6:37b6d0d56190 306 /* Register event with callback */
samdanbury 6:37b6d0d56190 307 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
samdanbury 6:37b6d0d56190 308
samdanbury 6:37b6d0d56190 309 if (newconn == NULL) {
samdanbury 6:37b6d0d56190 310 /* connection has been aborted */
samdanbury 6:37b6d0d56190 311 NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
samdanbury 6:37b6d0d56190 312 return ERR_ABRT;
samdanbury 6:37b6d0d56190 313 }
samdanbury 6:37b6d0d56190 314 #if TCP_LISTEN_BACKLOG
samdanbury 6:37b6d0d56190 315 /* Let the stack know that we have accepted the connection. */
samdanbury 6:37b6d0d56190 316 msg.function = do_recv;
samdanbury 6:37b6d0d56190 317 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 318 /* don't care for the return value of do_recv */
samdanbury 6:37b6d0d56190 319 TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 320 #endif /* TCP_LISTEN_BACKLOG */
samdanbury 6:37b6d0d56190 321
samdanbury 6:37b6d0d56190 322 *new_conn = newconn;
samdanbury 6:37b6d0d56190 323 /* don't set conn->last_err: it's only ERR_OK, anyway */
samdanbury 6:37b6d0d56190 324 return ERR_OK;
samdanbury 6:37b6d0d56190 325 #else /* LWIP_TCP */
samdanbury 6:37b6d0d56190 326 LWIP_UNUSED_ARG(conn);
samdanbury 6:37b6d0d56190 327 LWIP_UNUSED_ARG(new_conn);
samdanbury 6:37b6d0d56190 328 return ERR_ARG;
samdanbury 6:37b6d0d56190 329 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 330 }
samdanbury 6:37b6d0d56190 331
samdanbury 6:37b6d0d56190 332 /**
samdanbury 6:37b6d0d56190 333 * Receive data: actual implementation that doesn't care whether pbuf or netbuf
samdanbury 6:37b6d0d56190 334 * is received
samdanbury 6:37b6d0d56190 335 *
samdanbury 6:37b6d0d56190 336 * @param conn the netconn from which to receive data
samdanbury 6:37b6d0d56190 337 * @param new_buf pointer where a new pbuf/netbuf is stored when received data
samdanbury 6:37b6d0d56190 338 * @return ERR_OK if data has been received, an error code otherwise (timeout,
samdanbury 6:37b6d0d56190 339 * memory error or another error)
samdanbury 6:37b6d0d56190 340 */
samdanbury 6:37b6d0d56190 341 static err_t
samdanbury 6:37b6d0d56190 342 netconn_recv_data(struct netconn *conn, void **new_buf)
samdanbury 6:37b6d0d56190 343 {
samdanbury 6:37b6d0d56190 344 void *buf = NULL;
samdanbury 6:37b6d0d56190 345 u16_t len;
samdanbury 6:37b6d0d56190 346 err_t err;
samdanbury 6:37b6d0d56190 347 #if LWIP_TCP
samdanbury 6:37b6d0d56190 348 struct api_msg msg;
samdanbury 6:37b6d0d56190 349 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 350
samdanbury 6:37b6d0d56190 351 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 352 *new_buf = NULL;
samdanbury 6:37b6d0d56190 353 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 354 LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
samdanbury 6:37b6d0d56190 355
samdanbury 6:37b6d0d56190 356 err = conn->last_err;
samdanbury 6:37b6d0d56190 357 if (ERR_IS_FATAL(err)) {
samdanbury 6:37b6d0d56190 358 /* don't recv on fatal errors: this might block the application task
samdanbury 6:37b6d0d56190 359 waiting on recvmbox forever! */
samdanbury 6:37b6d0d56190 360 /* @todo: this does not allow us to fetch data that has been put into recvmbox
samdanbury 6:37b6d0d56190 361 before the fatal error occurred - is that a problem? */
samdanbury 6:37b6d0d56190 362 return err;
samdanbury 6:37b6d0d56190 363 }
samdanbury 6:37b6d0d56190 364
samdanbury 6:37b6d0d56190 365 #if LWIP_SO_RCVTIMEO
samdanbury 6:37b6d0d56190 366 if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
samdanbury 6:37b6d0d56190 367 NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
samdanbury 6:37b6d0d56190 368 return ERR_TIMEOUT;
samdanbury 6:37b6d0d56190 369 }
samdanbury 6:37b6d0d56190 370 #else
samdanbury 6:37b6d0d56190 371 sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
samdanbury 6:37b6d0d56190 372 #endif /* LWIP_SO_RCVTIMEO*/
samdanbury 6:37b6d0d56190 373
samdanbury 6:37b6d0d56190 374 #if LWIP_TCP
samdanbury 6:37b6d0d56190 375 if (conn->type == NETCONN_TCP) {
samdanbury 6:37b6d0d56190 376 if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
samdanbury 6:37b6d0d56190 377 /* Let the stack know that we have taken the data. */
samdanbury 6:37b6d0d56190 378 /* TODO: Speedup: Don't block and wait for the answer here
samdanbury 6:37b6d0d56190 379 (to prevent multiple thread-switches). */
samdanbury 6:37b6d0d56190 380 msg.function = do_recv;
samdanbury 6:37b6d0d56190 381 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 382 if (buf != NULL) {
samdanbury 6:37b6d0d56190 383 msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
samdanbury 6:37b6d0d56190 384 } else {
samdanbury 6:37b6d0d56190 385 msg.msg.msg.r.len = 1;
samdanbury 6:37b6d0d56190 386 }
samdanbury 6:37b6d0d56190 387 /* don't care for the return value of do_recv */
samdanbury 6:37b6d0d56190 388 TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 389 }
samdanbury 6:37b6d0d56190 390
samdanbury 6:37b6d0d56190 391 /* If we are closed, we indicate that we no longer wish to use the socket */
samdanbury 6:37b6d0d56190 392 if (buf == NULL) {
samdanbury 6:37b6d0d56190 393 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
samdanbury 6:37b6d0d56190 394 /* Avoid to lose any previous error code */
samdanbury 6:37b6d0d56190 395 NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
samdanbury 6:37b6d0d56190 396 return ERR_CLSD;
samdanbury 6:37b6d0d56190 397 }
samdanbury 6:37b6d0d56190 398 len = ((struct pbuf *)buf)->tot_len;
samdanbury 6:37b6d0d56190 399 }
samdanbury 6:37b6d0d56190 400 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 401 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
samdanbury 6:37b6d0d56190 402 else
samdanbury 6:37b6d0d56190 403 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
samdanbury 6:37b6d0d56190 404 #if (LWIP_UDP || LWIP_RAW)
samdanbury 6:37b6d0d56190 405 {
samdanbury 6:37b6d0d56190 406 LWIP_ASSERT("buf != NULL", buf != NULL);
samdanbury 6:37b6d0d56190 407 len = netbuf_len((struct netbuf *)buf);
samdanbury 6:37b6d0d56190 408 }
samdanbury 6:37b6d0d56190 409 #endif /* (LWIP_UDP || LWIP_RAW) */
samdanbury 6:37b6d0d56190 410
samdanbury 6:37b6d0d56190 411 #if LWIP_SO_RCVBUF
samdanbury 6:37b6d0d56190 412 SYS_ARCH_DEC(conn->recv_avail, len);
samdanbury 6:37b6d0d56190 413 #endif /* LWIP_SO_RCVBUF */
samdanbury 6:37b6d0d56190 414 /* Register event with callback */
samdanbury 6:37b6d0d56190 415 API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
samdanbury 6:37b6d0d56190 416
samdanbury 6:37b6d0d56190 417 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
samdanbury 6:37b6d0d56190 418
samdanbury 6:37b6d0d56190 419 *new_buf = buf;
samdanbury 6:37b6d0d56190 420 /* don't set conn->last_err: it's only ERR_OK, anyway */
samdanbury 6:37b6d0d56190 421 return ERR_OK;
samdanbury 6:37b6d0d56190 422 }
samdanbury 6:37b6d0d56190 423
samdanbury 6:37b6d0d56190 424 /**
samdanbury 6:37b6d0d56190 425 * Receive data (in form of a pbuf) from a TCP netconn
samdanbury 6:37b6d0d56190 426 *
samdanbury 6:37b6d0d56190 427 * @param conn the netconn from which to receive data
samdanbury 6:37b6d0d56190 428 * @param new_buf pointer where a new pbuf is stored when received data
samdanbury 6:37b6d0d56190 429 * @return ERR_OK if data has been received, an error code otherwise (timeout,
samdanbury 6:37b6d0d56190 430 * memory error or another error)
samdanbury 6:37b6d0d56190 431 * ERR_ARG if conn is not a TCP netconn
samdanbury 6:37b6d0d56190 432 */
samdanbury 6:37b6d0d56190 433 err_t
samdanbury 6:37b6d0d56190 434 netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
samdanbury 6:37b6d0d56190 435 {
samdanbury 6:37b6d0d56190 436 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
samdanbury 6:37b6d0d56190 437 netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
samdanbury 6:37b6d0d56190 438
samdanbury 6:37b6d0d56190 439 return netconn_recv_data(conn, (void **)new_buf);
samdanbury 6:37b6d0d56190 440 }
samdanbury 6:37b6d0d56190 441
samdanbury 6:37b6d0d56190 442 /**
samdanbury 6:37b6d0d56190 443 * Receive data (in form of a netbuf containing a packet buffer) from a netconn
samdanbury 6:37b6d0d56190 444 *
samdanbury 6:37b6d0d56190 445 * @param conn the netconn from which to receive data
samdanbury 6:37b6d0d56190 446 * @param new_buf pointer where a new netbuf is stored when received data
samdanbury 6:37b6d0d56190 447 * @return ERR_OK if data has been received, an error code otherwise (timeout,
samdanbury 6:37b6d0d56190 448 * memory error or another error)
samdanbury 6:37b6d0d56190 449 */
samdanbury 6:37b6d0d56190 450 err_t
samdanbury 6:37b6d0d56190 451 netconn_recv(struct netconn *conn, struct netbuf **new_buf)
samdanbury 6:37b6d0d56190 452 {
samdanbury 6:37b6d0d56190 453 #if LWIP_TCP
samdanbury 6:37b6d0d56190 454 struct netbuf *buf = NULL;
samdanbury 6:37b6d0d56190 455 err_t err;
samdanbury 6:37b6d0d56190 456 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 457
samdanbury 6:37b6d0d56190 458 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 459 *new_buf = NULL;
samdanbury 6:37b6d0d56190 460 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 461 LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
samdanbury 6:37b6d0d56190 462
samdanbury 6:37b6d0d56190 463 #if LWIP_TCP
samdanbury 6:37b6d0d56190 464 if (conn->type == NETCONN_TCP) {
samdanbury 6:37b6d0d56190 465 struct pbuf *p = NULL;
samdanbury 6:37b6d0d56190 466 /* This is not a listening netconn, since recvmbox is set */
samdanbury 6:37b6d0d56190 467
samdanbury 6:37b6d0d56190 468 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
samdanbury 6:37b6d0d56190 469 if (buf == NULL) {
samdanbury 6:37b6d0d56190 470 NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
samdanbury 6:37b6d0d56190 471 return ERR_MEM;
samdanbury 6:37b6d0d56190 472 }
samdanbury 6:37b6d0d56190 473
samdanbury 6:37b6d0d56190 474 err = netconn_recv_data(conn, (void **)&p);
samdanbury 6:37b6d0d56190 475 if (err != ERR_OK) {
samdanbury 6:37b6d0d56190 476 memp_free(MEMP_NETBUF, buf);
samdanbury 6:37b6d0d56190 477 return err;
samdanbury 6:37b6d0d56190 478 }
samdanbury 6:37b6d0d56190 479 LWIP_ASSERT("p != NULL", p != NULL);
samdanbury 6:37b6d0d56190 480
samdanbury 6:37b6d0d56190 481 buf->p = p;
samdanbury 6:37b6d0d56190 482 buf->ptr = p;
samdanbury 6:37b6d0d56190 483 buf->port = 0;
samdanbury 6:37b6d0d56190 484 ip_addr_set_any(&buf->addr);
samdanbury 6:37b6d0d56190 485 *new_buf = buf;
samdanbury 6:37b6d0d56190 486 /* don't set conn->last_err: it's only ERR_OK, anyway */
samdanbury 6:37b6d0d56190 487 return ERR_OK;
samdanbury 6:37b6d0d56190 488 } else
samdanbury 6:37b6d0d56190 489 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 490 {
samdanbury 6:37b6d0d56190 491 #if (LWIP_UDP || LWIP_RAW)
samdanbury 6:37b6d0d56190 492 return netconn_recv_data(conn, (void **)new_buf);
samdanbury 6:37b6d0d56190 493 #endif /* (LWIP_UDP || LWIP_RAW) */
samdanbury 6:37b6d0d56190 494 }
samdanbury 6:37b6d0d56190 495 }
samdanbury 6:37b6d0d56190 496
samdanbury 6:37b6d0d56190 497 /**
samdanbury 6:37b6d0d56190 498 * TCP: update the receive window: by calling this, the application
samdanbury 6:37b6d0d56190 499 * tells the stack that it has processed data and is able to accept
samdanbury 6:37b6d0d56190 500 * new data.
samdanbury 6:37b6d0d56190 501 * ATTENTION: use with care, this is mainly used for sockets!
samdanbury 6:37b6d0d56190 502 * Can only be used when calling netconn_set_noautorecved(conn, 1) before.
samdanbury 6:37b6d0d56190 503 *
samdanbury 6:37b6d0d56190 504 * @param conn the netconn for which to update the receive window
samdanbury 6:37b6d0d56190 505 * @param length amount of data processed (ATTENTION: this must be accurate!)
samdanbury 6:37b6d0d56190 506 */
samdanbury 6:37b6d0d56190 507 void
samdanbury 6:37b6d0d56190 508 netconn_recved(struct netconn *conn, u32_t length)
samdanbury 6:37b6d0d56190 509 {
samdanbury 6:37b6d0d56190 510 #if LWIP_TCP
samdanbury 6:37b6d0d56190 511 if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
samdanbury 6:37b6d0d56190 512 (netconn_get_noautorecved(conn))) {
samdanbury 6:37b6d0d56190 513 struct api_msg msg;
samdanbury 6:37b6d0d56190 514 /* Let the stack know that we have taken the data. */
samdanbury 6:37b6d0d56190 515 /* TODO: Speedup: Don't block and wait for the answer here
samdanbury 6:37b6d0d56190 516 (to prevent multiple thread-switches). */
samdanbury 6:37b6d0d56190 517 msg.function = do_recv;
samdanbury 6:37b6d0d56190 518 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 519 msg.msg.msg.r.len = length;
samdanbury 6:37b6d0d56190 520 /* don't care for the return value of do_recv */
samdanbury 6:37b6d0d56190 521 TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 522 }
samdanbury 6:37b6d0d56190 523 #else /* LWIP_TCP */
samdanbury 6:37b6d0d56190 524 LWIP_UNUSED_ARG(conn);
samdanbury 6:37b6d0d56190 525 LWIP_UNUSED_ARG(length);
samdanbury 6:37b6d0d56190 526 #endif /* LWIP_TCP */
samdanbury 6:37b6d0d56190 527 }
samdanbury 6:37b6d0d56190 528
samdanbury 6:37b6d0d56190 529 /**
samdanbury 6:37b6d0d56190 530 * Send data (in form of a netbuf) to a specific remote IP address and port.
samdanbury 6:37b6d0d56190 531 * Only to be used for UDP and RAW netconns (not TCP).
samdanbury 6:37b6d0d56190 532 *
samdanbury 6:37b6d0d56190 533 * @param conn the netconn over which to send data
samdanbury 6:37b6d0d56190 534 * @param buf a netbuf containing the data to send
samdanbury 6:37b6d0d56190 535 * @param addr the remote IP address to which to send the data
samdanbury 6:37b6d0d56190 536 * @param port the remote port to which to send the data
samdanbury 6:37b6d0d56190 537 * @return ERR_OK if data was sent, any other err_t on error
samdanbury 6:37b6d0d56190 538 */
samdanbury 6:37b6d0d56190 539 err_t
samdanbury 6:37b6d0d56190 540 netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
samdanbury 6:37b6d0d56190 541 {
samdanbury 6:37b6d0d56190 542 if (buf != NULL) {
samdanbury 6:37b6d0d56190 543 ip_addr_set(&buf->addr, addr);
samdanbury 6:37b6d0d56190 544 buf->port = port;
samdanbury 6:37b6d0d56190 545 return netconn_send(conn, buf);
samdanbury 6:37b6d0d56190 546 }
samdanbury 6:37b6d0d56190 547 return ERR_VAL;
samdanbury 6:37b6d0d56190 548 }
samdanbury 6:37b6d0d56190 549
samdanbury 6:37b6d0d56190 550 /**
samdanbury 6:37b6d0d56190 551 * Send data over a UDP or RAW netconn (that is already connected).
samdanbury 6:37b6d0d56190 552 *
samdanbury 6:37b6d0d56190 553 * @param conn the UDP or RAW netconn over which to send data
samdanbury 6:37b6d0d56190 554 * @param buf a netbuf containing the data to send
samdanbury 6:37b6d0d56190 555 * @return ERR_OK if data was sent, any other err_t on error
samdanbury 6:37b6d0d56190 556 */
samdanbury 6:37b6d0d56190 557 err_t
samdanbury 6:37b6d0d56190 558 netconn_send(struct netconn *conn, struct netbuf *buf)
samdanbury 6:37b6d0d56190 559 {
samdanbury 6:37b6d0d56190 560 struct api_msg msg;
samdanbury 6:37b6d0d56190 561 err_t err;
samdanbury 6:37b6d0d56190 562
samdanbury 6:37b6d0d56190 563 LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 564
samdanbury 6:37b6d0d56190 565 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
samdanbury 6:37b6d0d56190 566 msg.function = do_send;
samdanbury 6:37b6d0d56190 567 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 568 msg.msg.msg.b = buf;
samdanbury 6:37b6d0d56190 569 err = TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 570
samdanbury 6:37b6d0d56190 571 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 572 return err;
samdanbury 6:37b6d0d56190 573 }
samdanbury 6:37b6d0d56190 574
samdanbury 6:37b6d0d56190 575 /**
samdanbury 6:37b6d0d56190 576 * Send data over a TCP netconn.
samdanbury 6:37b6d0d56190 577 *
samdanbury 6:37b6d0d56190 578 * @param conn the TCP netconn over which to send data
samdanbury 6:37b6d0d56190 579 * @param dataptr pointer to the application buffer that contains the data to send
samdanbury 6:37b6d0d56190 580 * @param size size of the application data to send
samdanbury 6:37b6d0d56190 581 * @param apiflags combination of following flags :
samdanbury 6:37b6d0d56190 582 * - NETCONN_COPY: data will be copied into memory belonging to the stack
samdanbury 6:37b6d0d56190 583 * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
samdanbury 6:37b6d0d56190 584 * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once
samdanbury 6:37b6d0d56190 585 * @return ERR_OK if data was sent, any other err_t on error
samdanbury 6:37b6d0d56190 586 */
samdanbury 6:37b6d0d56190 587 err_t
samdanbury 6:37b6d0d56190 588 netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags)
samdanbury 6:37b6d0d56190 589 {
samdanbury 6:37b6d0d56190 590 struct api_msg msg;
samdanbury 6:37b6d0d56190 591 err_t err;
samdanbury 6:37b6d0d56190 592
samdanbury 6:37b6d0d56190 593 LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 594 LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;);
samdanbury 6:37b6d0d56190 595 if (size == 0) {
samdanbury 6:37b6d0d56190 596 return ERR_OK;
samdanbury 6:37b6d0d56190 597 }
samdanbury 6:37b6d0d56190 598
samdanbury 6:37b6d0d56190 599 /* @todo: for non-blocking write, check if 'size' would ever fit into
samdanbury 6:37b6d0d56190 600 snd_queue or snd_buf */
samdanbury 6:37b6d0d56190 601 msg.function = do_write;
samdanbury 6:37b6d0d56190 602 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 603 msg.msg.msg.w.dataptr = dataptr;
samdanbury 6:37b6d0d56190 604 msg.msg.msg.w.apiflags = apiflags;
samdanbury 6:37b6d0d56190 605 msg.msg.msg.w.len = size;
samdanbury 6:37b6d0d56190 606 /* For locking the core: this _can_ be delayed on low memory/low send buffer,
samdanbury 6:37b6d0d56190 607 but if it is, this is done inside api_msg.c:do_write(), so we can use the
samdanbury 6:37b6d0d56190 608 non-blocking version here. */
samdanbury 6:37b6d0d56190 609 err = TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 610
samdanbury 6:37b6d0d56190 611 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 612 return err;
samdanbury 6:37b6d0d56190 613 }
samdanbury 6:37b6d0d56190 614
samdanbury 6:37b6d0d56190 615 /**
samdanbury 6:37b6d0d56190 616 * Close ot shutdown a TCP netconn (doesn't delete it).
samdanbury 6:37b6d0d56190 617 *
samdanbury 6:37b6d0d56190 618 * @param conn the TCP netconn to close or shutdown
samdanbury 6:37b6d0d56190 619 * @param how fully close or only shutdown one side?
samdanbury 6:37b6d0d56190 620 * @return ERR_OK if the netconn was closed, any other err_t on error
samdanbury 6:37b6d0d56190 621 */
samdanbury 6:37b6d0d56190 622 static err_t
samdanbury 6:37b6d0d56190 623 netconn_close_shutdown(struct netconn *conn, u8_t how)
samdanbury 6:37b6d0d56190 624 {
samdanbury 6:37b6d0d56190 625 struct api_msg msg;
samdanbury 6:37b6d0d56190 626 err_t err;
samdanbury 6:37b6d0d56190 627
samdanbury 6:37b6d0d56190 628 LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 629
samdanbury 6:37b6d0d56190 630 msg.function = do_close;
samdanbury 6:37b6d0d56190 631 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 632 /* shutting down both ends is the same as closing */
samdanbury 6:37b6d0d56190 633 msg.msg.msg.sd.shut = how;
samdanbury 6:37b6d0d56190 634 /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close,
samdanbury 6:37b6d0d56190 635 don't use TCPIP_APIMSG here */
samdanbury 6:37b6d0d56190 636 err = tcpip_apimsg(&msg);
samdanbury 6:37b6d0d56190 637
samdanbury 6:37b6d0d56190 638 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 639 return err;
samdanbury 6:37b6d0d56190 640 }
samdanbury 6:37b6d0d56190 641
samdanbury 6:37b6d0d56190 642 /**
samdanbury 6:37b6d0d56190 643 * Close a TCP netconn (doesn't delete it).
samdanbury 6:37b6d0d56190 644 *
samdanbury 6:37b6d0d56190 645 * @param conn the TCP netconn to close
samdanbury 6:37b6d0d56190 646 * @return ERR_OK if the netconn was closed, any other err_t on error
samdanbury 6:37b6d0d56190 647 */
samdanbury 6:37b6d0d56190 648 err_t
samdanbury 6:37b6d0d56190 649 netconn_close(struct netconn *conn)
samdanbury 6:37b6d0d56190 650 {
samdanbury 6:37b6d0d56190 651 /* shutting down both ends is the same as closing */
samdanbury 6:37b6d0d56190 652 return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
samdanbury 6:37b6d0d56190 653 }
samdanbury 6:37b6d0d56190 654
samdanbury 6:37b6d0d56190 655 /**
samdanbury 6:37b6d0d56190 656 * Shut down one or both sides of a TCP netconn (doesn't delete it).
samdanbury 6:37b6d0d56190 657 *
samdanbury 6:37b6d0d56190 658 * @param conn the TCP netconn to shut down
samdanbury 6:37b6d0d56190 659 * @return ERR_OK if the netconn was closed, any other err_t on error
samdanbury 6:37b6d0d56190 660 */
samdanbury 6:37b6d0d56190 661 err_t
samdanbury 6:37b6d0d56190 662 netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
samdanbury 6:37b6d0d56190 663 {
samdanbury 6:37b6d0d56190 664 return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
samdanbury 6:37b6d0d56190 665 }
samdanbury 6:37b6d0d56190 666
samdanbury 6:37b6d0d56190 667 #if LWIP_IGMP
samdanbury 6:37b6d0d56190 668 /**
samdanbury 6:37b6d0d56190 669 * Join multicast groups for UDP netconns.
samdanbury 6:37b6d0d56190 670 *
samdanbury 6:37b6d0d56190 671 * @param conn the UDP netconn for which to change multicast addresses
samdanbury 6:37b6d0d56190 672 * @param multiaddr IP address of the multicast group to join or leave
samdanbury 6:37b6d0d56190 673 * @param netif_addr the IP address of the network interface on which to send
samdanbury 6:37b6d0d56190 674 * the igmp message
samdanbury 6:37b6d0d56190 675 * @param join_or_leave flag whether to send a join- or leave-message
samdanbury 6:37b6d0d56190 676 * @return ERR_OK if the action was taken, any err_t on error
samdanbury 6:37b6d0d56190 677 */
samdanbury 6:37b6d0d56190 678 err_t
samdanbury 6:37b6d0d56190 679 netconn_join_leave_group(struct netconn *conn,
samdanbury 6:37b6d0d56190 680 ip_addr_t *multiaddr,
samdanbury 6:37b6d0d56190 681 ip_addr_t *netif_addr,
samdanbury 6:37b6d0d56190 682 enum netconn_igmp join_or_leave)
samdanbury 6:37b6d0d56190 683 {
samdanbury 6:37b6d0d56190 684 struct api_msg msg;
samdanbury 6:37b6d0d56190 685 err_t err;
samdanbury 6:37b6d0d56190 686
samdanbury 6:37b6d0d56190 687 LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 688
samdanbury 6:37b6d0d56190 689 msg.function = do_join_leave_group;
samdanbury 6:37b6d0d56190 690 msg.msg.conn = conn;
samdanbury 6:37b6d0d56190 691 msg.msg.msg.jl.multiaddr = multiaddr;
samdanbury 6:37b6d0d56190 692 msg.msg.msg.jl.netif_addr = netif_addr;
samdanbury 6:37b6d0d56190 693 msg.msg.msg.jl.join_or_leave = join_or_leave;
samdanbury 6:37b6d0d56190 694 err = TCPIP_APIMSG(&msg);
samdanbury 6:37b6d0d56190 695
samdanbury 6:37b6d0d56190 696 NETCONN_SET_SAFE_ERR(conn, err);
samdanbury 6:37b6d0d56190 697 return err;
samdanbury 6:37b6d0d56190 698 }
samdanbury 6:37b6d0d56190 699 #endif /* LWIP_IGMP */
samdanbury 6:37b6d0d56190 700
samdanbury 6:37b6d0d56190 701 #if LWIP_DNS
samdanbury 6:37b6d0d56190 702 /**
samdanbury 6:37b6d0d56190 703 * Execute a DNS query, only one IP address is returned
samdanbury 6:37b6d0d56190 704 *
samdanbury 6:37b6d0d56190 705 * @param name a string representation of the DNS host name to query
samdanbury 6:37b6d0d56190 706 * @param addr a preallocated ip_addr_t where to store the resolved IP address
samdanbury 6:37b6d0d56190 707 * @return ERR_OK: resolving succeeded
samdanbury 6:37b6d0d56190 708 * ERR_MEM: memory error, try again later
samdanbury 6:37b6d0d56190 709 * ERR_ARG: dns client not initialized or invalid hostname
samdanbury 6:37b6d0d56190 710 * ERR_VAL: dns server response was invalid
samdanbury 6:37b6d0d56190 711 */
samdanbury 6:37b6d0d56190 712 err_t
samdanbury 6:37b6d0d56190 713 netconn_gethostbyname(const char *name, ip_addr_t *addr)
samdanbury 6:37b6d0d56190 714 {
samdanbury 6:37b6d0d56190 715 struct dns_api_msg msg;
samdanbury 6:37b6d0d56190 716 err_t err;
samdanbury 6:37b6d0d56190 717 sys_sem_t sem;
samdanbury 6:37b6d0d56190 718
samdanbury 6:37b6d0d56190 719 LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 720 LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
samdanbury 6:37b6d0d56190 721
samdanbury 6:37b6d0d56190 722 err = sys_sem_new(&sem, 0);
samdanbury 6:37b6d0d56190 723 if (err != ERR_OK) {
samdanbury 6:37b6d0d56190 724 return err;
samdanbury 6:37b6d0d56190 725 }
samdanbury 6:37b6d0d56190 726
samdanbury 6:37b6d0d56190 727 msg.name = name;
samdanbury 6:37b6d0d56190 728 msg.addr = addr;
samdanbury 6:37b6d0d56190 729 msg.err = &err;
samdanbury 6:37b6d0d56190 730 msg.sem = &sem;
samdanbury 6:37b6d0d56190 731
samdanbury 6:37b6d0d56190 732 tcpip_callback(do_gethostbyname, &msg);
samdanbury 6:37b6d0d56190 733 sys_sem_wait(&sem);
samdanbury 6:37b6d0d56190 734 sys_sem_free(&sem);
samdanbury 6:37b6d0d56190 735
samdanbury 6:37b6d0d56190 736 return err;
samdanbury 6:37b6d0d56190 737 }
samdanbury 6:37b6d0d56190 738 #endif /* LWIP_DNS*/
samdanbury 6:37b6d0d56190 739
samdanbury 6:37b6d0d56190 740 #endif /* LWIP_NETCONN */