LCOV - code coverage report
Current view: top level - snapwebsites - tcp_client_server.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 12 0.0 %
Date: 2019-12-15 17:13:15 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // TCP Client & Server -- classes to ease handling sockets
       2             : // Copyright (c) 2012-2019  Made to Order Software Corp.  All Rights Reserved
       3             : //
       4             : // This program is free software; you can redistribute it and/or modify
       5             : // it under the terms of the GNU General Public License as published by
       6             : // the Free Software Foundation; either version 2 of the License, or
       7             : // (at your option) any later version.
       8             : //
       9             : // This program is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : // GNU General Public License for more details.
      13             : //
      14             : // You should have received a copy of the GNU General Public License
      15             : // along with this program; if not, write to the Free Software
      16             : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      17             : #pragma once
      18             : 
      19             : // make sure we use OpenSSL with multi-thread support
      20             : // (TODO: move to .cpp once we have the impl!)
      21             : #define OPENSSL_THREAD_DEFINES
      22             : 
      23             : // addr lib
      24             : //
      25             : #include "libaddr/addr.h"
      26             : 
      27             : // Qt lib
      28             : //
      29             : #include <QString>
      30             : 
      31             : // C++ lib
      32             : //
      33             : #include <stdexcept>
      34             : #include <memory>
      35             : 
      36             : // C lib
      37             : //
      38             : #include <arpa/inet.h>
      39             : 
      40             : // OpenSSL lib
      41             : //
      42             : // BIO versions of the TCP client/server
      43             : // TODO: move to an impl
      44             : #include <openssl/bio.h>
      45             : #include <openssl/err.h>
      46             : #include <openssl/ssl.h>
      47             : 
      48             : namespace tcp_client_server
      49             : {
      50             : 
      51           0 : class tcp_client_server_logic_error : public std::logic_error
      52             : {
      53             : public:
      54           0 :     tcp_client_server_logic_error(std::string const & errmsg) : logic_error(errmsg) {}
      55             : };
      56             : 
      57           0 : class tcp_client_server_runtime_error : public std::runtime_error
      58             : {
      59             : public:
      60           0 :     tcp_client_server_runtime_error(std::string const & errmsg) : runtime_error(errmsg) {}
      61             : };
      62             : 
      63           0 : class tcp_client_server_parameter_error : public tcp_client_server_logic_error
      64             : {
      65             : public:
      66           0 :     tcp_client_server_parameter_error(std::string const & errmsg) : tcp_client_server_logic_error(errmsg) {}
      67             : };
      68             : 
      69           0 : class tcp_client_server_initialization_error : public tcp_client_server_runtime_error
      70             : {
      71             : public:
      72           0 :     tcp_client_server_initialization_error(std::string const & errmsg) : tcp_client_server_runtime_error(errmsg) {}
      73             : };
      74             : 
      75           0 : class tcp_client_server_initialization_missing_error : public tcp_client_server_runtime_error
      76             : {
      77             : public:
      78           0 :     tcp_client_server_initialization_missing_error(std::string const & errmsg) : tcp_client_server_runtime_error(errmsg) {}
      79             : };
      80             : 
      81             : 
      82             : 
      83             : // TODO: assuming that bio_client with MODE_PLAIN works the same way
      84             : //       as a basic tcp_client, we should remove this class
      85             : class tcp_client
      86             : {
      87             : public:
      88             :     typedef std::shared_ptr<tcp_client>     pointer_t;
      89             : 
      90             :                         tcp_client(std::string const & addr, int port);
      91             :                         tcp_client(tcp_client const & src) = delete;
      92             :     tcp_client &        operator = (tcp_client const & rhs) = delete;
      93             :                         ~tcp_client();
      94             : 
      95             :     int                 get_socket() const;
      96             :     int                 get_port() const;
      97             :     int                 get_client_port() const;
      98             :     std::string         get_addr() const;
      99             :     std::string         get_client_addr() const;
     100             : 
     101             :     int                 read(char * buf, size_t size);
     102             :     int                 read_line(std::string & line);
     103             :     int                 write(char const * buf, size_t size);
     104             : 
     105             : private:
     106             :     int                 f_socket = -1;
     107             :     int                 f_port = -1;
     108             :     std::string         f_addr = std::string();
     109             : };
     110             : 
     111             : 
     112             : // TODO: implement a bio_server then like with the client remove
     113             : //       this basic tcp_server if it was like the bio version
     114             : class tcp_server
     115             : {
     116             : public:
     117             :     typedef std::shared_ptr<tcp_server>     pointer_t;
     118             : 
     119             :     static int const    MAX_CONNECTIONS = 50;
     120             : 
     121             :                         tcp_server(std::string const & addr, int port, int max_connections = MAX_CONNECTIONS, bool reuse_addr = false, bool auto_close = false);
     122             :                         tcp_server(tcp_server const & src) = delete;
     123             :     tcp_server &        operator = (tcp_server const & rhs) = delete;
     124             :                         ~tcp_server();
     125             : 
     126             :     int                 get_socket() const;
     127             :     int                 get_max_connections() const;
     128             :     int                 get_port() const;
     129             :     std::string         get_addr() const;
     130             :     bool                get_keepalive() const;
     131             :     void                set_keepalive(bool yes = true);
     132             : 
     133             :     int                 accept( int const max_wait_ms = -1 );
     134             :     int                 get_last_accepted_socket() const;
     135             : 
     136             : private:
     137             :     int                 f_max_connections = MAX_CONNECTIONS;
     138             :     int                 f_socket = -1;
     139             :     int                 f_port = -1;
     140             :     std::string         f_addr = std::string();
     141             :     int                 f_accepted_socket = -1;
     142             :     bool                f_keepalive = true;
     143             :     bool                f_auto_close = false;
     144             : };
     145             : 
     146             : 
     147             : class bio_server;
     148             : 
     149             : // Create/manage certificates details:
     150             : // https://help.ubuntu.com/lts/serverguide/certificates-and-security.html
     151             : class bio_client
     152             : {
     153             : public:
     154             :     typedef std::shared_ptr<bio_client>     pointer_t;
     155             : 
     156             :     enum class mode_t
     157             :     {
     158             :         MODE_PLAIN,             // avoid SSL/TLS
     159             :         MODE_SECURE,            // WARNING: may return a non-verified connection
     160             :         MODE_ALWAYS_SECURE      // fails if cannot be 100% secure
     161             :     };
     162             : 
     163           0 :     class options
     164             :     {
     165             :     public:
     166             :         typedef uint32_t            ssl_options_t;
     167             :         static int const            MAX_VERIFICATION_DEPTH = 100;
     168             :         static ssl_options_t const  DEFAULT_SSL_OPTIONS = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_COMPRESSION;
     169             : 
     170             :                             options();
     171             : 
     172             :         void                set_verification_depth(size_t depth);
     173             :         size_t              get_verification_depth() const;
     174             : 
     175             :         void                set_ssl_options(ssl_options_t ssl_options);
     176             :         ssl_options_t       get_ssl_options() const;
     177             : 
     178             :         void                set_ssl_certificate_path(std::string const path);
     179             :         std::string const & get_ssl_certificate_path() const;
     180             :         void                set_keepalive(bool keepalive = true);
     181             :         bool                get_keepalive() const;
     182             : 
     183             :         void                set_sni(bool sni = true);
     184             :         bool                get_sni() const;
     185             : 
     186             :         void                set_host(std::string const & host);
     187             :         std::string const & get_host() const;
     188             : 
     189             :     private:
     190             :         size_t              f_verification_depth = 4;
     191             :         uint32_t            f_ssl_options = DEFAULT_SSL_OPTIONS;
     192             :         std::string         f_ssl_certificate_path = std::string("/etc/ssl/certs");
     193             :         bool                f_keepalive = true;
     194             :         bool                f_sni = true;
     195             :         std::string         f_host = std::string();
     196             :     };
     197             : 
     198             :                         bio_client(std::string const & addr, int port, mode_t mode = mode_t::MODE_PLAIN, options const & opt = options());
     199             :                         bio_client(bio_client const & src) = delete;
     200             :     bio_client &        operator = (bio_client const & rhs) = delete;
     201             :                         ~bio_client();
     202             : 
     203             :     void                close();
     204             : 
     205             :     int                 get_socket() const;
     206             :     int                 get_port() const;
     207             :     int                 get_client_port() const;
     208             :     std::string         get_addr() const;
     209             :     std::string         get_client_addr() const;
     210             : 
     211             :     int                 read(char * buf, size_t size);
     212             :     int                 read_line(std::string & line);
     213             :     int                 write(char const * buf, size_t size);
     214             : 
     215             : private:
     216             :     friend bio_server;
     217             : 
     218             :                         bio_client(std::shared_ptr<BIO> bio);
     219             : 
     220             :     std::shared_ptr<SSL_CTX>    f_ssl_ctx = std::shared_ptr<SSL_CTX>();
     221             :     std::shared_ptr<BIO>        f_bio = std::shared_ptr<BIO>();
     222             : };
     223             : 
     224             : 
     225             : // try `man BIO_f_ssl` or go to:
     226             : // https://www.openssl.org/docs/manmaster/crypto/BIO_f_ssl.html
     227           0 : class bio_server
     228             : {
     229             : public:
     230             :     typedef std::shared_ptr<bio_server>     pointer_t;
     231             : 
     232             :     static int const    MAX_CONNECTIONS = 50;
     233             : 
     234             :     enum class mode_t
     235             :     {
     236             :         MODE_PLAIN,             // no encryption
     237             :         MODE_SECURE             // use TLS encryption
     238             :     };
     239             : 
     240             :                             bio_server(addr::addr const & addr_port, int max_connections, bool reuse_addr, std::string const & certificate, std::string const & private_key, mode_t mode);
     241             : 
     242             :     bool                    is_secure() const;
     243             :     int                     get_socket() const;
     244             :     bio_client::pointer_t   accept();
     245             : 
     246             : private:
     247             :     int                         f_max_connections = MAX_CONNECTIONS;
     248             :     std::shared_ptr<SSL_CTX>    f_ssl_ctx = std::shared_ptr<SSL_CTX>();
     249             :     std::shared_ptr<BIO>        f_listen = std::shared_ptr<BIO>();
     250             :     bool                        f_keepalive = true;
     251             : };
     252             : 
     253             : 
     254             : void cleanup();
     255             : void cleanup_on_thread_exit();
     256             : 
     257             : 
     258             : 
     259             : bool is_ipv4(char const * ip);
     260             : bool is_ipv6(char const * ip);
     261             : void get_addr_port(QString const & addr_port, QString & addr, int & port, char const * protocol);
     262             : 
     263             : 
     264             : } // namespace tcp_client_server
     265             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13