• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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