327 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			327 lines
		
	
	
		
			9.5 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();
 | |
| 
 | |
|     /**
 | |
|      * Create a new listener
 | |
|      *
 | |
|      * @param service       Service where the listener points to
 | |
|      * @param name          Name of the listener
 | |
|      * @param protocol      Protocol module to use
 | |
|      * @param address       The address to listen with
 | |
|      * @param port          The port to listen on
 | |
|      * @param authenticator Name of the authenticator to be used
 | |
|      * @param auth_options  Authenticator options
 | |
|      * @param ssl           SSL configuration
 | |
|      *
 | |
|      * @return New listener or nullptr on error
 | |
|      */
 | |
|     static SListener create(SERVICE* service,
 | |
|                             const std::string& name,
 | |
|                             const std::string& protocol,
 | |
|                             const std::string& address,
 | |
|                             unsigned short port,
 | |
|                             const std::string& authenticator,
 | |
|                             const std::string& auth_options,
 | |
|                             SSL_LISTENER* ssl);
 | |
| 
 | |
|     /**
 | |
|      * 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;
 | |
| 
 | |
|     /**
 | |
|      * The SSL_LISTENER object
 | |
|      */
 | |
|     SSL_LISTENER* ssl() 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);
 | |
| 
 | |
|     // Functions that are temporarily public
 | |
|     bool          create_listener_config(const char* filename);
 | |
|     struct users* users() const;
 | |
|     void          set_users(struct users* u);
 | |
| 
 | |
| 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 */
 | |
|     SSL_LISTENER*     m_ssl;            /**< Structure of SSL data or NULL */
 | |
|     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 */
 | |
| 
 | |
|     int m_fd;     /**< 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, SSL_LISTENER* ssl);
 | |
| 
 | |
|     /**
 | |
|      * Listen on a file descriptor shared between all workers
 | |
|      *
 | |
|      * @param config_bind The bind configuration consisting of an address and a port separated by the pipe
 | |
|      *                    character. For UNIX domain sockets, the address is the socket path and the port
 | |
|      *                    is always zero.
 | |
|      *
 | |
|      * @return True if the listening was started successfully
 | |
|      */
 | |
|     bool listen_shared(std::string config_bind);
 | |
| 
 | |
|     /**
 | |
|      * Accept a single client connection
 | |
|      *
 | |
|      * @return The new DCB or nullptr on error
 | |
|      */
 | |
|     DCB* accept_one_dcb();
 | |
| 
 | |
|     /**
 | |
|      * The file descriptor for accepting new connections
 | |
|      *
 | |
|      * When SO_REUSEPORT is in use, each worker has a separate file descriptor that they accept on.
 | |
|      */
 | |
|     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);
 | |
| 
 | |
| int  listener_set_ssl_version(SSL_LISTENER* ssl_listener, const char* version);
 | |
| void listener_set_certificates(SSL_LISTENER* ssl_listener, char* cert, char* key, char* ca_cert);
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Initialize SSL configuration
 | |
|  *
 | |
|  * This sets up the generated RSA encryption keys, chooses the listener
 | |
|  * encryption level and configures the listener certificate, private key and
 | |
|  * certificate authority file.
 | |
|  *
 | |
|  * @note This function should not be called directly, use config_create_ssl() instead
 | |
|  *
 | |
|  * @todo Combine this with config_create_ssl() into one function
 | |
|  *
 | |
|  * @param ssl SSL configuration to initialize
 | |
|  *
 | |
|  * @return True on success, false on error
 | |
|  */
 | |
| bool SSL_LISTENER_init(SSL_LISTENER* ssl);
 | |
| 
 | |
| /**
 | |
|  * Free an SSL_LISTENER
 | |
|  *
 | |
|  * @param ssl SSL_LISTENER to free
 | |
|  */
 | |
| void SSL_LISTENER_free(SSL_LISTENER* ssl);
 | 
