245 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
| /*
 | |
|    Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or modify
 | |
|    it under the terms of the GNU General Public License, version 2.0,
 | |
|    as published by the Free Software Foundation.
 | |
| 
 | |
|    This program is also distributed with certain software (including
 | |
|    but not limited to OpenSSL) that is licensed under separate terms,
 | |
|    as designated in a particular file or component or in included license
 | |
|    documentation.  The authors of MySQL hereby grant you an additional
 | |
|    permission to link the program and your derivative works with the
 | |
|    separately licensed software that they have included with MySQL.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License, version 2.0, for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
 | |
| */
 | |
| 
 | |
| #ifndef SOCKET_CONNECTION_INCLUDED
 | |
| #define SOCKET_CONNECTION_INCLUDED
 | |
| 
 | |
| #include "my_config.h"
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <list>
 | |
| #include <map>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include "my_psi_config.h"
 | |
| #include "mysql/components/services/psi_statement_bits.h"
 | |
| #include "mysql/psi/mysql_socket.h"  // MYSQL_SOCKET
 | |
| #ifdef HAVE_POLL_H
 | |
| #include <poll.h>
 | |
| #endif
 | |
| 
 | |
| class Channel_info;
 | |
| 
 | |
| extern const char *MY_BIND_ALL_ADDRESSES;
 | |
| extern const char *ipv4_all_addresses;
 | |
| extern const char *ipv6_all_addresses;
 | |
| 
 | |
| #ifdef HAVE_PSI_STATEMENT_INTERFACE
 | |
| extern PSI_statement_info stmt_info_new_packet;
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|   Key Comparator for socket_map_t used in Mysqld_socket_listener
 | |
| */
 | |
| struct Socket_lt_type {
 | |
|   bool operator()(const MYSQL_SOCKET &s1, const MYSQL_SOCKET &s2) const {
 | |
|     return mysql_socket_getfd(s1) < mysql_socket_getfd(s2);
 | |
|   }
 | |
| };
 | |
| 
 | |
| // Enum denoting type of socket whether unix socket or tcp socket.
 | |
| enum class Socket_type { UNIX_SOCKET, TCP_SOCKET };
 | |
| // Listen socket attributes.
 | |
| struct Socket_attr {
 | |
|   explicit Socket_attr(Socket_type socket_type) : m_socket_type(socket_type) {}
 | |
|   Socket_attr(Socket_type socket_type, const std::string &network_namespace)
 | |
|       : m_socket_type(socket_type), m_network_namespace(network_namespace) {}
 | |
|   Socket_type m_socket_type;
 | |
|   std::string m_network_namespace;
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Typedef representing socket map type which hold the sockets and a
 | |
|   corresponding bool which is true if it is unix socket and false for tcp
 | |
|   socket.
 | |
| */
 | |
| typedef std::map<MYSQL_SOCKET, Socket_attr, Socket_lt_type> socket_map_t;
 | |
| 
 | |
| // iterator type for socket map type.
 | |
| typedef std::map<MYSQL_SOCKET, Socket_attr, Socket_lt_type>::const_iterator
 | |
|     socket_map_const_iterator_t;
 | |
| 
 | |
| /**
 | |
|   Plain structure to collect together a host name/ip address and
 | |
|   a corresponding network namespace if set and pass these information
 | |
|   to different functions as a single unit.
 | |
| */
 | |
| struct Bind_address_info {
 | |
|   std::string address, network_namespace;
 | |
|   Bind_address_info() = default;
 | |
| 
 | |
|   explicit Bind_address_info(const std::string &addr) : address(addr) {}
 | |
| 
 | |
|   Bind_address_info(const std::string &addr, const std::string &nspace)
 | |
|       : address(addr), network_namespace(nspace) {}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   This class represents the Mysqld_socket_listener which prepare the
 | |
|   listener sockets to recieve connection events from the client. The
 | |
|   Mysqld_socket_listener may be composed of either or both a tcp socket
 | |
|   which listen on a default mysqld tcp port or a user specified  port
 | |
|   via mysqld command-line  and a unix socket which is bind to a mysqld
 | |
|   defaul pathname.
 | |
| */
 | |
| class Mysqld_socket_listener {
 | |
|   /*
 | |
|     Addresses to listen to and network namespace for
 | |
|     every address if set.
 | |
|   */
 | |
|   std::list<Bind_address_info> m_bind_addresses;
 | |
|   /*
 | |
|     Address to listen to an admin connection request
 | |
|     and network namespace if set.
 | |
|   */
 | |
|   Bind_address_info m_admin_bind_address;
 | |
|   uint m_tcp_port;        // TCP port to bind to
 | |
|   uint m_admin_tcp_port;  // TCP port to bind to for support admin connection
 | |
|   bool m_use_separate_thread_for_admin;  // use a separate thread for listening
 | |
|                                          // to admin interface
 | |
|   uint m_backlog;       // backlog specifying length of pending connection queue
 | |
|   uint m_port_timeout;  // port timeout value
 | |
|   std::string m_unix_sockname;  // unix socket pathname to bind to
 | |
|   bool m_unlink_sockname;       // Unlink socket & lock file if true.
 | |
|   /*
 | |
|     Map indexed by MYSQL socket fds and correspoding bool to distinguish
 | |
|     between unix and tcp socket.
 | |
|   */
 | |
|   socket_map_t m_socket_map;  // map indexed by mysql socket fd and index
 | |
|   MYSQL_SOCKET m_admin_interface_listen_socket;
 | |
| 
 | |
| #ifdef HAVE_POLL
 | |
|   struct poll_info_t {
 | |
|     std::vector<struct pollfd> m_fds;
 | |
|     std::vector<MYSQL_SOCKET> m_pfs_fds;
 | |
|   };
 | |
|   // poll related info. used in poll for listening to connection events.
 | |
|   poll_info_t m_poll_info;
 | |
| #else
 | |
|   struct select_info_t {
 | |
|     fd_set m_read_fds, m_client_fds;
 | |
|     my_socket m_max_used_connection;
 | |
|     select_info_t() : m_max_used_connection(0) { FD_ZERO(&m_client_fds); }
 | |
|   };
 | |
|   // select info for used in select for listening to connection events.
 | |
|   select_info_t m_select_info;
 | |
| #endif  // HAVE_POLL
 | |
| 
 | |
|  public:
 | |
|   /**
 | |
|     Constructor to setup a listener for listen to connect events from
 | |
|     clients.
 | |
| 
 | |
|     @param   bind_addresses  list of addresses to listen to
 | |
|     @param   tcp_port        TCP port to bind to
 | |
|     @param   admin_bind_addr address to listen admin connection
 | |
|     @param   admin_tcp_port  TCP port for admin connection to bind
 | |
|     @param   use_separate_thread_for_admin  Listen to connection requests
 | |
|                              on admin interface in a separate thread
 | |
|     @param   backlog         backlog specifying length of pending
 | |
|                              connection queue used in listen.
 | |
|     @param   port_timeout    portname.
 | |
|     @param   unix_sockname   pathname for unix socket to bind to
 | |
|   */
 | |
|   Mysqld_socket_listener(const std::list<Bind_address_info> &bind_addresses,
 | |
|                          uint tcp_port,
 | |
|                          const Bind_address_info &admin_bind_addr,
 | |
|                          uint admin_tcp_port,
 | |
|                          bool use_separate_thread_for_admin, uint backlog,
 | |
|                          uint port_timeout, std::string unix_sockname);
 | |
| 
 | |
|   /**
 | |
|     Set up a listener - set of sockets to listen for connection events
 | |
|     from clients.
 | |
| 
 | |
|     In case a server is started with the option
 | |
|     use_separate_thread_for_admin=true invocation of this method also spawns a
 | |
|     thread to handle incoming connection requests on admin interface.
 | |
| 
 | |
|     @retval false  listener sockets setup to be used to listen for connect
 | |
|     events true   failure in setting up the listener.
 | |
|   */
 | |
|   bool setup_listener();
 | |
| 
 | |
|   /**
 | |
|     The body of the event loop that listen for connection events from clients.
 | |
| 
 | |
|     @retval Channel_info   Channel_info object abstracting the connected client
 | |
|                            details for processing this connection.
 | |
|   */
 | |
|   Channel_info *listen_for_connection_event();
 | |
| 
 | |
|   /**
 | |
|     Close the listener.
 | |
| 
 | |
|     In case a server is started with the option
 | |
|     use_separate_thread_for_admin=true this method also shutdowns a thread for
 | |
|     handling of incoming connection requests on admin interface and joins it.
 | |
|   */
 | |
|   void close_listener();
 | |
| 
 | |
|   ~Mysqld_socket_listener() {
 | |
|     if (!m_socket_map.empty()) close_listener();
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   /**
 | |
|     Add a socket to a set of sockets being waiting for a new
 | |
|     connection request.
 | |
| 
 | |
|     @param listen_socket  Socket to listen for.
 | |
|   */
 | |
|   void add_socket_to_listener(MYSQL_SOCKET listen_socket);
 | |
| 
 | |
|   /**
 | |
|     Get a socket ready to accept incoming connection.
 | |
|     @param[out] is_unix_socket  has the value true in case a new incoming
 | |
|                                 connection ready for acceptance pertains
 | |
|                                 to unix socket domain.
 | |
|     @param[out] is_admin_socket  has the value true in case a new incoming
 | |
|                                  connection is waiting for acceptance on
 | |
|                                  admin interface.
 | |
| 
 | |
|     @return A socket ready to accept a new incoming connection.
 | |
|   */
 | |
|   MYSQL_SOCKET get_ready_socket(bool *is_unix_socket,
 | |
|                                 bool *is_admin_socket) const;
 | |
| 
 | |
|   /**
 | |
|     Set up connection events for poll or select.
 | |
| 
 | |
|     @param socket_map  sockets to listen for connection requests.
 | |
|   */
 | |
|   void setup_connection_events(const socket_map_t &socket_map);
 | |
| };
 | |
| 
 | |
| ulong get_connection_errors_select();
 | |
| 
 | |
| ulong get_connection_errors_accept();
 | |
| 
 | |
| ulong get_connection_errors_tcpwrap();
 | |
| 
 | |
| #endif  // SOCKET_CONNECTION_INCLUDED.
 |