Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested

Dependents:   STM32F746_iothub_client_sample_mqtt DISCO-F746NG_Ethernet Nucleo_F746ZG_Ethernet thethingsiO-DISCO_F746NG-mqtt ... more

Committer:
DieterGraef
Date:
Thu Jun 23 09:04:23 2016 +0000
Revision:
1:28ba13dd96f7
Parent:
0:d26c1b55cfca
corrected MAC issue. The MAC is now 02:00:00:xx:xx:xx where xx is the sum over the unique device register

Who changed what in which revision?

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