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