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 F7_Ethernet 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 LWIP_DEBUGF(API_LIB_DEBUG, ("~netconn_recv_data: new_buf=0x%x\r\n",new_buf)); 00351 LWIP_DEBUGF(API_LIB_DEBUG, ("~~netconn_recv_data: conn mailbox=0x%x\r\n",&conn->recvmbox)); 00352 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); 00353 *new_buf = NULL; 00354 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); 00355 LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); 00356 LWIP_DEBUGF(API_LIB_DEBUG, ("~~netconn_recv_data: err=0x%x\r\n",conn->last_err)); 00357 err = conn->last_err; 00358 if (err < ERR_ISCONN) { 00359 /* don't recv on fatal errors: this might block the application task 00360 waiting on recvmbox forever! */ 00361 /* @todo: this does not allow us to fetch data that has been put into recvmbox 00362 before the fatal error occurred - is that a problem? */ 00363 return err; 00364 } 00365 00366 #if LWIP_SO_RCVTIMEO 00367 LWIP_DEBUGF(API_LIB_DEBUG, ("~~~netconn_recv_data: fetch with timeout id %d\r\n",conn->recvmbox.id)); 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 LWIP_DEBUGF(API_LIB_DEBUG, ("~~~netconn_recv_data: fetch id %d \r\n",conn->recvmbox.id)); 00374 sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); 00375 #endif /* LWIP_SO_RCVTIMEO*/ 00376 00377 #if LWIP_TCP 00378 #if (LWIP_UDP || LWIP_RAW) 00379 if (conn->type == NETCONN_TCP) 00380 #endif /* (LWIP_UDP || LWIP_RAW) */ 00381 { 00382 if (!netconn_get_noautorecved(conn) || (buf == NULL)) { 00383 /* Let the stack know that we have taken the data. */ 00384 /* TODO: Speedup: Don't block and wait for the answer here 00385 (to prevent multiple thread-switches). */ 00386 msg.function = do_recv; 00387 msg.msg.conn = conn; 00388 if (buf != NULL) { 00389 msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len; 00390 } else { 00391 msg.msg.msg.r.len = 1; 00392 } 00393 /* don't care for the return value of do_recv */ 00394 TCPIP_APIMSG(&msg); 00395 } 00396 00397 /* If we are closed, we indicate that we no longer wish to use the socket */ 00398 if (buf == NULL) { 00399 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); 00400 /* Avoid to lose any previous error code */ 00401 NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); 00402 return ERR_CLSD; 00403 } 00404 len = ((struct pbuf *)buf)->tot_len; 00405 } 00406 #endif /* LWIP_TCP */ 00407 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW) 00408 else 00409 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ 00410 #if (LWIP_UDP || LWIP_RAW) 00411 { 00412 LWIP_ASSERT("buf != NULL", buf != NULL); 00413 len = netbuf_len((struct netbuf *)buf); 00414 } 00415 #endif /* (LWIP_UDP || LWIP_RAW) */ 00416 00417 #if LWIP_SO_RCVBUF 00418 SYS_ARCH_DEC(conn->recv_avail, len); 00419 #endif /* LWIP_SO_RCVBUF */ 00420 /* Register event with callback */ 00421 API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); 00422 00423 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); 00424 00425 *new_buf = buf; 00426 /* don't set conn->last_err: it's only ERR_OK, anyway */ 00427 return ERR_OK; 00428 } 00429 00430 /** 00431 * Receive data (in form of a pbuf) from a TCP netconn 00432 * 00433 * @param conn the netconn from which to receive data 00434 * @param new_buf pointer where a new pbuf is stored when received data 00435 * @return ERR_OK if data has been received, an error code otherwise (timeout, 00436 * memory error or another error) 00437 * ERR_ARG if conn is not a TCP netconn 00438 */ 00439 err_t 00440 netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) 00441 { 00442 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && 00443 netconn_type(conn) == NETCONN_TCP, return ERR_ARG;); 00444 LWIP_DEBUGF(API_LIB_DEBUG, ("+++netconn_recv_data: tcp \n")); 00445 return netconn_recv_data(conn, (void **)new_buf); 00446 } 00447 00448 /** 00449 * Receive data (in form of a netbuf containing a packet buffer) from a netconn 00450 * 00451 * @param conn the netconn from which to receive data 00452 * @param new_buf pointer where a new netbuf is stored when received data 00453 * @return ERR_OK if data has been received, an error code otherwise (timeout, 00454 * memory error or another error) 00455 */ 00456 err_t 00457 netconn_recv(struct netconn *conn, struct netbuf **new_buf) 00458 { 00459 #if LWIP_TCP 00460 struct netbuf *buf = NULL; 00461 err_t err; 00462 #endif /* LWIP_TCP */ 00463 00464 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); 00465 *new_buf = NULL; 00466 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); 00467 LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); 00468 00469 #if LWIP_TCP 00470 #if (LWIP_UDP || LWIP_RAW) 00471 if (conn->type == NETCONN_TCP) 00472 #endif /* (LWIP_UDP || LWIP_RAW) */ 00473 { 00474 struct pbuf *p = NULL; 00475 /* This is not a listening netconn, since recvmbox is set */ 00476 00477 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); 00478 if (buf == NULL) { 00479 NETCONN_SET_SAFE_ERR(conn, ERR_MEM); 00480 return ERR_MEM; 00481 } 00482 00483 err = netconn_recv_data(conn, (void **)&p); 00484 if (err != ERR_OK) { 00485 memp_free(MEMP_NETBUF, buf); 00486 return err; 00487 } 00488 LWIP_ASSERT("p != NULL", p != NULL); 00489 00490 buf->p = p; 00491 buf->ptr = p; 00492 buf->port = 0; 00493 ip_addr_set_any(&buf->addr); 00494 *new_buf = buf; 00495 /* don't set conn->last_err: it's only ERR_OK, anyway */ 00496 return ERR_OK; 00497 } 00498 #endif /* LWIP_TCP */ 00499 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW) 00500 else 00501 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ 00502 { 00503 #if (LWIP_UDP || LWIP_RAW) 00504 return netconn_recv_data(conn, (void **)new_buf); 00505 #endif /* (LWIP_UDP || LWIP_RAW) */ 00506 } 00507 } 00508 00509 /** 00510 * TCP: update the receive window: by calling this, the application 00511 * tells the stack that it has processed data and is able to accept 00512 * new data. 00513 * ATTENTION: use with care, this is mainly used for sockets! 00514 * Can only be used when calling netconn_set_noautorecved(conn, 1) before. 00515 * 00516 * @param conn the netconn for which to update the receive window 00517 * @param length amount of data processed (ATTENTION: this must be accurate!) 00518 */ 00519 void 00520 netconn_recved(struct netconn *conn, u32_t length) 00521 { 00522 #if LWIP_TCP 00523 if ((conn != NULL) && (conn->type == NETCONN_TCP) && 00524 (netconn_get_noautorecved(conn))) { 00525 struct api_msg msg; 00526 /* Let the stack know that we have taken the data. */ 00527 /* TODO: Speedup: Don't block and wait for the answer here 00528 (to prevent multiple thread-switches). */ 00529 msg.function = do_recv; 00530 msg.msg.conn = conn; 00531 msg.msg.msg.r.len = length; 00532 /* don't care for the return value of do_recv */ 00533 TCPIP_APIMSG(&msg); 00534 } 00535 #else /* LWIP_TCP */ 00536 LWIP_UNUSED_ARG(conn); 00537 LWIP_UNUSED_ARG(length); 00538 #endif /* LWIP_TCP */ 00539 } 00540 00541 /** 00542 * Send data (in form of a netbuf) to a specific remote IP address and port. 00543 * Only to be used for UDP and RAW netconns (not TCP). 00544 * 00545 * @param conn the netconn over which to send data 00546 * @param buf a netbuf containing the data to send 00547 * @param addr the remote IP address to which to send the data 00548 * @param port the remote port to which to send the data 00549 * @return ERR_OK if data was sent, any other err_t on error 00550 */ 00551 err_t 00552 netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port) 00553 { 00554 if (buf != NULL) { 00555 ip_addr_set(&buf->addr, addr); 00556 buf->port = port; 00557 return netconn_send(conn, buf); 00558 } 00559 return ERR_VAL; 00560 } 00561 00562 /** 00563 * Send data over a UDP or RAW netconn (that is already connected). 00564 * 00565 * @param conn the UDP or RAW netconn over which to send data 00566 * @param buf a netbuf containing the data to send 00567 * @return ERR_OK if data was sent, any other err_t on error 00568 */ 00569 err_t 00570 netconn_send(struct netconn *conn, struct netbuf *buf) 00571 { 00572 struct api_msg msg; 00573 err_t err; 00574 00575 LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); 00576 00577 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); 00578 msg.function = do_send; 00579 msg.msg.conn = conn; 00580 msg.msg.msg.b = buf; 00581 err = TCPIP_APIMSG(&msg); 00582 00583 NETCONN_SET_SAFE_ERR(conn, err); 00584 return err; 00585 } 00586 00587 /** 00588 * Send data over a TCP netconn. 00589 * 00590 * @param conn the TCP netconn over which to send data 00591 * @param dataptr pointer to the application buffer that contains the data to send 00592 * @param size size of the application data to send 00593 * @param apiflags combination of following flags : 00594 * - NETCONN_COPY: data will be copied into memory belonging to the stack 00595 * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent 00596 * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once 00597 * @param bytes_written pointer to a location that receives the number of written bytes 00598 * @return ERR_OK if data was sent, any other err_t on error 00599 */ 00600 err_t 00601 netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, 00602 u8_t apiflags, size_t *bytes_written) 00603 { 00604 struct api_msg msg; 00605 err_t err; 00606 u8_t dontblock; 00607 00608 LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); 00609 LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;); 00610 if (size == 0) { 00611 return ERR_OK; 00612 } 00613 dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); 00614 if (dontblock && !bytes_written) { 00615 /* This implies netconn_write() cannot be used for non-blocking send, since 00616 it has no way to return the number of bytes written. */ 00617 return ERR_VAL; 00618 } 00619 00620 /* non-blocking write sends as much */ 00621 msg.function = do_write; 00622 msg.msg.conn = conn; 00623 msg.msg.msg.w.dataptr = dataptr; 00624 msg.msg.msg.w.apiflags = apiflags; 00625 msg.msg.msg.w.len = size; 00626 #if LWIP_SO_SNDTIMEO 00627 if (conn->send_timeout != 0) { 00628 /* get the time we started, which is later compared to 00629 sys_now() + conn->send_timeout */ 00630 msg.msg.msg.w.time_started = sys_now(); 00631 } else { 00632 msg.msg.msg.w.time_started = 0; 00633 } 00634 #endif /* LWIP_SO_SNDTIMEO */ 00635 00636 /* For locking the core: this _can_ be delayed on low memory/low send buffer, 00637 but if it is, this is done inside api_msg.c:do_write(), so we can use the 00638 non-blocking version here. */ 00639 err = TCPIP_APIMSG(&msg); 00640 if ((err == ERR_OK) && (bytes_written != NULL)) { 00641 if (dontblock 00642 #if LWIP_SO_SNDTIMEO 00643 || (conn->send_timeout != 0) 00644 #endif /* LWIP_SO_SNDTIMEO */ 00645 ) { 00646 /* nonblocking write: maybe the data has been sent partly */ 00647 *bytes_written = msg.msg.msg.w.len; 00648 } else { 00649 /* blocking call succeeded: all data has been sent if it */ 00650 *bytes_written = size; 00651 } 00652 } 00653 00654 NETCONN_SET_SAFE_ERR(conn, err); 00655 return err; 00656 } 00657 00658 /** 00659 * Close ot shutdown a TCP netconn (doesn't delete it). 00660 * 00661 * @param conn the TCP netconn to close or shutdown 00662 * @param how fully close or only shutdown one side? 00663 * @return ERR_OK if the netconn was closed, any other err_t on error 00664 */ 00665 static err_t 00666 netconn_close_shutdown(struct netconn *conn, u8_t how) 00667 { 00668 struct api_msg msg; 00669 err_t err; 00670 00671 LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); 00672 00673 msg.function = do_close; 00674 msg.msg.conn = conn; 00675 /* shutting down both ends is the same as closing */ 00676 msg.msg.msg.sd.shut = how; 00677 /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close, 00678 don't use TCPIP_APIMSG here */ 00679 err = tcpip_apimsg(&msg); 00680 00681 NETCONN_SET_SAFE_ERR(conn, err); 00682 return err; 00683 } 00684 00685 /** 00686 * Close a TCP netconn (doesn't delete it). 00687 * 00688 * @param conn the TCP netconn to close 00689 * @return ERR_OK if the netconn was closed, any other err_t on error 00690 */ 00691 err_t 00692 netconn_close(struct netconn *conn) 00693 { 00694 /* shutting down both ends is the same as closing */ 00695 return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); 00696 } 00697 00698 /** 00699 * Shut down one or both sides of a TCP netconn (doesn't delete it). 00700 * 00701 * @param conn the TCP netconn to shut down 00702 * @return ERR_OK if the netconn was closed, any other err_t on error 00703 */ 00704 err_t 00705 netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) 00706 { 00707 return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); 00708 } 00709 00710 #if LWIP_IGMP 00711 /** 00712 * Join multicast groups for UDP netconns. 00713 * 00714 * @param conn the UDP netconn for which to change multicast addresses 00715 * @param multiaddr IP address of the multicast group to join or leave 00716 * @param netif_addr the IP address of the network interface on which to send 00717 * the igmp message 00718 * @param join_or_leave flag whether to send a join- or leave-message 00719 * @return ERR_OK if the action was taken, any err_t on error 00720 */ 00721 err_t 00722 netconn_join_leave_group(struct netconn *conn, 00723 ip_addr_t *multiaddr, 00724 ip_addr_t *netif_addr, 00725 enum netconn_igmp join_or_leave) 00726 { 00727 struct api_msg msg; 00728 err_t err; 00729 00730 LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); 00731 00732 msg.function = do_join_leave_group; 00733 msg.msg.conn = conn; 00734 msg.msg.msg.jl.multiaddr = multiaddr; 00735 msg.msg.msg.jl.netif_addr = netif_addr; 00736 msg.msg.msg.jl.join_or_leave = join_or_leave; 00737 err = TCPIP_APIMSG(&msg); 00738 00739 NETCONN_SET_SAFE_ERR(conn, err); 00740 return err; 00741 } 00742 #endif /* LWIP_IGMP */ 00743 00744 #if LWIP_DNS 00745 /** 00746 * Execute a DNS query, only one IP address is returned 00747 * 00748 * @param name a string representation of the DNS host name to query 00749 * @param addr a preallocated ip_addr_t where to store the resolved IP address 00750 * @return ERR_OK: resolving succeeded 00751 * ERR_MEM: memory error, try again later 00752 * ERR_ARG: dns client not initialized or invalid hostname 00753 * ERR_VAL: dns server response was invalid 00754 */ 00755 err_t 00756 netconn_gethostbyname(const char *name, ip_addr_t *addr) 00757 { 00758 struct dns_api_msg msg; 00759 err_t err; 00760 sys_sem_t sem; 00761 00762 LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); 00763 LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); 00764 00765 err = sys_sem_new(&sem, 0); 00766 if (err != ERR_OK) { 00767 return err; 00768 } 00769 00770 msg.name = name; 00771 msg.addr = addr; 00772 msg.err = &err; 00773 msg.sem = &sem; 00774 00775 tcpip_callback(do_gethostbyname, &msg); 00776 sys_sem_wait(&sem); 00777 sys_sem_free(&sem); 00778 00779 return err; 00780 } 00781 #endif /* LWIP_DNS*/ 00782 00783 #endif /* LWIP_NETCONN */
Generated on Tue Jul 12 2022 21:19:01 by
1.7.2
