 3af66f3309
			
		
	
	3af66f3309
	
	
	
		
			
			Servers and listeners now have a SSLProvider member variable that is used for all SSL related tasks.
		
			
				
	
	
		
			368 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			368 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2018 MariaDB Corporation Ab
 | |
|  *
 | |
|  * Use of this software is governed by the Business Source License included
 | |
|  * in the LICENSE.TXT file and at www.mariadb.com/bsl11.
 | |
|  *
 | |
|  * Change Date: 2022-01-01
 | |
|  *
 | |
|  * On the date above, in accordance with the Business Source License, use
 | |
|  * of this software will be governed by version 2 or later of the General
 | |
|  * Public License.
 | |
|  */
 | |
| #pragma once
 | |
| 
 | |
| #include <maxscale/ccdefs.hh>
 | |
| 
 | |
| #include <atomic>
 | |
| #include <string>
 | |
| #include <memory>
 | |
| #include <vector>
 | |
| 
 | |
| #include <maxbase/jansson.h>
 | |
| #include <maxscale/protocol.hh>
 | |
| #include <maxscale/ssl.hh>
 | |
| #include <maxscale/service.hh>
 | |
| #include <maxscale/routingworker.hh>
 | |
| 
 | |
| struct DCB;
 | |
| class SERVICE;
 | |
| 
 | |
| class Listener;
 | |
| using SListener = std::shared_ptr<Listener>;
 | |
| 
 | |
| /**
 | |
|  * The Listener class is used to link a network port to a service. It defines the name of the
 | |
|  * protocol module that should be loaded as well as the authenticator that is used.
 | |
|  */
 | |
| class Listener : public MXB_POLL_DATA
 | |
| {
 | |
| public:
 | |
| 
 | |
|     ~Listener();
 | |
| 
 | |
|     enum class Type
 | |
|     {
 | |
|         UNIX_SOCKET,    // UNIX domain socket shared between workers
 | |
|         SHARED_TCP,     // TCP listening socket shared between workers
 | |
|         UNIQUE_TCP,     // Unique TCP listening socket for each worker
 | |
|         MAIN_WORKER,    // Listener that always moves the execution to the main worker
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Create a new listener
 | |
|      *
 | |
|      * @param name     Name of the listener
 | |
|      * @param protocol Protocol module to use
 | |
|      * @param params   Parameters for the listener
 | |
|      *
 | |
|      * @return New listener or nullptr on error
 | |
|      */
 | |
|     static SListener create(const std::string& name,
 | |
|                             const std::string& protocol,
 | |
|                             const MXS_CONFIG_PARAMETER& params);
 | |
| 
 | |
|     /**
 | |
|      * Destroy a listener
 | |
|      *
 | |
|      * This removes the listener from the global list of active listeners. Once destroyed, the port used
 | |
|      * by a listener is open for immediate reuse.
 | |
|      *
 | |
|      * @param listener Listener to destroy
 | |
|      */
 | |
|     static void destroy(const SListener& listener);
 | |
| 
 | |
|     /**
 | |
|      * Start listening on the configured port
 | |
|      *
 | |
|      * @return True if the listener was able to start listening
 | |
|      */
 | |
|     bool listen();
 | |
| 
 | |
|     /**
 | |
|      * Stop the listener
 | |
|      *
 | |
|      * @return True if the listener was successfully stopped
 | |
|      */
 | |
|     bool stop();
 | |
| 
 | |
|     /**
 | |
|      * Start a stopped listener
 | |
|      *
 | |
|      * @return True if the listener was successfully started
 | |
|      */
 | |
|     bool start();
 | |
| 
 | |
|     /**
 | |
|      * Listener name
 | |
|      */
 | |
|     const char* name() const;
 | |
| 
 | |
|     /**
 | |
|      * Network address the listener listens on
 | |
|      */
 | |
|     const char* address() const;
 | |
| 
 | |
|     /**
 | |
|      * Network port the listener listens on
 | |
|      */
 | |
|     uint16_t port() const;
 | |
| 
 | |
|     /**
 | |
|      * Service the listener points to
 | |
|      */
 | |
|     SERVICE* service() const;
 | |
| 
 | |
|     /**
 | |
|      * The authenticator module name
 | |
|      */
 | |
|     const char* authenticator() const;
 | |
| 
 | |
|     /**
 | |
|      * The protocol module name
 | |
|      */
 | |
|     const char* protocol() const;
 | |
| 
 | |
|     /**
 | |
|      * The protocol module entry points
 | |
|      */
 | |
|     const MXS_PROTOCOL& protocol_func() const;
 | |
| 
 | |
|     /**
 | |
|      * The authenticator module entry points
 | |
|      */
 | |
|     const MXS_AUTHENTICATOR& auth_func() const;
 | |
| 
 | |
|     /**
 | |
|      * The authenticator instance
 | |
|      */
 | |
|     void* auth_instance() const;
 | |
| 
 | |
|     /**
 | |
|      * The state of the listener
 | |
|      */
 | |
|     const char* state() const;
 | |
| 
 | |
|     /**
 | |
|      * Convert to JSON
 | |
|      *
 | |
|      * @return JSON representation of the object
 | |
|      */
 | |
|     json_t* to_json() const;
 | |
| 
 | |
|     /**
 | |
|      * Load users for a listener
 | |
|      *
 | |
|      * @return The result from the authenticator module
 | |
|      */
 | |
|     int load_users();
 | |
| 
 | |
|     /**
 | |
|      * Print the users into a DCB
 | |
|      *
 | |
|      * Note: not const due to authenticator API
 | |
|      *
 | |
|      * @param dcb DCB to write into
 | |
|      */
 | |
|     void print_users(DCB* dcb);
 | |
| 
 | |
|     Type type() const
 | |
|     {
 | |
|         return m_type;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Mark authentication as failed
 | |
|      *
 | |
|      * This updates the number of failures that have occurred from this host. If the number of authentications
 | |
|      * exceeds a certain value, any attempts to connect from the remote in quesion will be rejected.
 | |
|      *
 | |
|      * @param remote The address where the connection originated
 | |
|      */
 | |
|     void mark_auth_as_failed(const std::string& remote);
 | |
| 
 | |
|     // Functions that are temporarily public
 | |
|     bool          create_listener_config(const char* filename);
 | |
|     struct users* users() const;
 | |
|     void          set_users(struct users* u);
 | |
| 
 | |
|     const mxs::SSLProvider& ssl() const
 | |
|     {
 | |
|         return m_ssl_provider;
 | |
|     }
 | |
| 
 | |
|     mxs::SSLProvider& ssl()
 | |
|     {
 | |
|         return m_ssl_provider;
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     enum State
 | |
|     {
 | |
|         CREATED,
 | |
|         STARTED,
 | |
|         STOPPED,
 | |
|         FAILED,
 | |
|         DESTROYED
 | |
|     };
 | |
| 
 | |
|     std::string m_name;             /**< Name of the listener */
 | |
|     State       m_state;            /**< Listener state */
 | |
|     std::string m_protocol;         /**< Protocol module to load */
 | |
|     uint16_t    m_port;             /**< Port to listen on */
 | |
|     std::string m_address;          /**< Address to listen with */
 | |
|     std::string m_authenticator;    /**< Name of authenticator */
 | |
|     std::string m_auth_options;     /**< Authenticator options */
 | |
|     void*       m_auth_instance;    /**< Authenticator instance */
 | |
| 
 | |
|     struct users*        m_users;           /**< The user data for this listener */
 | |
|     SERVICE*             m_service;         /**< The service which used by this listener */
 | |
|     std::atomic<bool>    m_active;          /**< True if the port has not been deleted */
 | |
|     MXS_PROTOCOL         m_proto_func;      /**< Preloaded protocol functions */
 | |
|     MXS_AUTHENTICATOR    m_auth_func;       /**< Preloaded authenticator functions */
 | |
|     MXS_CONFIG_PARAMETER m_params;          /**< Configuration parameters */
 | |
|     mxs::SSLProvider     m_ssl_provider;
 | |
| 
 | |
|     Type m_type;    /**< The type of the listener */
 | |
| 
 | |
|     mxs::rworker_local<int> m_fd {-1};      /**< File descriptor the listener listens on */
 | |
| 
 | |
|     /** A shared pointer to the listener itself that is passed as the argument to
 | |
|      * the protocol's accept function. This allows client connections to live
 | |
|      * longer than the listener they started on.
 | |
|      *
 | |
|      * This will eventually be replaced with a shared_ptr of the authenticator instance as that is
 | |
|      * what is actually required by the client sessions.
 | |
|      *
 | |
|      * In practice as a service must outlive all sessions on it, the reference could be owned by the service
 | |
|      * instead of each individual client. This would remove the need to increment the listener reference
 | |
|      * count every time a client is accepted.
 | |
|      */
 | |
|     SListener m_self;
 | |
| 
 | |
|     /**
 | |
|      * Creates a new listener that points to a service
 | |
|      *
 | |
|      * @param service       Service where the listener points to
 | |
|      * @param name          Name of the listener
 | |
|      * @param address       The address where the listener listens
 | |
|      * @param port          The port on which the listener listens
 | |
|      * @param protocol      The protocol module to use
 | |
|      * @param authenticator The authenticator module to use
 | |
|      * @param auth_opts     Options for the authenticator
 | |
|      * @param auth_instance The authenticator instance
 | |
|      * @param ssl           The SSL configuration
 | |
|      */
 | |
|     Listener(SERVICE* service, const std::string& name, const std::string& address, uint16_t port,
 | |
|              const std::string& protocol, const std::string& authenticator,
 | |
|              const std::string& auth_opts, void* auth_instance, std::unique_ptr<mxs::SSLContext> ssl,
 | |
|              const MXS_CONFIG_PARAMETER& params);
 | |
| 
 | |
|     /**
 | |
|      * Listen on a file descriptor shared between all workers
 | |
|      *
 | |
|      * @return True if the listening was started successfully
 | |
|      */
 | |
|     bool listen_shared();
 | |
| 
 | |
|     /**
 | |
|      * Listen with a unique file descriptor for each worker
 | |
|      *
 | |
|      * @return True if the listening was started successfully
 | |
|      */
 | |
|     bool listen_unique();
 | |
| 
 | |
|     /**
 | |
|      * Close all opened file descriptors for this listener
 | |
|      */
 | |
|     void close_all_fds();
 | |
| 
 | |
|     /**
 | |
|      * Accept a single client connection
 | |
|      *
 | |
|      * @param fd The opened file descriptor to which the client is connected to
 | |
|      * @param addr The network information
 | |
|      * @param host The host where the client is connecting from
 | |
|      *
 | |
|      * @return The new DCB or nullptr on error
 | |
|      */
 | |
|     DCB* accept_one_dcb(int fd, const sockaddr_storage* addr, const char* host);
 | |
| 
 | |
|     /**
 | |
|      * Accept all available client connections
 | |
|      */
 | |
|     void accept_connections();
 | |
| 
 | |
|     /**
 | |
|      * Reject a client connection
 | |
|      *
 | |
|      * Writes an error message to the fd if the protocol supports it and then closes it.
 | |
|      *
 | |
|      * @param fd   The file descriptor to close
 | |
|      * @param host The host where the connection originated from
 | |
|      */
 | |
|     void reject_connection(int fd, const char* host);
 | |
| 
 | |
|     /**
 | |
|      * The file descriptor for accepting new connections
 | |
|      *
 | |
|      * @return The worker-local file descriptor
 | |
|      */
 | |
|     int fd() const
 | |
|     {
 | |
|         return *m_fd;
 | |
|     }
 | |
| 
 | |
|     // Handler for EPOLL_IN events
 | |
|     static uint32_t poll_handler(MXB_POLL_DATA* data, MXB_WORKER* worker, uint32_t events);
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * @brief Serialize a listener to a file
 | |
|  *
 | |
|  * This converts @c listener into an INI format file. This allows created listeners
 | |
|  * to be persisted to disk. This will replace any existing files with the same
 | |
|  * name.
 | |
|  *
 | |
|  * @param listener Listener to serialize
 | |
|  * @return True if the serialization of the listener was successful, false if it fails
 | |
|  */
 | |
| bool listener_serialize(const SListener& listener);
 | |
| 
 | |
| /**
 | |
|  * Find a listener
 | |
|  *
 | |
|  * @param name Name of the listener
 | |
|  *
 | |
|  * @return The listener if it exists or an empty SListener if it doesn't
 | |
|  */
 | |
| SListener listener_find(const std::string& name);
 | |
| 
 | |
| /**
 | |
|  * Find all listeners that point to a service
 | |
|  *
 | |
|  * @param service Service whose listeners are returned
 | |
|  *
 | |
|  * @return The listeners that point to the service
 | |
|  */
 | |
| std::vector<SListener> listener_find_by_service(const SERVICE* service);
 | |
| 
 | |
| /**
 | |
|  * Find listener by socket
 | |
|  *
 | |
|  * @param socket  Path to a socket file
 | |
|  *
 | |
|  * @return The matching listener if one was found
 | |
|  */
 | |
| SListener listener_find_by_socket(const std::string& socket);
 | |
| 
 | |
| /**
 | |
|  * Find listener by address and port
 | |
|  *
 | |
|  * @param address Network address
 | |
|  * @param port    Network port
 | |
|  *
 | |
|  * @return The matching listener if one was found
 | |
|  */
 | |
| SListener listener_find_by_address(const std::string& address, unsigned short port);
 |