Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_altcp.c Source File

lwip_altcp.c

Go to the documentation of this file.
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 */