Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
api_lib.c
00001 /** 00002 * @file 00003 * Sequential API External module 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 /* This is the part of the API that is linked with 00040 the application */ 00041 00042 #include "lwip/opt.h" 00043 00044 #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ 00045 00046 #include "lwip/api.h" 00047 #include "lwip/tcpip.h" 00048 #include "lwip/memp.h" 00049 00050 #include "lwip/ip.h" 00051 #include "lwip/raw.h" 00052 #include "lwip/udp.h" 00053 #include "lwip/tcp.h" 00054 00055 #include <string.h> 00056 00057 /** 00058 * Create a new netconn (of a specific type) that has a callback function. 00059 * The corresponding pcb is also created. 00060 * 00061 * @param t the type of 'connection' to create (@see enum netconn_type) 00062 * @param proto the IP protocol for RAW IP pcbs 00063 * @param callback a function to call on status changes (RX available, TX'ed) 00064 * @return a newly allocated struct netconn or 00065 * NULL on memory error 00066 */ 00067 struct netconn* 00068 netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) 00069 { 00070 struct netconn *conn; 00071 struct api_msg msg; 00072 00073 conn = netconn_alloc(t, callback); 00074 if (conn != NULL) { 00075 msg.function = do_newconn; 00076 msg.msg.msg.n.proto = proto; 00077 msg.msg.conn = conn; 00078 if (TCPIP_APIMSG(&msg) != ERR_OK) { 00079 LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); 00080 LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); 00081 LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); 00082 #if LWIP_TCP 00083 LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); 00084 #endif /* LWIP_TCP */ 00085 sys_sem_free(&conn->op_completed); 00086 sys_mbox_free(&conn->recvmbox); 00087 memp_free(MEMP_NETCONN, conn); 00088 return NULL; 00089 } 00090 } 00091 return conn; 00092 } 00093 00094 /** 00095 * Close a netconn 'connection' and free its resources. 00096 * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate 00097 * after this returns. 00098 * 00099 * @param conn the netconn to delete 00100 * @return ERR_OK if the connection was deleted 00101 */ 00102 err_t 00103 netconn_delete(struct netconn *conn) 00104 { 00105 struct api_msg msg; 00106 00107 /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ 00108 if (conn == NULL) { 00109 return ERR_OK; 00110 } 00111 00112 msg.function = do_delconn; 00113 msg.msg.conn = conn; 00114 tcpip_apimsg(&msg); 00115 00116 netconn_free(conn); 00117 00118 /* don't care for return value of do_delconn since it only calls void functions */ 00119 00120 return ERR_OK; 00121 } 00122 00123 /** 00124 * Get the local or remote IP address and port of a netconn. 00125 * For RAW netconns, this returns the protocol instead of a port! 00126 * 00127 * @param conn the netconn to query 00128 * @param addr a pointer to which to save the IP address 00129 * @param port a pointer to which to save the port (or protocol for RAW) 00130 * @param local 1 to get the local IP address, 0 to get the remote one 00131 * @return ERR_CONN for invalid connections 00132 * ERR_OK if the information was retrieved 00133 */ 00134 err_t 00135 netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) 00136 { 00137 struct api_msg msg; 00138 err_t err; 00139 00140 LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); 00141 LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); 00142 LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); 00143 00144 msg.function = do_getaddr; 00145 msg.msg.conn = conn; 00146 msg.msg.msg.ad.ipaddr = addr; 00147 msg.msg.msg.ad.port = port; 00148 msg.msg.msg.ad.local = local; 00149 err = TCPIP_APIMSG(&msg); 00150 00151 NETCONN_SET_SAFE_ERR(conn, err); 00152 return err; 00153 } 00154 00155 /** 00156 * Bind a netconn to a specific local IP address and port. 00157 * Binding one netconn twice might not always be checked correctly! 00158 * 00159 * @param conn the netconn to bind 00160 * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY 00161 * to bind to all addresses) 00162 * @param port the local port to bind the netconn to (not used for RAW) 00163 * @return ERR_OK if bound, any other err_t on failure 00164 */ 00165 err_t 00166 netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port) 00167 { 00168 struct api_msg msg; 00169 err_t err; 00170 00171 LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); 00172 00173 msg.function = do_bind; 00174 msg.msg.conn = conn; 00175 msg.msg.msg.bc.ipaddr = addr; 00176 msg.msg.msg.bc.port = port; 00177 err = TCPIP_APIMSG(&msg); 00178 00179 NETCONN_SET_SAFE_ERR(conn, err); 00180 return err; 00181 } 00182 00183 /** 00184 * Connect a netconn to a specific remote IP address and port. 00185 * 00186 * @param conn the netconn to connect 00187 * @param addr the remote IP address to connect to 00188 * @param port the remote port to connect to (no used for RAW) 00189 * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise 00190 */ 00191 err_t 00192 netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) 00193 { 00194 struct api_msg msg; 00195 err_t err; 00196 00197 LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); 00198 00199 msg.function = do_connect; 00200 msg.msg.conn = conn; 00201 msg.msg.msg.bc.ipaddr = addr; 00202 msg.msg.msg.bc.port = port; 00203 /* This is the only function which need to not block tcpip_thread */ 00204 err = tcpip_apimsg(&msg); 00205 00206 NETCONN_SET_SAFE_ERR(conn, err); 00207 return err; 00208 } 00209 00210 /** 00211 * Disconnect a netconn from its current peer (only valid for UDP netconns). 00212 * 00213 * @param conn the netconn to disconnect 00214 * @return TODO: return value is not set here... 00215 */ 00216 err_t 00217 netconn_disconnect(struct netconn *conn) 00218 { 00219 struct api_msg msg; 00220 err_t err; 00221 00222 LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); 00223 00224 msg.function = do_disconnect; 00225 msg.msg.conn = conn; 00226 err = TCPIP_APIMSG(&msg); 00227 00228 NETCONN_SET_SAFE_ERR(conn, err); 00229 return err; 00230 } 00231 00232 /** 00233 * Set a TCP netconn into listen mode 00234 * 00235 * @param conn the tcp netconn to set to listen mode 00236 * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 00237 * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns 00238 * don't return any error (yet?)) 00239 */ 00240 err_t 00241 netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) 00242 { 00243 #if LWIP_TCP 00244 struct api_msg msg; 00245 err_t err; 00246 00247 /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ 00248 LWIP_UNUSED_ARG(backlog); 00249 00250 LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); 00251 00252 msg.function = do_listen; 00253 msg.msg.conn = conn; 00254 #if TCP_LISTEN_BACKLOG 00255 msg.msg.msg.lb.backlog = backlog; 00256 #endif /* TCP_LISTEN_BACKLOG */ 00257 err = TCPIP_APIMSG(&msg); 00258 00259 NETCONN_SET_SAFE_ERR(conn, err); 00260 return err; 00261 #else /* LWIP_TCP */ 00262 LWIP_UNUSED_ARG(conn); 00263 LWIP_UNUSED_ARG(backlog); 00264 return ERR_ARG; 00265 #endif /* LWIP_TCP */ 00266 } 00267 00268 /** 00269 * Accept a new connection on a TCP listening netconn. 00270 * 00271 * @param conn the TCP listen netconn 00272 * @param new_conn pointer where the new connection is stored 00273 * @return ERR_OK if a new connection has been received or an error 00274 * code otherwise 00275 */ 00276 err_t 00277 netconn_accept(struct netconn *conn, struct netconn **new_conn) 00278 { 00279 #if LWIP_TCP 00280 struct netconn *newconn; 00281 err_t err; 00282 #if TCP_LISTEN_BACKLOG 00283 struct api_msg msg; 00284 #endif /* TCP_LISTEN_BACKLOG */ 00285 00286 LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); 00287 *new_conn = NULL; 00288 LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); 00289 LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;); 00290 00291 err = conn->last_err; 00292 if (ERR_IS_FATAL(err)) { 00293 /* don't recv on fatal errors: this might block the application task 00294 waiting on acceptmbox forever! */ 00295 return err; 00296 } 00297 00298 #if LWIP_SO_RCVTIMEO 00299 if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { 00300 NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); 00301 return ERR_TIMEOUT; 00302 } 00303 #else 00304 sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0); 00305 #endif /* LWIP_SO_RCVTIMEO*/ 00306 /* Register event with callback */ 00307 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); 00308 00309 if (newconn == NULL) { 00310 /* connection has been aborted */ 00311 NETCONN_SET_SAFE_ERR(conn, ERR_ABRT); 00312 return ERR_ABRT; 00313 } 00314 #if TCP_LISTEN_BACKLOG 00315 /* Let the stack know that we have accepted the connection. */ 00316 msg.function = do_recv; 00317 msg.msg.conn = conn; 00318 /* don't care for the return value of do_recv */ 00319 TCPIP_APIMSG(&msg); 00320 #endif /* TCP_LISTEN_BACKLOG */ 00321 00322 *new_conn = newconn; 00323 /* don't set conn->last_err: it's only ERR_OK, anyway */ 00324 return ERR_OK; 00325 #else /* LWIP_TCP */ 00326 LWIP_UNUSED_ARG(conn); 00327 LWIP_UNUSED_ARG(new_conn); 00328 return ERR_ARG; 00329 #endif /* LWIP_TCP */ 00330 } 00331 00332 /** 00333 * Receive data: actual implementation that doesn't care whether pbuf or netbuf 00334 * is received 00335 * 00336 * @param conn the netconn from which to receive data 00337 * @param new_buf pointer where a new pbuf/netbuf is stored when received data 00338 * @return ERR_OK if data has been received, an error code otherwise (timeout, 00339 * memory error or another error) 00340 */ 00341 static err_t 00342 netconn_recv_data(struct netconn *conn, void **new_buf) 00343 { 00344 void *buf = NULL; 00345 u16_t len; 00346 err_t err; 00347 #if LWIP_TCP 00348 struct api_msg msg; 00349 #endif /* LWIP_TCP */ 00350 00351 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); 00352 *new_buf = NULL; 00353 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); 00354 LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); 00355 00356 err = conn->last_err; 00357 if (ERR_IS_FATAL(err)) { 00358 /* don't recv on fatal errors: this might block the application task 00359 waiting on recvmbox forever! */ 00360 /* @todo: this does not allow us to fetch data that has been put into recvmbox 00361 before the fatal error occurred - is that a problem? */ 00362 return err; 00363 } 00364 00365 #if LWIP_SO_RCVTIMEO 00366 if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { 00367 NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); 00368 return ERR_TIMEOUT; 00369 } 00370 #else 00371 sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); 00372 #endif /* LWIP_SO_RCVTIMEO*/ 00373 00374 #if LWIP_TCP 00375 if (conn->type == NETCONN_TCP) { 00376 if (!netconn_get_noautorecved(conn) || (buf == NULL)) { 00377 /* Let the stack know that we have taken the data. */ 00378 /* TODO: Speedup: Don't block and wait for the answer here 00379 (to prevent multiple thread-switches). */ 00380 msg.function = do_recv; 00381 msg.msg.conn = conn; 00382 if (buf != NULL) { 00383 msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len; 00384 } else { 00385 msg.msg.msg.r.len = 1; 00386 } 00387 /* don't care for the return value of do_recv */ 00388 TCPIP_APIMSG(&msg); 00389 } 00390 00391 /* If we are closed, we indicate that we no longer wish to use the socket */ 00392 if (buf == NULL) { 00393 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); 00394 /* Avoid to lose any previous error code */ 00395 NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); 00396 return ERR_CLSD; 00397 } 00398 len = ((struct pbuf *)buf)->tot_len; 00399 } 00400 #endif /* LWIP_TCP */ 00401 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW) 00402 else 00403 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ 00404 #if (LWIP_UDP || LWIP_RAW) 00405 { 00406 LWIP_ASSERT("buf != NULL", buf != NULL); 00407 len = netbuf_len((struct netbuf *)buf); 00408 } 00409 #endif /* (LWIP_UDP || LWIP_RAW) */ 00410 00411 #if LWIP_SO_RCVBUF 00412 SYS_ARCH_DEC(conn->recv_avail, len); 00413 #endif /* LWIP_SO_RCVBUF */ 00414 /* Register event with callback */ 00415 API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); 00416 00417 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); 00418 00419 *new_buf = buf; 00420 /* don't set conn->last_err: it's only ERR_OK, anyway */ 00421 return ERR_OK; 00422 } 00423 00424 /** 00425 * Receive data (in form of a pbuf) from a TCP netconn 00426 * 00427 * @param conn the netconn from which to receive data 00428 * @param new_buf pointer where a new pbuf is stored when received data 00429 * @return ERR_OK if data has been received, an error code otherwise (timeout, 00430 * memory error or another error) 00431 * ERR_ARG if conn is not a TCP netconn 00432 */ 00433 err_t 00434 netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) 00435 { 00436 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && 00437 netconn_type(conn) == NETCONN_TCP, return ERR_ARG;); 00438 00439 return netconn_recv_data(conn, (void **)new_buf); 00440 } 00441 00442 /** 00443 * Receive data (in form of a netbuf containing a packet buffer) from a netconn 00444 * 00445 * @param conn the netconn from which to receive data 00446 * @param new_buf pointer where a new netbuf is stored when received data 00447 * @return ERR_OK if data has been received, an error code otherwise (timeout, 00448 * memory error or another error) 00449 */ 00450 err_t 00451 netconn_recv(struct netconn *conn, struct netbuf **new_buf) 00452 { 00453 #if LWIP_TCP 00454 struct netbuf *buf = NULL; 00455 err_t err; 00456 #endif /* LWIP_TCP */ 00457 00458 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); 00459 *new_buf = NULL; 00460 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); 00461 LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); 00462 00463 #if LWIP_TCP 00464 if (conn->type == NETCONN_TCP) { 00465 struct pbuf *p = NULL; 00466 /* This is not a listening netconn, since recvmbox is set */ 00467 00468 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); 00469 if (buf == NULL) { 00470 NETCONN_SET_SAFE_ERR(conn, ERR_MEM); 00471 return ERR_MEM; 00472 } 00473 00474 err = netconn_recv_data(conn, (void **)&p); 00475 if (err != ERR_OK) { 00476 memp_free(MEMP_NETBUF, buf); 00477 return err; 00478 } 00479 LWIP_ASSERT("p != NULL", p != NULL); 00480 00481 buf->p = p; 00482 buf->ptr = p; 00483 buf->port = 0; 00484 ip_addr_set_any(&buf->addr); 00485 *new_buf = buf; 00486 /* don't set conn->last_err: it's only ERR_OK, anyway */ 00487 return ERR_OK; 00488 } else 00489 #endif /* LWIP_TCP */ 00490 { 00491 #if (LWIP_UDP || LWIP_RAW) 00492 return netconn_recv_data(conn, (void **)new_buf); 00493 #endif /* (LWIP_UDP || LWIP_RAW) */ 00494 } 00495 } 00496 00497 /** 00498 * TCP: update the receive window: by calling this, the application 00499 * tells the stack that it has processed data and is able to accept 00500 * new data. 00501 * ATTENTION: use with care, this is mainly used for sockets! 00502 * Can only be used when calling netconn_set_noautorecved(conn, 1) before. 00503 * 00504 * @param conn the netconn for which to update the receive window 00505 * @param length amount of data processed (ATTENTION: this must be accurate!) 00506 */ 00507 void 00508 netconn_recved(struct netconn *conn, u32_t length) 00509 { 00510 #if LWIP_TCP 00511 if ((conn != NULL) && (conn->type == NETCONN_TCP) && 00512 (netconn_get_noautorecved(conn))) { 00513 struct api_msg msg; 00514 /* Let the stack know that we have taken the data. */ 00515 /* TODO: Speedup: Don't block and wait for the answer here 00516 (to prevent multiple thread-switches). */ 00517 msg.function = do_recv; 00518 msg.msg.conn = conn; 00519 msg.msg.msg.r.len = length; 00520 /* don't care for the return value of do_recv */ 00521 TCPIP_APIMSG(&msg); 00522 } 00523 #else /* LWIP_TCP */ 00524 LWIP_UNUSED_ARG(conn); 00525 LWIP_UNUSED_ARG(length); 00526 #endif /* LWIP_TCP */ 00527 } 00528 00529 /** 00530 * Send data (in form of a netbuf) to a specific remote IP address and port. 00531 * Only to be used for UDP and RAW netconns (not TCP). 00532 * 00533 * @param conn the netconn over which to send data 00534 * @param buf a netbuf containing the data to send 00535 * @param addr the remote IP address to which to send the data 00536 * @param port the remote port to which to send the data 00537 * @return ERR_OK if data was sent, any other err_t on error 00538 */ 00539 err_t 00540 netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port) 00541 { 00542 if (buf != NULL) { 00543 ip_addr_set(&buf->addr, addr); 00544 buf->port = port; 00545 return netconn_send(conn, buf); 00546 } 00547 return ERR_VAL; 00548 } 00549 00550 /** 00551 * Send data over a UDP or RAW netconn (that is already connected). 00552 * 00553 * @param conn the UDP or RAW netconn over which to send data 00554 * @param buf a netbuf containing the data to send 00555 * @return ERR_OK if data was sent, any other err_t on error 00556 */ 00557 err_t 00558 netconn_send(struct netconn *conn, struct netbuf *buf) 00559 { 00560 struct api_msg msg; 00561 err_t err; 00562 00563 LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); 00564 00565 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); 00566 msg.function = do_send; 00567 msg.msg.conn = conn; 00568 msg.msg.msg.b = buf; 00569 err = TCPIP_APIMSG(&msg); 00570 00571 NETCONN_SET_SAFE_ERR(conn, err); 00572 return err; 00573 } 00574 00575 /** 00576 * Send data over a TCP netconn. 00577 * 00578 * @param conn the TCP netconn over which to send data 00579 * @param dataptr pointer to the application buffer that contains the data to send 00580 * @param size size of the application data to send 00581 * @param apiflags combination of following flags : 00582 * - NETCONN_COPY: data will be copied into memory belonging to the stack 00583 * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent 00584 * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once 00585 * @return ERR_OK if data was sent, any other err_t on error 00586 */ 00587 err_t 00588 netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags) 00589 { 00590 struct api_msg msg; 00591 err_t err; 00592 00593 LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); 00594 LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;); 00595 if (size == 0) { 00596 return ERR_OK; 00597 } 00598 00599 /* @todo: for non-blocking write, check if 'size' would ever fit into 00600 snd_queue or snd_buf */ 00601 msg.function = do_write; 00602 msg.msg.conn = conn; 00603 msg.msg.msg.w.dataptr = dataptr; 00604 msg.msg.msg.w.apiflags = apiflags; 00605 msg.msg.msg.w.len = size; 00606 /* For locking the core: this _can_ be delayed on low memory/low send buffer, 00607 but if it is, this is done inside api_msg.c:do_write(), so we can use the 00608 non-blocking version here. */ 00609 err = TCPIP_APIMSG(&msg); 00610 00611 NETCONN_SET_SAFE_ERR(conn, err); 00612 return err; 00613 } 00614 00615 /** 00616 * Close ot shutdown a TCP netconn (doesn't delete it). 00617 * 00618 * @param conn the TCP netconn to close or shutdown 00619 * @param how fully close or only shutdown one side? 00620 * @return ERR_OK if the netconn was closed, any other err_t on error 00621 */ 00622 static err_t 00623 netconn_close_shutdown(struct netconn *conn, u8_t how) 00624 { 00625 struct api_msg msg; 00626 err_t err; 00627 00628 LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); 00629 00630 msg.function = do_close; 00631 msg.msg.conn = conn; 00632 /* shutting down both ends is the same as closing */ 00633 msg.msg.msg.sd.shut = how; 00634 /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close, 00635 don't use TCPIP_APIMSG here */ 00636 err = tcpip_apimsg(&msg); 00637 00638 NETCONN_SET_SAFE_ERR(conn, err); 00639 return err; 00640 } 00641 00642 /** 00643 * Close a TCP netconn (doesn't delete it). 00644 * 00645 * @param conn the TCP netconn to close 00646 * @return ERR_OK if the netconn was closed, any other err_t on error 00647 */ 00648 err_t 00649 netconn_close(struct netconn *conn) 00650 { 00651 /* shutting down both ends is the same as closing */ 00652 return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); 00653 } 00654 00655 /** 00656 * Shut down one or both sides of a TCP netconn (doesn't delete it). 00657 * 00658 * @param conn the TCP netconn to shut down 00659 * @return ERR_OK if the netconn was closed, any other err_t on error 00660 */ 00661 err_t 00662 netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) 00663 { 00664 return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); 00665 } 00666 00667 #if LWIP_IGMP 00668 /** 00669 * Join multicast groups for UDP netconns. 00670 * 00671 * @param conn the UDP netconn for which to change multicast addresses 00672 * @param multiaddr IP address of the multicast group to join or leave 00673 * @param netif_addr the IP address of the network interface on which to send 00674 * the igmp message 00675 * @param join_or_leave flag whether to send a join- or leave-message 00676 * @return ERR_OK if the action was taken, any err_t on error 00677 */ 00678 err_t 00679 netconn_join_leave_group(struct netconn *conn, 00680 ip_addr_t *multiaddr, 00681 ip_addr_t *netif_addr, 00682 enum netconn_igmp join_or_leave) 00683 { 00684 struct api_msg msg; 00685 err_t err; 00686 00687 LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); 00688 00689 msg.function = do_join_leave_group; 00690 msg.msg.conn = conn; 00691 msg.msg.msg.jl.multiaddr = multiaddr; 00692 msg.msg.msg.jl.netif_addr = netif_addr; 00693 msg.msg.msg.jl.join_or_leave = join_or_leave; 00694 err = TCPIP_APIMSG(&msg); 00695 00696 NETCONN_SET_SAFE_ERR(conn, err); 00697 return err; 00698 } 00699 #endif /* LWIP_IGMP */ 00700 00701 #if LWIP_DNS 00702 /** 00703 * Execute a DNS query, only one IP address is returned 00704 * 00705 * @param name a string representation of the DNS host name to query 00706 * @param addr a preallocated ip_addr_t where to store the resolved IP address 00707 * @return ERR_OK: resolving succeeded 00708 * ERR_MEM: memory error, try again later 00709 * ERR_ARG: dns client not initialized or invalid hostname 00710 * ERR_VAL: dns server response was invalid 00711 */ 00712 err_t 00713 netconn_gethostbyname(const char *name, ip_addr_t *addr) 00714 { 00715 struct dns_api_msg msg; 00716 err_t err; 00717 sys_sem_t sem; 00718 00719 LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); 00720 LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); 00721 00722 err = sys_sem_new(&sem, 0); 00723 if (err != ERR_OK) { 00724 return err; 00725 } 00726 00727 msg.name = name; 00728 msg.addr = addr; 00729 msg.err = &err; 00730 msg.sem = &sem; 00731 00732 tcpip_callback(do_gethostbyname, &msg); 00733 sys_sem_wait(&sem); 00734 sys_sem_free(&sem); 00735 00736 return err; 00737 } 00738 #endif /* LWIP_DNS*/ 00739 00740 #endif /* LWIP_NETCONN */
Generated on Tue Jul 12 2022 11:29:36 by
