/* * 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 #include #include #include #include #include #include #include #include #include struct DCB; class SERVICE; class Listener; using SListener = std::shared_ptr; /** * 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 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 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);