1 /**
2 * @file
3 * @defgroup altcp Application layered TCP Functions
4 * @ingroup altcp_api
5 *
6 * This file contains the common functions for altcp to work.
7 * For more details see @ref altcp_api.
8 */
9
10 /**
11 * @defgroup altcp_api Application layered TCP Introduction
12 * @ingroup callbackstyle_api
13 *
14 * Overview
15 * --------
16 * altcp (application layered TCP connection API; to be used from TCPIP thread)
17 * is an abstraction layer that prevents applications linking hard against the
18 * @ref tcp.h functions while providing the same functionality. It is used to
19 * e.g. add SSL/TLS (see LWIP_ALTCP_TLS) or proxy-connect support to an application
20 * written for the tcp callback API without that application knowing the
21 * protocol details.
22 *
23 * * This interface mimics the tcp callback API to the application while preventing
24 * direct linking (much like virtual functions).
25 * * This way, an application can make use of other application layer protocols
26 * on top of TCP without knowing the details (e.g. TLS, proxy connection).
27 * * This is achieved by simply including "lwip/altcp.h" instead of "lwip/tcp.h",
28 * replacing "struct tcp_pcb" with "struct altcp_pcb" and prefixing all functions
29 * with "altcp_" instead of "tcp_".
30 *
31 * With altcp support disabled (LWIP_ALTCP==0), applications written against the
32 * altcp API can still be compiled but are directly linked against the tcp.h
33 * callback API and then cannot use layered protocols. To minimize code changes
34 * in this case, the use of altcp_allocators is strongly suggested.
35 *
36 * Usage
37 * -----
38 * To make use of this API from an existing tcp raw API application:
39 * * Include "lwip/altcp.h" instead of "lwip/tcp.h"
40 * * Replace "struct tcp_pcb" with "struct altcp_pcb"
41 * * Prefix all called tcp API functions with "altcp_" instead of "tcp_" to link
42 * against the altcp functions
43 * * @ref altcp_new (and @ref altcp_new_ip_type / @ref altcp_new_ip6) take
44 * an @ref altcp_allocator_t as an argument, whereas the original tcp API
45 * functions take no arguments.
46 * * An @ref altcp_allocator_t allocator is an object that holds a pointer to an
47 * allocator object and a corresponding state (e.g. for TLS, the corresponding
48 * state may hold certificates or keys). This way, the application does not
49 * even need to know if it uses TLS or pure TCP, this is handled at runtime
50 * by passing a specific allocator.
51 * * An application can alternatively bind hard to the altcp_tls API by calling
52 * @ref altcp_tls_new or @ref altcp_tls_wrap.
53 * * The TLS layer is not directly implemented by lwIP, but a port to mbedTLS is
54 * provided.
55 * * Another altcp layer is proxy-connect to use TLS behind a HTTP proxy (see
56 * @ref altcp_proxyconnect.h)
57 *
58 * altcp_allocator_t
59 * -----------------
60 * An altcp allocator is created by the application by combining an allocator
61 * callback function and a corresponding state, e.g.:\code{.c}
62 * static const unsigned char cert[] = {0x2D, ... (see mbedTLS doc for how to create this)};
63 * struct altcp_tls_config * conf = altcp_tls_create_config_client(cert, sizeof(cert));
64 * altcp_allocator_t tls_allocator = {
65 * altcp_tls_alloc, conf
66 * };
67 * \endcode
68 *
69 *
70 * struct altcp_tls_config
71 * -----------------------
72 * The struct altcp_tls_config holds state that is needed to create new TLS client
73 * or server connections (e.g. certificates and private keys).
74 *
75 * It is not defined by lwIP itself but by the TLS port (e.g. altcp_tls to mbedTLS
76 * adaption). However, the parameters used to create it are defined in @ref
77 * altcp_tls.h (see @ref altcp_tls_create_config_server_privkey_cert for servers
78 * and @ref altcp_tls_create_config_client / @ref altcp_tls_create_config_client_2wayauth
79 * for clients).
80 *
81 * For mbedTLS, ensure that certificates can be parsed by 'mbedtls_x509_crt_parse()' and
82 * private keys can be parsed by 'mbedtls_pk_parse_key()'.
83 */
84
85 /*
86 * Copyright (c) 2017 Simon Goldschmidt
87 * All rights reserved.
88 *
89 * Redistribution and use in source and binary forms, with or without modification,
90 * are permitted provided that the following conditions are met:
91 *
92 * 1. Redistributions of source code must retain the above copyright notice,
93 * this list of conditions and the following disclaimer.
94 * 2. Redistributions in binary form must reproduce the above copyright notice,
95 * this list of conditions and the following disclaimer in the documentation
96 * and/or other materials provided with the distribution.
97 * 3. The name of the author may not be used to endorse or promote products
98 * derived from this software without specific prior written permission.
99 *
100 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
101 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
102 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
103 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
104 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
105 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
106 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
107 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
108 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
109 * OF SUCH DAMAGE.
110 *
111 * This file is part of the lwIP TCP/IP stack.
112 *
113 * Author: Simon Goldschmidt <goldsimon@gmx.de>
114 *
115 */
116
117 #include "lwip/opt.h"
118
119 #if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */
120
121 #include "lwip/altcp.h"
122 #include "lwip/priv/altcp_priv.h"
123 #include "lwip/altcp_tcp.h"
124 #include "lwip/tcp.h"
125 #include "lwip/mem.h"
126
127 #include <string.h>
128
129 extern const struct altcp_functions altcp_tcp_functions;
130
131 /**
132 * For altcp layer implementations only: allocate a new struct altcp_pcb from the pool
133 * and zero the memory
134 */
135 struct altcp_pcb *
altcp_alloc(void)136 altcp_alloc(void)
137 {
138 struct altcp_pcb *ret = (struct altcp_pcb *)memp_malloc(MEMP_ALTCP_PCB);
139 if (ret != NULL) {
140 memset(ret, 0, sizeof(struct altcp_pcb));
141 }
142 return ret;
143 }
144
145 /**
146 * For altcp layer implementations only: return a struct altcp_pcb to the pool
147 */
148 void
altcp_free(struct altcp_pcb * conn)149 altcp_free(struct altcp_pcb *conn)
150 {
151 if (conn) {
152 if (conn->fns && conn->fns->dealloc) {
153 conn->fns->dealloc(conn);
154 }
155 memp_free(MEMP_ALTCP_PCB, conn);
156 }
157 }
158
159 /**
160 * @ingroup altcp
161 * altcp_new_ip6: @ref altcp_new for IPv6
162 */
163 struct altcp_pcb *
altcp_new_ip6(altcp_allocator_t * allocator)164 altcp_new_ip6(altcp_allocator_t *allocator)
165 {
166 return altcp_new_ip_type(allocator, IPADDR_TYPE_V6);
167 }
168
169 /**
170 * @ingroup altcp
171 * altcp_new: @ref altcp_new for IPv4
172 */
173 struct altcp_pcb *
altcp_new(altcp_allocator_t * allocator)174 altcp_new(altcp_allocator_t *allocator)
175 {
176 return altcp_new_ip_type(allocator, IPADDR_TYPE_V4);
177 }
178
179 /**
180 * @ingroup altcp
181 * altcp_new_ip_type: called by applications to allocate a new pcb with the help of an
182 * allocator function.
183 *
184 * @param allocator allocator function and argument
185 * @param ip_type IP version of the pcb (@ref lwip_ip_addr_type)
186 * @return a new altcp_pcb or NULL on error
187 */
188 struct altcp_pcb *
altcp_new_ip_type(altcp_allocator_t * allocator,u8_t ip_type)189 altcp_new_ip_type(altcp_allocator_t *allocator, u8_t ip_type)
190 {
191 struct altcp_pcb *conn;
192 if (allocator == NULL) {
193 /* no allocator given, create a simple TCP connection */
194 return altcp_tcp_new_ip_type(ip_type);
195 }
196 if (allocator->alloc == NULL) {
197 /* illegal allocator */
198 return NULL;
199 }
200 conn = allocator->alloc(allocator->arg, ip_type);
201 if (conn == NULL) {
202 /* allocation failed */
203 return NULL;
204 }
205 return conn;
206 }
207
208 /**
209 * @ingroup altcp
210 * @see tcp_arg()
211 */
212 void
altcp_arg(struct altcp_pcb * conn,void * arg)213 altcp_arg(struct altcp_pcb *conn, void *arg)
214 {
215 if (conn) {
216 conn->arg = arg;
217 }
218 }
219
220 /**
221 * @ingroup altcp
222 * @see tcp_accept()
223 */
224 void
altcp_accept(struct altcp_pcb * conn,altcp_accept_fn accept)225 altcp_accept(struct altcp_pcb *conn, altcp_accept_fn accept)
226 {
227 if (conn != NULL) {
228 conn->accept = accept;
229 }
230 }
231
232 /**
233 * @ingroup altcp
234 * @see tcp_recv()
235 */
236 void
altcp_recv(struct altcp_pcb * conn,altcp_recv_fn recv)237 altcp_recv(struct altcp_pcb *conn, altcp_recv_fn recv)
238 {
239 if (conn) {
240 conn->recv = recv;
241 }
242 }
243
244 /**
245 * @ingroup altcp
246 * @see tcp_sent()
247 */
248 void
altcp_sent(struct altcp_pcb * conn,altcp_sent_fn sent)249 altcp_sent(struct altcp_pcb *conn, altcp_sent_fn sent)
250 {
251 if (conn) {
252 conn->sent = sent;
253 }
254 }
255
256 /**
257 * @ingroup altcp
258 * @see tcp_poll()
259 */
260 void
altcp_poll(struct altcp_pcb * conn,altcp_poll_fn poll,u8_t interval)261 altcp_poll(struct altcp_pcb *conn, altcp_poll_fn poll, u8_t interval)
262 {
263 if (conn) {
264 conn->poll = poll;
265 conn->pollinterval = interval;
266 if (conn->fns && conn->fns->set_poll) {
267 conn->fns->set_poll(conn, interval);
268 }
269 }
270 }
271
272 /**
273 * @ingroup altcp
274 * @see tcp_err()
275 */
276 void
altcp_err(struct altcp_pcb * conn,altcp_err_fn err)277 altcp_err(struct altcp_pcb *conn, altcp_err_fn err)
278 {
279 if (conn) {
280 conn->err = err;
281 }
282 }
283
284 /* Generic functions calling the "virtual" ones */
285
286 /**
287 * @ingroup altcp
288 * @see tcp_recved()
289 */
290 void
altcp_recved(struct altcp_pcb * conn,u16_t len)291 altcp_recved(struct altcp_pcb *conn, u16_t len)
292 {
293 if (conn && conn->fns && conn->fns->recved) {
294 conn->fns->recved(conn, len);
295 }
296 }
297
298 /**
299 * @ingroup altcp
300 * @see tcp_bind()
301 */
302 err_t
altcp_bind(struct altcp_pcb * conn,const ip_addr_t * ipaddr,u16_t port)303 altcp_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port)
304 {
305 if (conn && conn->fns && conn->fns->bind) {
306 return conn->fns->bind(conn, ipaddr, port);
307 }
308 return ERR_VAL;
309 }
310
311 /**
312 * @ingroup altcp
313 * @see tcp_connect()
314 */
315 err_t
altcp_connect(struct altcp_pcb * conn,const ip_addr_t * ipaddr,u16_t port,altcp_connected_fn connected)316 altcp_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
317 {
318 if (conn && conn->fns && conn->fns->connect) {
319 return conn->fns->connect(conn, ipaddr, port, connected);
320 }
321 return ERR_VAL;
322 }
323
324 /**
325 * @ingroup altcp
326 * @see tcp_listen_with_backlog_and_err()
327 */
328 struct altcp_pcb *
altcp_listen_with_backlog_and_err(struct altcp_pcb * conn,u8_t backlog,err_t * err)329 altcp_listen_with_backlog_and_err(struct altcp_pcb *conn, u8_t backlog, err_t *err)
330 {
331 if (conn && conn->fns && conn->fns->listen) {
332 return conn->fns->listen(conn, backlog, err);
333 }
334 return NULL;
335 }
336
337 /**
338 * @ingroup altcp
339 * @see tcp_abort()
340 */
341 void
altcp_abort(struct altcp_pcb * conn)342 altcp_abort(struct altcp_pcb *conn)
343 {
344 if (conn && conn->fns && conn->fns->abort) {
345 conn->fns->abort(conn);
346 }
347 }
348
349 /**
350 * @ingroup altcp
351 * @see tcp_close()
352 */
353 err_t
altcp_close(struct altcp_pcb * conn)354 altcp_close(struct altcp_pcb *conn)
355 {
356 if (conn && conn->fns && conn->fns->close) {
357 return conn->fns->close(conn);
358 }
359 return ERR_VAL;
360 }
361
362 /**
363 * @ingroup altcp
364 * @see tcp_shutdown()
365 */
366 err_t
altcp_shutdown(struct altcp_pcb * conn,int shut_rx,int shut_tx)367 altcp_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx)
368 {
369 if (conn && conn->fns && conn->fns->shutdown) {
370 return conn->fns->shutdown(conn, shut_rx, shut_tx);
371 }
372 return ERR_VAL;
373 }
374
375 /**
376 * @ingroup altcp
377 * @see tcp_write()
378 */
379 err_t
altcp_write(struct altcp_pcb * conn,const void * dataptr,u16_t len,u8_t apiflags)380 altcp_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
381 {
382 if (conn && conn->fns && conn->fns->write) {
383 return conn->fns->write(conn, dataptr, len, apiflags);
384 }
385 return ERR_VAL;
386 }
387
388 /**
389 * @ingroup altcp
390 * @see tcp_output()
391 */
392 err_t
altcp_output(struct altcp_pcb * conn)393 altcp_output(struct altcp_pcb *conn)
394 {
395 if (conn && conn->fns && conn->fns->output) {
396 return conn->fns->output(conn);
397 }
398 return ERR_VAL;
399 }
400
401 /**
402 * @ingroup altcp
403 * @see tcp_mss()
404 */
405 u16_t
altcp_mss(struct altcp_pcb * conn)406 altcp_mss(struct altcp_pcb *conn)
407 {
408 if (conn && conn->fns && conn->fns->mss) {
409 return conn->fns->mss(conn);
410 }
411 return 0;
412 }
413
414 /**
415 * @ingroup altcp
416 * @see tcp_sndbuf()
417 */
418 u16_t
altcp_sndbuf(struct altcp_pcb * conn)419 altcp_sndbuf(struct altcp_pcb *conn)
420 {
421 if (conn && conn->fns && conn->fns->sndbuf) {
422 return conn->fns->sndbuf(conn);
423 }
424 return 0;
425 }
426
427 /**
428 * @ingroup altcp
429 * @see tcp_sndqueuelen()
430 */
431 u16_t
altcp_sndqueuelen(struct altcp_pcb * conn)432 altcp_sndqueuelen(struct altcp_pcb *conn)
433 {
434 if (conn && conn->fns && conn->fns->sndqueuelen) {
435 return conn->fns->sndqueuelen(conn);
436 }
437 return 0;
438 }
439
440 void
altcp_nagle_disable(struct altcp_pcb * conn)441 altcp_nagle_disable(struct altcp_pcb *conn)
442 {
443 if (conn && conn->fns && conn->fns->nagle_disable) {
444 conn->fns->nagle_disable(conn);
445 }
446 }
447
448 void
altcp_nagle_enable(struct altcp_pcb * conn)449 altcp_nagle_enable(struct altcp_pcb *conn)
450 {
451 if (conn && conn->fns && conn->fns->nagle_enable) {
452 conn->fns->nagle_enable(conn);
453 }
454 }
455
456 int
altcp_nagle_disabled(struct altcp_pcb * conn)457 altcp_nagle_disabled(struct altcp_pcb *conn)
458 {
459 if (conn && conn->fns && conn->fns->nagle_disabled) {
460 return conn->fns->nagle_disabled(conn);
461 }
462 return 0;
463 }
464
465 /**
466 * @ingroup altcp
467 * @see tcp_setprio()
468 */
469 void
altcp_setprio(struct altcp_pcb * conn,u8_t prio)470 altcp_setprio(struct altcp_pcb *conn, u8_t prio)
471 {
472 if (conn && conn->fns && conn->fns->setprio) {
473 conn->fns->setprio(conn, prio);
474 }
475 }
476
477 err_t
altcp_get_tcp_addrinfo(struct altcp_pcb * conn,int local,ip_addr_t * addr,u16_t * port)478 altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port)
479 {
480 if (conn && conn->fns && conn->fns->addrinfo) {
481 return conn->fns->addrinfo(conn, local, addr, port);
482 }
483 return ERR_VAL;
484 }
485
486 ip_addr_t *
altcp_get_ip(struct altcp_pcb * conn,int local)487 altcp_get_ip(struct altcp_pcb *conn, int local)
488 {
489 if (conn && conn->fns && conn->fns->getip) {
490 return conn->fns->getip(conn, local);
491 }
492 return NULL;
493 }
494
495 u16_t
altcp_get_port(struct altcp_pcb * conn,int local)496 altcp_get_port(struct altcp_pcb *conn, int local)
497 {
498 if (conn && conn->fns && conn->fns->getport) {
499 return conn->fns->getport(conn, local);
500 }
501 return 0;
502 }
503
504 #if LWIP_TCP_KEEPALIVE
505 void
altcp_keepalive_disable(struct altcp_pcb * conn)506 altcp_keepalive_disable(struct altcp_pcb *conn)
507 {
508 if (conn && conn->fns && conn->fns->keepalive_disable) {
509 conn->fns->keepalive_disable(conn);
510 }
511 }
512
513 void
altcp_keepalive_enable(struct altcp_pcb * conn,u32_t idle,u32_t intvl,u32_t count)514 altcp_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count)
515 {
516 if (conn && conn->fns && conn->fns->keepalive_enable) {
517 conn->fns->keepalive_enable(conn, idle, intvl, count);
518 }
519 }
520 #endif
521
522 #ifdef LWIP_DEBUG
523 enum tcp_state
altcp_dbg_get_tcp_state(struct altcp_pcb * conn)524 altcp_dbg_get_tcp_state(struct altcp_pcb *conn)
525 {
526 if (conn && conn->fns && conn->fns->dbg_get_tcp_state) {
527 return conn->fns->dbg_get_tcp_state(conn);
528 }
529 return CLOSED;
530 }
531 #endif
532
533 /* Default implementations for the "virtual" functions */
534
535 void
altcp_default_set_poll(struct altcp_pcb * conn,u8_t interval)536 altcp_default_set_poll(struct altcp_pcb *conn, u8_t interval)
537 {
538 if (conn && conn->inner_conn) {
539 altcp_poll(conn->inner_conn, conn->poll, interval);
540 }
541 }
542
543 void
altcp_default_recved(struct altcp_pcb * conn,u16_t len)544 altcp_default_recved(struct altcp_pcb *conn, u16_t len)
545 {
546 if (conn && conn->inner_conn) {
547 altcp_recved(conn->inner_conn, len);
548 }
549 }
550
551 err_t
altcp_default_bind(struct altcp_pcb * conn,const ip_addr_t * ipaddr,u16_t port)552 altcp_default_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port)
553 {
554 if (conn && conn->inner_conn) {
555 return altcp_bind(conn->inner_conn, ipaddr, port);
556 }
557 return ERR_VAL;
558 }
559
560 err_t
altcp_default_shutdown(struct altcp_pcb * conn,int shut_rx,int shut_tx)561 altcp_default_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx)
562 {
563 if (conn) {
564 if (shut_rx && shut_tx && conn->fns && conn->fns->close) {
565 /* default shutdown for both sides is close */
566 return conn->fns->close(conn);
567 }
568 if (conn->inner_conn) {
569 return altcp_shutdown(conn->inner_conn, shut_rx, shut_tx);
570 }
571 }
572 return ERR_VAL;
573 }
574
575 err_t
altcp_default_write(struct altcp_pcb * conn,const void * dataptr,u16_t len,u8_t apiflags)576 altcp_default_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
577 {
578 if (conn && conn->inner_conn) {
579 return altcp_write(conn->inner_conn, dataptr, len, apiflags);
580 }
581 return ERR_VAL;
582 }
583
584 err_t
altcp_default_output(struct altcp_pcb * conn)585 altcp_default_output(struct altcp_pcb *conn)
586 {
587 if (conn && conn->inner_conn) {
588 return altcp_output(conn->inner_conn);
589 }
590 return ERR_VAL;
591 }
592
593 u16_t
altcp_default_mss(struct altcp_pcb * conn)594 altcp_default_mss(struct altcp_pcb *conn)
595 {
596 if (conn && conn->inner_conn) {
597 return altcp_mss(conn->inner_conn);
598 }
599 return 0;
600 }
601
602 u16_t
altcp_default_sndbuf(struct altcp_pcb * conn)603 altcp_default_sndbuf(struct altcp_pcb *conn)
604 {
605 if (conn && conn->inner_conn) {
606 return altcp_sndbuf(conn->inner_conn);
607 }
608 return 0;
609 }
610
611 u16_t
altcp_default_sndqueuelen(struct altcp_pcb * conn)612 altcp_default_sndqueuelen(struct altcp_pcb *conn)
613 {
614 if (conn && conn->inner_conn) {
615 return altcp_sndqueuelen(conn->inner_conn);
616 }
617 return 0;
618 }
619
620 void
altcp_default_nagle_disable(struct altcp_pcb * conn)621 altcp_default_nagle_disable(struct altcp_pcb *conn)
622 {
623 if (conn && conn->inner_conn) {
624 altcp_nagle_disable(conn->inner_conn);
625 }
626 }
627
628 void
altcp_default_nagle_enable(struct altcp_pcb * conn)629 altcp_default_nagle_enable(struct altcp_pcb *conn)
630 {
631 if (conn && conn->inner_conn) {
632 altcp_nagle_enable(conn->inner_conn);
633 }
634 }
635
636 int
altcp_default_nagle_disabled(struct altcp_pcb * conn)637 altcp_default_nagle_disabled(struct altcp_pcb *conn)
638 {
639 if (conn && conn->inner_conn) {
640 return altcp_nagle_disabled(conn->inner_conn);
641 }
642 return 0;
643 }
644
645 void
altcp_default_setprio(struct altcp_pcb * conn,u8_t prio)646 altcp_default_setprio(struct altcp_pcb *conn, u8_t prio)
647 {
648 if (conn && conn->inner_conn) {
649 altcp_setprio(conn->inner_conn, prio);
650 }
651 }
652
653 void
altcp_default_dealloc(struct altcp_pcb * conn)654 altcp_default_dealloc(struct altcp_pcb *conn)
655 {
656 LWIP_UNUSED_ARG(conn);
657 /* nothing to do */
658 }
659
660 err_t
altcp_default_get_tcp_addrinfo(struct altcp_pcb * conn,int local,ip_addr_t * addr,u16_t * port)661 altcp_default_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port)
662 {
663 if (conn && conn->inner_conn) {
664 return altcp_get_tcp_addrinfo(conn->inner_conn, local, addr, port);
665 }
666 return ERR_VAL;
667 }
668
669 ip_addr_t *
altcp_default_get_ip(struct altcp_pcb * conn,int local)670 altcp_default_get_ip(struct altcp_pcb *conn, int local)
671 {
672 if (conn && conn->inner_conn) {
673 return altcp_get_ip(conn->inner_conn, local);
674 }
675 return NULL;
676 }
677
678 u16_t
altcp_default_get_port(struct altcp_pcb * conn,int local)679 altcp_default_get_port(struct altcp_pcb *conn, int local)
680 {
681 if (conn && conn->inner_conn) {
682 return altcp_get_port(conn->inner_conn, local);
683 }
684 return 0;
685 }
686
687 #if LWIP_TCP_KEEPALIVE
688 void
altcp_default_keepalive_disable(struct altcp_pcb * conn)689 altcp_default_keepalive_disable(struct altcp_pcb *conn)
690 {
691 if (conn && conn->inner_conn) {
692 altcp_keepalive_disable(conn->inner_conn);
693 }
694 }
695
696 void
altcp_default_keepalive_enable(struct altcp_pcb * conn,u32_t idle,u32_t intvl,u32_t count)697 altcp_default_keepalive_enable(struct altcp_pcb *conn, u32_t idle, u32_t intvl, u32_t count)
698 {
699 if (conn && conn->inner_conn) {
700 altcp_keepalive_enable(conn->inner_conn, idle, intvl, count);
701 }
702 }
703 #endif
704
705 #ifdef LWIP_DEBUG
706 enum tcp_state
altcp_default_dbg_get_tcp_state(struct altcp_pcb * conn)707 altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn)
708 {
709 if (conn && conn->inner_conn) {
710 return altcp_dbg_get_tcp_state(conn->inner_conn);
711 }
712 return CLOSED;
713 }
714 #endif
715
716
717 #endif /* LWIP_ALTCP */
718