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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lwip_altcp.c
00001 /** 00002 * @file 00003 * @defgroup altcp Application layered TCP Functions 00004 * @ingroup altcp_api 00005 * 00006 * This file contains the common functions for altcp to work. 00007 * For more details see @ref altcp_api. 00008 */ 00009 00010 /** 00011 * @defgroup altcp_api Application layered TCP Introduction 00012 * @ingroup callbackstyle_api 00013 * 00014 * Overview 00015 * -------- 00016 * altcp (application layered TCP connection API; to be used from TCPIP thread) 00017 * is an abstraction layer that prevents applications linking hard against the 00018 * @ref tcp.h functions while providing the same functionality. It is used to 00019 * e.g. add SSL/TLS (see LWIP_ALTCP_TLS) or proxy-connect support to an application 00020 * written for the tcp callback API without that application knowing the 00021 * protocol details. 00022 * 00023 * * This interface mimics the tcp callback API to the application while preventing 00024 * direct linking (much like virtual functions). 00025 * * This way, an application can make use of other application layer protocols 00026 * on top of TCP without knowing the details (e.g. TLS, proxy connection). 00027 * * This is achieved by simply including "lwip/altcp.h" instead of "lwip/tcp.h", 00028 * replacing "struct tcp_pcb" with "struct altcp_pcb" and prefixing all functions 00029 * with "altcp_" instead of "tcp_". 00030 * 00031 * With altcp support disabled (LWIP_ALTCP==0), applications written against the 00032 * altcp API can still be compiled but are directly linked against the tcp.h 00033 * callback API and then cannot use layered protocols. To minimize code changes 00034 * in this case, the use of altcp_allocators is strongly suggested. 00035 * 00036 * Usage 00037 * ----- 00038 * To make use of this API from an existing tcp raw API application: 00039 * * Include "lwip/altcp.h" instead of "lwip/tcp.h" 00040 * * Replace "struct tcp_pcb" with "struct altcp_pcb" 00041 * * Prefix all called tcp API functions with "altcp_" instead of "tcp_" to link 00042 * against the altcp functions 00043 * * @ref altcp_new (and @ref altcp_new_ip_type/@ref altcp_new_ip6) take 00044 * an @ref altcp_allocator_t as an argument, whereas the original tcp API 00045 * functions take no arguments. 00046 * * An @ref altcp_allocator_t allocator is an object that holds a pointer to an 00047 * allocator object and a corresponding state (e.g. for TLS, the corresponding 00048 * state may hold certificates or keys). This way, the application does not 00049 * even need to know if it uses TLS or pure TCP, this is handled at runtime 00050 * by passing a specific allocator. 00051 * * An application can alternatively bind hard to the altcp_tls API by calling 00052 * @ref altcp_tls_new or @ref altcp_tls_wrap. 00053 * * The TLS layer is not directly implemented by lwIP, but a port to mbedTLS is 00054 * provided. 00055 * * Another altcp layer is proxy-connect to use TLS behind a HTTP proxy (see 00056 * @ref altcp_proxyconnect.h) 00057 * 00058 * altcp_allocator_t 00059 * ----------------- 00060 * An altcp allocator is created by the application by combining an allocator 00061 * callback function and a corresponding state, e.g.:\code{.c} 00062 * static const unsigned char cert[] = {0x2D, ... (see mbedTLS doc for how to create this)}; 00063 * struct altcp_tls_config * conf = altcp_tls_create_config_client(cert, sizeof(cert)); 00064 * altcp_allocator_t tls_allocator = { 00065 * altcp_tls_alloc, conf 00066 * }; 00067 * \endcode 00068 * 00069 * 00070 * struct altcp_tls_config 00071 * ----------------------- 00072 * The struct altcp_tls_config holds state that is needed to create new TLS client 00073 * or server connections (e.g. certificates and private keys). 00074 * 00075 * It is not defined by lwIP itself but by the TLS port (e.g. altcp_tls to mbedTLS 00076 * adaption). However, the parameters used to create it are defined in @ref 00077 * altcp_tls.h (see @ref altcp_tls_create_config_server_privkey_cert for servers 00078 * and @ref altcp_tls_create_config_client/@ref altcp_tls_create_config_client_2wayauth 00079 * for clients). 00080 * 00081 * For mbedTLS, ensure that certificates can be parsed by 'mbedtls_x509_crt_parse()' and 00082 * private keys can be parsed by 'mbedtls_pk_parse_key()'. 00083 */ 00084 00085 /* 00086 * Copyright (c) 2017 Simon Goldschmidt 00087 * All rights reserved. 00088 * 00089 * Redistribution and use in source and binary forms, with or without modification, 00090 * are permitted provided that the following conditions are met: 00091 * 00092 * 1. Redistributions of source code must retain the above copyright notice, 00093 * this list of conditions and the following disclaimer. 00094 * 2. Redistributions in binary form must reproduce the above copyright notice, 00095 * this list of conditions and the following disclaimer in the documentation 00096 * and/or other materials provided with the distribution. 00097 * 3. The name of the author may not be used to endorse or promote products 00098 * derived from this software without specific prior written permission. 00099 * 00100 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00101 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00102 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00103 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00104 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00105 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00106 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00107 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00108 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00109 * OF SUCH DAMAGE. 00110 * 00111 * This file is part of the lwIP TCP/IP stack. 00112 * 00113 * Author: Simon Goldschmidt <goldsimon@gmx.de> 00114 * 00115 */ 00116 00117 #include "lwip/opt.h" 00118 00119 #if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ 00120 00121 #include "lwip/altcp.h" 00122 #include "lwip/priv/altcp_priv.h" 00123 #include "lwip/altcp_tcp.h" 00124 #include "lwip/tcp.h" 00125 #include "lwip/mem.h" 00126 00127 #include <string.h> 00128 00129 extern const struct altcp_functions altcp_tcp_functions; 00130 00131 /** 00132 * For altcp layer implementations only: allocate a new struct altcp_pcb from the pool 00133 * and zero the memory 00134 */ 00135 struct altcp_pcb * 00136 altcp_alloc(void) 00137 { 00138 struct altcp_pcb *ret = (struct altcp_pcb *)memp_malloc(MEMP_ALTCP_PCB); 00139 if (ret != NULL) { 00140 memset(ret, 0, sizeof(struct altcp_pcb)); 00141 } 00142 return ret; 00143 } 00144 00145 /** 00146 * For altcp layer implementations only: return a struct altcp_pcb to the pool 00147 */ 00148 void 00149 altcp_free(struct altcp_pcb *conn) 00150 { 00151 if (conn) { 00152 if (conn->fns && conn->fns->dealloc) { 00153 conn->fns->dealloc(conn); 00154 } 00155 memp_free(MEMP_ALTCP_PCB, conn); 00156 } 00157 } 00158 00159 /** 00160 * @ingroup altcp 00161 * altcp_new_ip6: @ref altcp_new for IPv6 00162 */ 00163 struct altcp_pcb * 00164 altcp_new_ip6(altcp_allocator_t *allocator) 00165 { 00166 return altcp_new_ip_type(allocator, IPADDR_TYPE_V6); 00167 } 00168 00169 /** 00170 * @ingroup altcp 00171 * altcp_new: @ref altcp_new for IPv4 00172 */ 00173 struct altcp_pcb * 00174 altcp_new(altcp_allocator_t *allocator) 00175 { 00176 return altcp_new_ip_type(allocator, IPADDR_TYPE_V4); 00177 } 00178 00179 /** 00180 * @ingroup altcp 00181 * altcp_new_ip_type: called by applications to allocate a new pcb with the help of an 00182 * allocator function. 00183 * 00184 * @param allocator allocator function and argument 00185 * @param ip_type IP version of the pcb (@ref lwip_ip_addr_type) 00186 * @return a new altcp_pcb or NULL on error 00187 */ 00188 struct altcp_pcb * 00189 altcp_new_ip_type(altcp_allocator_t *allocator, u8_t ip_type) 00190 { 00191 struct altcp_pcb *conn; 00192 if (allocator == NULL) { 00193 /* no allocator given, create a simple TCP connection */ 00194 return altcp_tcp_new_ip_type(ip_type); 00195 } 00196 if (allocator->alloc == NULL) { 00197 /* illegal allocator */ 00198 return NULL; 00199 } 00200 conn = allocator->alloc(allocator->arg, ip_type); 00201 if (conn == NULL) { 00202 /* allocation failed */ 00203 return NULL; 00204 } 00205 return conn; 00206 } 00207 00208 /** 00209 * @ingroup altcp 00210 * @see tcp_arg() 00211 */ 00212 void 00213 altcp_arg (struct altcp_pcb *conn, void *arg) 00214 { 00215 if (conn) { 00216 conn->arg = arg; 00217 } 00218 } 00219 00220 /** 00221 * @ingroup altcp 00222 * @see tcp_accept() 00223 */ 00224 void 00225 altcp_accept (struct altcp_pcb *conn, altcp_accept_fn accept) 00226 { 00227 if (conn != NULL) { 00228 conn->accept = accept; 00229 } 00230 } 00231 00232 /** 00233 * @ingroup altcp 00234 * @see tcp_recv() 00235 */ 00236 void 00237 altcp_recv (struct altcp_pcb *conn, altcp_recv_fn recv) 00238 { 00239 if (conn) { 00240 conn->recv = recv; 00241 } 00242 } 00243 00244 /** 00245 * @ingroup altcp 00246 * @see tcp_sent() 00247 */ 00248 void 00249 altcp_sent (struct altcp_pcb *conn, altcp_sent_fn sent) 00250 { 00251 if (conn) { 00252 conn->sent = sent; 00253 } 00254 } 00255 00256 /** 00257 * @ingroup altcp 00258 * @see tcp_poll() 00259 */ 00260 void 00261 altcp_poll (struct altcp_pcb *conn, altcp_poll_fn poll, u8_t interval) 00262 { 00263 if (conn) { 00264 conn->poll = poll; 00265 conn->pollinterval = interval; 00266 if (conn->fns && conn->fns->set_poll) { 00267 conn->fns->set_poll(conn, interval); 00268 } 00269 } 00270 } 00271 00272 /** 00273 * @ingroup altcp 00274 * @see tcp_err() 00275 */ 00276 void 00277 altcp_err (struct altcp_pcb *conn, altcp_err_fn err) 00278 { 00279 if (conn) { 00280 conn->err = err; 00281 } 00282 } 00283 00284 /* Generic functions calling the "virtual" ones */ 00285 00286 /** 00287 * @ingroup altcp 00288 * @see tcp_recved() 00289 */ 00290 void 00291 altcp_recved (struct altcp_pcb *conn, u16_t len) 00292 { 00293 if (conn && conn->fns && conn->fns->recved) { 00294 conn->fns->recved(conn, len); 00295 } 00296 } 00297 00298 /** 00299 * @ingroup altcp 00300 * @see tcp_bind() 00301 */ 00302 err_t 00303 altcp_bind (struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port) 00304 { 00305 if (conn && conn->fns && conn->fns->bind) { 00306 return conn->fns->bind(conn, ipaddr, port); 00307 } 00308 return ERR_VAL; 00309 } 00310 00311 /** 00312 * @ingroup altcp 00313 * @see tcp_connect() 00314 */ 00315 err_t 00316 altcp_connect (struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected) 00317 { 00318 if (conn && conn->fns && conn->fns->connect) { 00319 return conn->fns->connect(conn, ipaddr, port, connected); 00320 } 00321 return ERR_VAL; 00322 } 00323 00324 /** 00325 * @ingroup altcp 00326 * @see tcp_listen_with_backlog_and_err() 00327 */ 00328 struct altcp_pcb * 00329 altcp_listen_with_backlog_and_err (struct altcp_pcb *conn, u8_t backlog, err_t *err) 00330 { 00331 if (conn && conn->fns && conn->fns->listen) { 00332 return conn->fns->listen(conn, backlog, err); 00333 } 00334 return NULL; 00335 } 00336 00337 /** 00338 * @ingroup altcp 00339 * @see tcp_abort() 00340 */ 00341 void 00342 altcp_abort (struct altcp_pcb *conn) 00343 { 00344 if (conn && conn->fns && conn->fns->abort) { 00345 conn->fns->abort(conn); 00346 } 00347 } 00348 00349 /** 00350 * @ingroup altcp 00351 * @see tcp_close() 00352 */ 00353 err_t 00354 altcp_close (struct altcp_pcb *conn) 00355 { 00356 if (conn && conn->fns && conn->fns->close) { 00357 return conn->fns->close(conn); 00358 } 00359 return ERR_VAL; 00360 } 00361 00362 /** 00363 * @ingroup altcp 00364 * @see tcp_shutdown() 00365 */ 00366 err_t 00367 altcp_shutdown (struct altcp_pcb *conn, int shut_rx, int shut_tx) 00368 { 00369 if (conn && conn->fns && conn->fns->shutdown) { 00370 return conn->fns->shutdown(conn, shut_rx, shut_tx); 00371 } 00372 return ERR_VAL; 00373 } 00374 00375 /** 00376 * @ingroup altcp 00377 * @see tcp_write() 00378 */ 00379 err_t 00380 altcp_write (struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags) 00381 { 00382 if (conn && conn->fns && conn->fns->write) { 00383 return conn->fns->write(conn, dataptr, len, apiflags); 00384 } 00385 return ERR_VAL; 00386 } 00387 00388 /** 00389 * @ingroup altcp 00390 * @see tcp_output() 00391 */ 00392 err_t 00393 altcp_output (struct altcp_pcb *conn) 00394 { 00395 if (conn && conn->fns && conn->fns->output) { 00396 return conn->fns->output(conn); 00397 } 00398 return ERR_VAL; 00399 } 00400 00401 /** 00402 * @ingroup altcp 00403 * @see tcp_mss() 00404 */ 00405 u16_t 00406 altcp_mss (struct altcp_pcb *conn) 00407 { 00408 if (conn && conn->fns && conn->fns->mss) { 00409 return conn->fns->mss(conn); 00410 } 00411 return 0; 00412 } 00413 00414 /** 00415 * @ingroup altcp 00416 * @see tcp_sndbuf() 00417 */ 00418 u16_t 00419 altcp_sndbuf (struct altcp_pcb *conn) 00420 { 00421 if (conn && conn->fns && conn->fns->sndbuf) { 00422 return conn->fns->sndbuf(conn); 00423 } 00424 return 0; 00425 } 00426 00427 /** 00428 * @ingroup altcp 00429 * @see tcp_sndqueuelen() 00430 */ 00431 u16_t 00432 altcp_sndqueuelen (struct altcp_pcb *conn) 00433 { 00434 if (conn && conn->fns && conn->fns->sndqueuelen) { 00435 return conn->fns->sndqueuelen(conn); 00436 } 00437 return 0; 00438 } 00439 00440 void 00441 altcp_nagle_disable(struct altcp_pcb *conn) 00442 { 00443 if (conn && conn->fns && conn->fns->nagle_disable) { 00444 conn->fns->nagle_disable(conn); 00445 } 00446 } 00447 00448 void 00449 altcp_nagle_enable(struct altcp_pcb *conn) 00450 { 00451 if (conn && conn->fns && conn->fns->nagle_enable) { 00452 conn->fns->nagle_enable(conn); 00453 } 00454 } 00455 00456 int 00457 altcp_nagle_disabled(struct altcp_pcb *conn) 00458 { 00459 if (conn && conn->fns && conn->fns->nagle_disabled) { 00460 return conn->fns->nagle_disabled(conn); 00461 } 00462 return 0; 00463 } 00464 00465 /** 00466 * @ingroup altcp 00467 * @see tcp_setprio() 00468 */ 00469 void 00470 altcp_setprio (struct altcp_pcb *conn, u8_t prio) 00471 { 00472 if (conn && conn->fns && conn->fns->setprio) { 00473 conn->fns->setprio(conn, prio); 00474 } 00475 } 00476 00477 err_t 00478 altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port) 00479 { 00480 if (conn && conn->fns && conn->fns->addrinfo) { 00481 return conn->fns->addrinfo(conn, local, addr, port); 00482 } 00483 return ERR_VAL; 00484 } 00485 00486 ip_addr_t * 00487 altcp_get_ip(struct altcp_pcb *conn, int local) 00488 { 00489 if (conn && conn->fns && conn->fns->getip) { 00490 return conn->fns->getip(conn, local); 00491 } 00492 return NULL; 00493 } 00494 00495 u16_t 00496 altcp_get_port(struct altcp_pcb *conn, int local) 00497 { 00498 if (conn && conn->fns && conn->fns->getport) { 00499 return conn->fns->getport(conn, local); 00500 } 00501 return 0; 00502 } 00503 00504 #ifdef LWIP_DEBUG 00505 enum tcp_state 00506 altcp_dbg_get_tcp_state(struct altcp_pcb *conn) 00507 { 00508 if (conn && conn->fns && conn->fns->dbg_get_tcp_state) { 00509 return conn->fns->dbg_get_tcp_state(conn); 00510 } 00511 return CLOSED; 00512 } 00513 #endif 00514 00515 /* Default implementations for the "virtual" functions */ 00516 00517 void 00518 altcp_default_set_poll(struct altcp_pcb *conn, u8_t interval) 00519 { 00520 if (conn && conn->inner_conn) { 00521 altcp_poll (conn->inner_conn, conn->poll, interval); 00522 } 00523 } 00524 00525 void 00526 altcp_default_recved(struct altcp_pcb *conn, u16_t len) 00527 { 00528 if (conn && conn->inner_conn) { 00529 altcp_recved (conn->inner_conn, len); 00530 } 00531 } 00532 00533 err_t 00534 altcp_default_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port) 00535 { 00536 if (conn && conn->inner_conn) { 00537 return altcp_bind (conn->inner_conn, ipaddr, port); 00538 } 00539 return ERR_VAL; 00540 } 00541 00542 err_t 00543 altcp_default_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx) 00544 { 00545 if (conn) { 00546 if (shut_rx && shut_tx && conn->fns && conn->fns->close) { 00547 /* default shutdown for both sides is close */ 00548 return conn->fns->close(conn); 00549 } 00550 if (conn->inner_conn) { 00551 return altcp_shutdown (conn->inner_conn, shut_rx, shut_tx); 00552 } 00553 } 00554 return ERR_VAL; 00555 } 00556 00557 err_t 00558 altcp_default_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags) 00559 { 00560 if (conn && conn->inner_conn) { 00561 return altcp_write (conn->inner_conn, dataptr, len, apiflags); 00562 } 00563 return ERR_VAL; 00564 } 00565 00566 err_t 00567 altcp_default_output(struct altcp_pcb *conn) 00568 { 00569 if (conn && conn->inner_conn) { 00570 return altcp_output (conn->inner_conn); 00571 } 00572 return ERR_VAL; 00573 } 00574 00575 u16_t 00576 altcp_default_mss(struct altcp_pcb *conn) 00577 { 00578 if (conn && conn->inner_conn) { 00579 return altcp_mss (conn->inner_conn); 00580 } 00581 return 0; 00582 } 00583 00584 u16_t 00585 altcp_default_sndbuf(struct altcp_pcb *conn) 00586 { 00587 if (conn && conn->inner_conn) { 00588 return altcp_sndbuf (conn->inner_conn); 00589 } 00590 return 0; 00591 } 00592 00593 u16_t 00594 altcp_default_sndqueuelen(struct altcp_pcb *conn) 00595 { 00596 if (conn && conn->inner_conn) { 00597 return altcp_sndqueuelen (conn->inner_conn); 00598 } 00599 return 0; 00600 } 00601 00602 void 00603 altcp_default_nagle_disable(struct altcp_pcb *conn) 00604 { 00605 if (conn && conn->inner_conn) { 00606 altcp_nagle_disable(conn->inner_conn); 00607 } 00608 } 00609 00610 void 00611 altcp_default_nagle_enable(struct altcp_pcb *conn) 00612 { 00613 if (conn && conn->inner_conn) { 00614 altcp_nagle_enable(conn->inner_conn); 00615 } 00616 } 00617 00618 int 00619 altcp_default_nagle_disabled(struct altcp_pcb *conn) 00620 { 00621 if (conn && conn->inner_conn) { 00622 return altcp_nagle_disabled(conn->inner_conn); 00623 } 00624 return 0; 00625 } 00626 00627 void 00628 altcp_default_setprio(struct altcp_pcb *conn, u8_t prio) 00629 { 00630 if (conn && conn->inner_conn) { 00631 altcp_setprio (conn->inner_conn, prio); 00632 } 00633 } 00634 00635 void 00636 altcp_default_dealloc(struct altcp_pcb *conn) 00637 { 00638 LWIP_UNUSED_ARG(conn); 00639 /* nothing to do */ 00640 } 00641 00642 err_t 00643 altcp_default_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port) 00644 { 00645 if (conn && conn->inner_conn) { 00646 return altcp_get_tcp_addrinfo(conn->inner_conn, local, addr, port); 00647 } 00648 return ERR_VAL; 00649 } 00650 00651 ip_addr_t * 00652 altcp_default_get_ip(struct altcp_pcb *conn, int local) 00653 { 00654 if (conn && conn->inner_conn) { 00655 return altcp_get_ip(conn->inner_conn, local); 00656 } 00657 return NULL; 00658 } 00659 00660 u16_t 00661 altcp_default_get_port(struct altcp_pcb *conn, int local) 00662 { 00663 if (conn && conn->inner_conn) { 00664 return altcp_get_port(conn->inner_conn, local); 00665 } 00666 return 0; 00667 } 00668 00669 #ifdef LWIP_DEBUG 00670 enum tcp_state 00671 altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn) 00672 { 00673 if (conn && conn->inner_conn) { 00674 return altcp_dbg_get_tcp_state(conn->inner_conn); 00675 } 00676 return CLOSED; 00677 } 00678 #endif 00679 00680 00681 #endif /* LWIP_ALTCP */
Generated on Tue Jul 12 2022 13:54:27 by
