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_tcp.c
00001 /** 00002 * @file 00003 * Application layered TCP connection API (to be used from TCPIP thread)\n 00004 * This interface mimics the tcp callback API to the application while preventing 00005 * direct linking (much like virtual functions). 00006 * This way, an application can make use of other application layer protocols 00007 * on top of TCP without knowing the details (e.g. TLS, proxy connection). 00008 * 00009 * This file contains the base implementation calling into tcp. 00010 */ 00011 00012 /* 00013 * Copyright (c) 2017 Simon Goldschmidt 00014 * All rights reserved. 00015 * 00016 * Redistribution and use in source and binary forms, with or without modification, 00017 * are permitted provided that the following conditions are met: 00018 * 00019 * 1. Redistributions of source code must retain the above copyright notice, 00020 * this list of conditions and the following disclaimer. 00021 * 2. Redistributions in binary form must reproduce the above copyright notice, 00022 * this list of conditions and the following disclaimer in the documentation 00023 * and/or other materials provided with the distribution. 00024 * 3. The name of the author may not be used to endorse or promote products 00025 * derived from this software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00028 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00029 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00030 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00032 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00033 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00034 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00035 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00036 * OF SUCH DAMAGE. 00037 * 00038 * This file is part of the lwIP TCP/IP stack. 00039 * 00040 * Author: Simon Goldschmidt <goldsimon@gmx.de> 00041 * 00042 */ 00043 00044 #include "lwip/opt.h" 00045 00046 #if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ 00047 00048 #include "lwip/altcp.h" 00049 #include "lwip/altcp_tcp.h" 00050 #include "lwip/priv/altcp_priv.h" 00051 #include "lwip/tcp.h" 00052 #include "lwip/mem.h" 00053 00054 #include <string.h> 00055 00056 #define ALTCP_TCP_ASSERT_CONN(conn) do { \ 00057 LWIP_ASSERT("conn->inner_conn == NULL", (conn)->inner_conn == NULL); \ 00058 LWIP_UNUSED_ARG(conn); /* for LWIP_NOASSERT */ } while(0) 00059 #define ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb) do { \ 00060 LWIP_ASSERT("pcb mismatch", (conn)->state == tpcb); \ 00061 LWIP_UNUSED_ARG(tpcb); /* for LWIP_NOASSERT */ \ 00062 ALTCP_TCP_ASSERT_CONN(conn); } while(0) 00063 00064 00065 /* Variable prototype, the actual declaration is at the end of this file 00066 since it contains pointers to static functions declared here */ 00067 extern const struct altcp_functions altcp_tcp_functions; 00068 00069 static void altcp_tcp_setup(struct altcp_pcb *conn, struct tcp_pcb *tpcb); 00070 00071 /* callback functions for TCP */ 00072 static err_t 00073 altcp_tcp_accept(void *arg, struct tcp_pcb *new_tpcb, err_t err) 00074 { 00075 struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg; 00076 if (listen_conn && listen_conn->accept) { 00077 /* create a new altcp_conn to pass to the next 'accept' callback */ 00078 struct altcp_pcb *new_conn = altcp_alloc(); 00079 if (new_conn == NULL) { 00080 return ERR_MEM; 00081 } 00082 altcp_tcp_setup(new_conn, new_tpcb); 00083 return listen_conn->accept(listen_conn->arg, new_conn, err); 00084 } 00085 return ERR_ARG; 00086 } 00087 00088 static err_t 00089 altcp_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) 00090 { 00091 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00092 if (conn) { 00093 ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb); 00094 if (conn->connected) { 00095 return conn->connected(conn->arg, conn, err); 00096 } 00097 } 00098 return ERR_OK; 00099 } 00100 00101 static err_t 00102 altcp_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) 00103 { 00104 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00105 if (conn) { 00106 ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb); 00107 if (conn->recv) { 00108 return conn->recv(conn->arg, conn, p, err); 00109 } 00110 } 00111 if (p != NULL) { 00112 /* prevent memory leaks */ 00113 pbuf_free(p); 00114 } 00115 return ERR_OK; 00116 } 00117 00118 static err_t 00119 altcp_tcp_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) 00120 { 00121 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00122 if (conn) { 00123 ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb); 00124 if (conn->sent) { 00125 return conn->sent(conn->arg, conn, len); 00126 } 00127 } 00128 return ERR_OK; 00129 } 00130 00131 static err_t 00132 altcp_tcp_poll(void *arg, struct tcp_pcb *tpcb) 00133 { 00134 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00135 if (conn) { 00136 ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb); 00137 if (conn->poll) { 00138 return conn->poll(conn->arg, conn); 00139 } 00140 } 00141 return ERR_OK; 00142 } 00143 00144 static void 00145 altcp_tcp_err(void *arg, err_t err) 00146 { 00147 struct altcp_pcb *conn = (struct altcp_pcb *)arg; 00148 if (conn) { 00149 conn->state = NULL; /* already freed */ 00150 if (conn->err) { 00151 conn->err(conn->arg, err); 00152 } 00153 altcp_free(conn); 00154 } 00155 } 00156 00157 /* setup functions */ 00158 00159 static void 00160 altcp_tcp_remove_callbacks(struct tcp_pcb *tpcb) 00161 { 00162 tcp_arg(tpcb, NULL); 00163 tcp_recv(tpcb, NULL); 00164 tcp_sent(tpcb, NULL); 00165 tcp_err(tpcb, NULL); 00166 tcp_poll(tpcb, NULL, tpcb->pollinterval); 00167 } 00168 00169 static void 00170 altcp_tcp_setup_callbacks(struct altcp_pcb *conn, struct tcp_pcb *tpcb) 00171 { 00172 tcp_arg(tpcb, conn); 00173 tcp_recv(tpcb, altcp_tcp_recv); 00174 tcp_sent(tpcb, altcp_tcp_sent); 00175 tcp_err(tpcb, altcp_tcp_err); 00176 /* tcp_poll is set when interval is set by application */ 00177 /* listen is set totally different :-) */ 00178 } 00179 00180 static void 00181 altcp_tcp_setup(struct altcp_pcb *conn, struct tcp_pcb *tpcb) 00182 { 00183 altcp_tcp_setup_callbacks(conn, tpcb); 00184 conn->state = tpcb; 00185 conn->fns = &altcp_tcp_functions; 00186 } 00187 00188 struct altcp_pcb * 00189 altcp_tcp_new_ip_type(u8_t ip_type) 00190 { 00191 /* Allocate the tcp pcb first to invoke the priority handling code 00192 if we're out of pcbs */ 00193 struct tcp_pcb *tpcb = tcp_new_ip_type(ip_type); 00194 if (tpcb != NULL) { 00195 struct altcp_pcb *ret = altcp_alloc(); 00196 if (ret != NULL) { 00197 altcp_tcp_setup(ret, tpcb); 00198 return ret; 00199 } else { 00200 /* altcp_pcb allocation failed -> free the tcp_pcb too */ 00201 tcp_close(tpcb); 00202 } 00203 } 00204 return NULL; 00205 } 00206 00207 /** altcp_tcp allocator function fitting to @ref altcp_allocator_t / @ref altcp_new. 00208 * 00209 * arg pointer is not used for TCP. 00210 */ 00211 struct altcp_pcb * 00212 altcp_tcp_alloc(void *arg, u8_t ip_type) 00213 { 00214 LWIP_UNUSED_ARG(arg); 00215 return altcp_tcp_new_ip_type(ip_type); 00216 } 00217 00218 struct altcp_pcb * 00219 altcp_tcp_wrap(struct tcp_pcb *tpcb) 00220 { 00221 if (tpcb != NULL) { 00222 struct altcp_pcb *ret = altcp_alloc(); 00223 if (ret != NULL) { 00224 altcp_tcp_setup(ret, tpcb); 00225 return ret; 00226 } 00227 } 00228 return NULL; 00229 } 00230 00231 00232 /* "virtual" functions calling into tcp */ 00233 static void 00234 altcp_tcp_set_poll(struct altcp_pcb *conn, u8_t interval) 00235 { 00236 if (conn != NULL) { 00237 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00238 ALTCP_TCP_ASSERT_CONN(conn); 00239 tcp_poll(pcb, altcp_tcp_poll, interval); 00240 } 00241 } 00242 00243 static void 00244 altcp_tcp_recved(struct altcp_pcb *conn, u16_t len) 00245 { 00246 if (conn != NULL) { 00247 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00248 ALTCP_TCP_ASSERT_CONN(conn); 00249 tcp_recved(pcb, len); 00250 } 00251 } 00252 00253 static err_t 00254 altcp_tcp_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port) 00255 { 00256 struct tcp_pcb *pcb; 00257 if (conn == NULL) { 00258 return ERR_VAL; 00259 } 00260 ALTCP_TCP_ASSERT_CONN(conn); 00261 pcb = (struct tcp_pcb *)conn->state; 00262 return tcp_bind(pcb, ipaddr, port); 00263 } 00264 00265 static err_t 00266 altcp_tcp_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected) 00267 { 00268 struct tcp_pcb *pcb; 00269 if (conn == NULL) { 00270 return ERR_VAL; 00271 } 00272 ALTCP_TCP_ASSERT_CONN(conn); 00273 conn->connected = connected; 00274 pcb = (struct tcp_pcb *)conn->state; 00275 return tcp_connect(pcb, ipaddr, port, altcp_tcp_connected); 00276 } 00277 00278 static struct altcp_pcb * 00279 altcp_tcp_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err) 00280 { 00281 struct tcp_pcb *pcb; 00282 struct tcp_pcb *lpcb; 00283 if (conn == NULL) { 00284 return NULL; 00285 } 00286 ALTCP_TCP_ASSERT_CONN(conn); 00287 pcb = (struct tcp_pcb *)conn->state; 00288 lpcb = tcp_listen_with_backlog_and_err(pcb, backlog, err); 00289 if (lpcb != NULL) { 00290 conn->state = lpcb; 00291 tcp_accept(lpcb, altcp_tcp_accept); 00292 return conn; 00293 } 00294 return NULL; 00295 } 00296 00297 static void 00298 altcp_tcp_abort(struct altcp_pcb *conn) 00299 { 00300 if (conn != NULL) { 00301 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00302 ALTCP_TCP_ASSERT_CONN(conn); 00303 if (pcb) { 00304 tcp_abort(pcb); 00305 } 00306 } 00307 } 00308 00309 static err_t 00310 altcp_tcp_close(struct altcp_pcb *conn) 00311 { 00312 struct tcp_pcb *pcb; 00313 if (conn == NULL) { 00314 return ERR_VAL; 00315 } 00316 ALTCP_TCP_ASSERT_CONN(conn); 00317 pcb = (struct tcp_pcb *)conn->state; 00318 if (pcb) { 00319 err_t err; 00320 tcp_poll_fn oldpoll = pcb->poll; 00321 altcp_tcp_remove_callbacks(pcb); 00322 err = tcp_close(pcb); 00323 if (err != ERR_OK) { 00324 /* not closed, set up all callbacks again */ 00325 altcp_tcp_setup_callbacks(conn, pcb); 00326 /* poll callback is not included in the above */ 00327 tcp_poll(pcb, oldpoll, pcb->pollinterval); 00328 return err; 00329 } 00330 conn->state = NULL; /* unsafe to reference pcb after tcp_close(). */ 00331 } 00332 altcp_free(conn); 00333 return ERR_OK; 00334 } 00335 00336 static err_t 00337 altcp_tcp_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx) 00338 { 00339 struct tcp_pcb *pcb; 00340 if (conn == NULL) { 00341 return ERR_VAL; 00342 } 00343 ALTCP_TCP_ASSERT_CONN(conn); 00344 pcb = (struct tcp_pcb *)conn->state; 00345 return tcp_shutdown(pcb, shut_rx, shut_tx); 00346 } 00347 00348 static err_t 00349 altcp_tcp_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags) 00350 { 00351 struct tcp_pcb *pcb; 00352 if (conn == NULL) { 00353 return ERR_VAL; 00354 } 00355 ALTCP_TCP_ASSERT_CONN(conn); 00356 pcb = (struct tcp_pcb *)conn->state; 00357 return tcp_write(pcb, dataptr, len, apiflags); 00358 } 00359 00360 static err_t 00361 altcp_tcp_output(struct altcp_pcb *conn) 00362 { 00363 struct tcp_pcb *pcb; 00364 if (conn == NULL) { 00365 return ERR_VAL; 00366 } 00367 ALTCP_TCP_ASSERT_CONN(conn); 00368 pcb = (struct tcp_pcb *)conn->state; 00369 return tcp_output(pcb); 00370 } 00371 00372 static u16_t 00373 altcp_tcp_mss(struct altcp_pcb *conn) 00374 { 00375 struct tcp_pcb *pcb; 00376 if (conn == NULL) { 00377 return 0; 00378 } 00379 ALTCP_TCP_ASSERT_CONN(conn); 00380 pcb = (struct tcp_pcb *)conn->state; 00381 return tcp_mss(pcb); 00382 } 00383 00384 static u16_t 00385 altcp_tcp_sndbuf(struct altcp_pcb *conn) 00386 { 00387 struct tcp_pcb *pcb; 00388 if (conn == NULL) { 00389 return 0; 00390 } 00391 ALTCP_TCP_ASSERT_CONN(conn); 00392 pcb = (struct tcp_pcb *)conn->state; 00393 return tcp_sndbuf(pcb); 00394 } 00395 00396 static u16_t 00397 altcp_tcp_sndqueuelen(struct altcp_pcb *conn) 00398 { 00399 struct tcp_pcb *pcb; 00400 if (conn == NULL) { 00401 return 0; 00402 } 00403 ALTCP_TCP_ASSERT_CONN(conn); 00404 pcb = (struct tcp_pcb *)conn->state; 00405 return tcp_sndqueuelen(pcb); 00406 } 00407 00408 static void 00409 altcp_tcp_nagle_disable(struct altcp_pcb *conn) 00410 { 00411 if (conn && conn->state) { 00412 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00413 ALTCP_TCP_ASSERT_CONN(conn); 00414 tcp_nagle_disable(pcb); 00415 } 00416 } 00417 00418 static void 00419 altcp_tcp_nagle_enable(struct altcp_pcb *conn) 00420 { 00421 if (conn && conn->state) { 00422 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00423 ALTCP_TCP_ASSERT_CONN(conn); 00424 tcp_nagle_enable(pcb); 00425 } 00426 } 00427 00428 static int 00429 altcp_tcp_nagle_disabled(struct altcp_pcb *conn) 00430 { 00431 if (conn && conn->state) { 00432 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00433 ALTCP_TCP_ASSERT_CONN(conn); 00434 return tcp_nagle_disabled(pcb); 00435 } 00436 return 0; 00437 } 00438 00439 static void 00440 altcp_tcp_setprio(struct altcp_pcb *conn, u8_t prio) 00441 { 00442 if (conn != NULL) { 00443 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00444 ALTCP_TCP_ASSERT_CONN(conn); 00445 tcp_setprio(pcb, prio); 00446 } 00447 } 00448 00449 static void 00450 altcp_tcp_dealloc(struct altcp_pcb *conn) 00451 { 00452 LWIP_UNUSED_ARG(conn); 00453 ALTCP_TCP_ASSERT_CONN(conn); 00454 /* no private state to clean up */ 00455 } 00456 00457 static err_t 00458 altcp_tcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port) 00459 { 00460 if (conn) { 00461 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00462 ALTCP_TCP_ASSERT_CONN(conn); 00463 return tcp_tcp_get_tcp_addrinfo(pcb, local, addr, port); 00464 } 00465 return ERR_VAL; 00466 } 00467 00468 static ip_addr_t * 00469 altcp_tcp_get_ip(struct altcp_pcb *conn, int local) 00470 { 00471 if (conn) { 00472 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00473 ALTCP_TCP_ASSERT_CONN(conn); 00474 if (pcb) { 00475 if (local) { 00476 return &pcb->local_ip; 00477 } else { 00478 return &pcb->remote_ip; 00479 } 00480 } 00481 } 00482 return NULL; 00483 } 00484 00485 static u16_t 00486 altcp_tcp_get_port(struct altcp_pcb *conn, int local) 00487 { 00488 if (conn) { 00489 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00490 ALTCP_TCP_ASSERT_CONN(conn); 00491 if (pcb) { 00492 if (local) { 00493 return pcb->local_port; 00494 } else { 00495 return pcb->remote_port; 00496 } 00497 } 00498 } 00499 return 0; 00500 } 00501 00502 #ifdef LWIP_DEBUG 00503 static enum tcp_state 00504 altcp_tcp_dbg_get_tcp_state(struct altcp_pcb *conn) 00505 { 00506 if (conn) { 00507 struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; 00508 ALTCP_TCP_ASSERT_CONN(conn); 00509 if (pcb) { 00510 return pcb->state; 00511 } 00512 } 00513 return CLOSED; 00514 } 00515 #endif 00516 const struct altcp_functions altcp_tcp_functions = { 00517 altcp_tcp_set_poll, 00518 altcp_tcp_recved, 00519 altcp_tcp_bind, 00520 altcp_tcp_connect, 00521 altcp_tcp_listen, 00522 altcp_tcp_abort, 00523 altcp_tcp_close, 00524 altcp_tcp_shutdown, 00525 altcp_tcp_write, 00526 altcp_tcp_output, 00527 altcp_tcp_mss, 00528 altcp_tcp_sndbuf, 00529 altcp_tcp_sndqueuelen, 00530 altcp_tcp_nagle_disable, 00531 altcp_tcp_nagle_enable, 00532 altcp_tcp_nagle_disabled, 00533 altcp_tcp_setprio, 00534 altcp_tcp_dealloc, 00535 altcp_tcp_get_tcp_addrinfo, 00536 altcp_tcp_get_ip, 00537 altcp_tcp_get_port 00538 #ifdef LWIP_DEBUG 00539 , altcp_tcp_dbg_get_tcp_state 00540 #endif 00541 }; 00542 00543 #endif /* LWIP_ALTCP */
Generated on Tue Jul 12 2022 13:54:27 by
