From 01e9f71af12c71809b9722195d9df9b4c3febcb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 28 Nov 2018 14:22:12 +0200 Subject: [PATCH] MXS-2197: Make SERV_LISTENER a C++ class The class is still mostly the same as the old C version but it now uses std::string instead of char pointers. Changed configuration default values so that the parameters passed to the listener allocation are always valid. --- include/maxscale/authenticator.h | 9 +- include/maxscale/dcb.h | 49 ++-- include/maxscale/listener.h | 162 ------------- include/maxscale/listener.hh | 213 ++++++++++++++++++ include/maxscale/users.h | 2 +- server/core/authenticator.cc | 4 +- server/core/config.cc | 6 +- server/core/dcb.cc | 6 +- server/core/listener.cc | 162 +++++-------- server/core/service.cc | 83 +++---- server/core/test/test_dcb.cc | 6 +- server/core/test/test_poll.cc | 6 +- .../CDCPlainAuth/cdc_plain_auth.cc | 4 - .../authenticator/MySQLAuth/mysql_auth.cc | 6 +- server/modules/protocol/HTTPD/httpd.cc | 2 +- 15 files changed, 353 insertions(+), 367 deletions(-) delete mode 100644 include/maxscale/listener.h create mode 100644 include/maxscale/listener.hh diff --git a/include/maxscale/authenticator.h b/include/maxscale/authenticator.h index 54ee35099..675e5d38d 100644 --- a/include/maxscale/authenticator.h +++ b/include/maxscale/authenticator.h @@ -23,6 +23,8 @@ #include #include +class SERV_LISTENER; + MXS_BEGIN_DECLS /** @@ -44,7 +46,6 @@ typedef enum authenticator_capability struct dcb; struct server; struct session; -struct servlistener; /** * @verbatim @@ -96,8 +97,8 @@ typedef struct mxs_authenticator int (* authenticate)(struct dcb*); void (* free)(struct dcb*); void (* destroy)(void*); - int (* loadusers)(struct servlistener*); - void (* diagnostic)(struct dcb*, struct servlistener*); + int (* loadusers)(SERV_LISTENER*); + void (* diagnostic)(struct dcb*, SERV_LISTENER*); /** * @brief Return diagnostic information about the authenticator @@ -111,7 +112,7 @@ typedef struct mxs_authenticator * * @see jansson.h */ - json_t* (*diagnostic_json)(const struct servlistener* listener); + json_t* (*diagnostic_json)(const SERV_LISTENER * listener); /** This entry point was added to avoid calling authenticator functions * directly when a COM_CHANGE_USER command is executed. */ diff --git a/include/maxscale/dcb.h b/include/maxscale/dcb.h index e3d2353b0..451221468 100644 --- a/include/maxscale/dcb.h +++ b/include/maxscale/dcb.h @@ -26,14 +26,15 @@ #include #include +class SERVICE; +class SERV_LISTENER; + MXS_BEGIN_DECLS #define ERRHANDLE struct session; struct server; -struct service; -struct servlistener; struct dcb; @@ -188,7 +189,7 @@ typedef struct dcb size_t protocol_packet_length; /**< How long the protocol specific packet is */ size_t protocol_bytes_processed; /**< How many bytes of a packet have been read */ struct session* session; /**< The owning session */ - struct servlistener* listener; /**< For a client DCB, the listener data */ + SERV_LISTENER* listener; /**< For a client DCB, the listener data */ MXS_PROTOCOL func; /**< The protocol functions for this descriptor */ MXS_AUTHENTICATOR authfunc; /**< The authenticator functions for this descriptor * */ @@ -201,26 +202,26 @@ typedef struct dcb GWBUF* fakeq; /**< Fake event queue for generated events */ uint32_t fake_event; /**< Fake event to be delivered to handler */ - DCBSTATS stats; /**< DCB related statistics */ - struct dcb* nextpersistent; /**< Next DCB in the persistent pool for SERVER */ - time_t persistentstart; /**< 0: Not in the persistent pool. - * -1: Evicted from the persistent pool and being closed. - * non-0: Time when placed in the persistent pool. - */ - struct service* service; /**< The related service */ - void* data; /**< Specific client data, shared between DCBs of this session */ - void* authenticator_data; /**< The authenticator data for this DCB */ - DCB_CALLBACK* callbacks; /**< The list of callbacks for the DCB */ - int64_t last_read; /*< Last time the DCB received data */ - struct server* server; /**< The associated backend server */ - SSL* ssl; /*< SSL struct for connection */ - bool ssl_read_want_read; /*< Flag */ - bool ssl_read_want_write; /*< Flag */ - bool ssl_write_want_read; /*< Flag */ - bool ssl_write_want_write; /*< Flag */ - bool was_persistent; /**< Whether this DCB was in the persistent pool */ - bool high_water_reached; /** High water mark reached, to determine whether need release - * throttle */ + DCBSTATS stats; /**< DCB related statistics */ + struct dcb* nextpersistent; /**< Next DCB in the persistent pool for SERVER */ + time_t persistentstart; /**< 0: Not in the persistent pool. + * -1: Evicted from the persistent pool and being closed. + * non-0: Time when placed in the persistent pool. + */ + SERVICE* service; /**< The related service */ + void* data; /**< Specific client data, shared between DCBs of this session */ + void* authenticator_data; /**< The authenticator data for this DCB */ + DCB_CALLBACK* callbacks; /**< The list of callbacks for the DCB */ + int64_t last_read; /*< Last time the DCB received data */ + struct server* server; /**< The associated backend server */ + SSL* ssl; /*< SSL struct for connection */ + bool ssl_read_want_read; /*< Flag */ + bool ssl_read_want_write; /*< Flag */ + bool ssl_write_want_read; /*< Flag */ + bool ssl_write_want_write;/*< Flag */ + bool was_persistent; /**< Whether this DCB was in the persistent pool */ + bool high_water_reached; /** High water mark reached, to determine whether need release + * throttle */ struct { struct dcb* next; /**< Next DCB in owning thread's list */ @@ -260,7 +261,7 @@ void dcb_global_init(); int dcb_write(DCB*, GWBUF*); DCB* dcb_accept(DCB* listener); -DCB* dcb_alloc(dcb_role_t, struct servlistener*); +DCB* dcb_alloc(dcb_role_t, SERV_LISTENER*); DCB* dcb_connect(struct server*, struct session*, const char*); int dcb_read(DCB*, GWBUF**, int); int dcb_drain_writeq(DCB*); diff --git a/include/maxscale/listener.h b/include/maxscale/listener.h deleted file mode 100644 index 9abe3e0cb..000000000 --- a/include/maxscale/listener.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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 - -/** - * @file listener.h - */ - -#include -#include -#include -#include - -MXS_BEGIN_DECLS - -struct dcb; -struct service; - -/** - * The servlistener structure is used to link a service to the protocols that - * are used to support that service. It defines the name of the protocol module - * that should be loaded to support the client connection and the port that the - * protocol should use to listen for incoming client connections. - */ -typedef struct servlistener -{ - char* name; /**< Name of the listener */ - char* protocol; /**< Protocol module to load */ - unsigned short port; /**< Port to listen on */ - char* address; /**< Address to listen with */ - char* authenticator; /**< Name of authenticator */ - char* auth_options; /**< Authenticator options */ - void* auth_instance; /**< Authenticator instance created in MXS_AUTHENTICATOR::initialize() - * */ - SSL_LISTENER* ssl; /**< Structure of SSL data or NULL */ - struct dcb* listener; /**< The DCB for the listener */ - struct users* users; /**< The user data for this listener */ - struct service* service; /**< The service which used by this listener */ - pthread_mutex_t lock; - int active; /**< True if the port has not been deleted */ - struct servlistener* next; /**< Next service protocol */ -} SERV_LISTENER; // TODO: Rename to LISTENER - -typedef struct listener_iterator -{ - SERV_LISTENER* current; -} LISTENER_ITERATOR; - -/** - * @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 SERV_LISTENER* listener); - -/** - * @brief Convert listener to JSON - * - * @param listener Listener to convert - * - * @return Converted listener - */ -json_t* listener_to_json(const SERV_LISTENER* listener); - -SERV_LISTENER* listener_alloc(struct service* service, - const char* name, - const char* protocol, - const char* address, - unsigned short port, - const char* authenticator, - const char* auth_options, - SSL_LISTENER* ssl); -void listener_free(SERV_LISTENER* listener); -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); - -/** - * @brief Check if listener is active - * - * @param listener Listener to check - * - * @return True if listener is active - */ -bool listener_is_active(SERV_LISTENER* listener); - -/** - * @brief Modify listener active state - * - * @param listener Listener to modify - * @param active True to activate, false to disable - */ -void listener_set_active(SERV_LISTENER* listener, bool active); - -/** - * @brief Initialize a listener iterator for iterating service listeners - * - * @param service Service whose listeners are iterated - * @param iter Pointer to iterator to initialize - * - * @return The first value pointed by the iterator - */ -SERV_LISTENER* listener_iterator_init(const struct service* service, LISTENER_ITERATOR* iter); - -/** - * @brief Get the next listener - * - * @param iter Listener iterator - * - * @return The next listener or NULL on end of list - */ -SERV_LISTENER* listener_iterator_next(LISTENER_ITERATOR* iter); - -/** - * Get listener state as a string - * - * @param listener Listener to inspect - * - * @return State of the listener as a string - */ -const char* listener_state_to_string(const SERV_LISTENER* listener); - -MXS_END_DECLS diff --git a/include/maxscale/listener.hh b/include/maxscale/listener.hh new file mode 100644 index 000000000..7f0588087 --- /dev/null +++ b/include/maxscale/listener.hh @@ -0,0 +1,213 @@ +/* + * 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 + +struct dcb; +class SERVICE; + +/** + * 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. + */ +// TODO: Rename to Listener +class SERV_LISTENER +{ +public: + SERV_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); + ~SERV_LISTENER(); + +public: + std::string name; /**< Name of the listener */ + std::string protocol; /**< Protocol module to load */ + uint16_t port; /**< Port to listen on */ + std::string address; /**< Address to listen with */ + std::string authenticator;/**< Name of authenticator */ + std::string auth_options; /**< Authenticator options */ + void* auth_instance;/**< Authenticator instance */ + SSL_LISTENER* ssl; /**< Structure of SSL data or NULL */ + struct dcb* listener; /**< The DCB for the listener */ + struct users* users; /**< The user data for this listener */ + SERVICE* service; /**< The service which used by this listener */ + int active; /**< True if the port has not been deleted */ + SERV_LISTENER* next; /**< Next service protocol */ +}; + +typedef struct listener_iterator +{ + SERV_LISTENER* current; +} LISTENER_ITERATOR; + +/** + * @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 SERV_LISTENER* listener); + +/** + * @brief Convert listener to JSON + * + * @param listener Listener to convert + * + * @return Converted listener + */ +json_t* listener_to_json(const SERV_LISTENER* 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 + */ +SERV_LISTENER* listener_alloc(SERVICE* service, + const char* name, + const char* protocol, + const char* address, + unsigned short port, + const char* authenticator, + const char* auth_options, + SSL_LISTENER* ssl); + +/** + * @brief Free a listener + * + * The listener must be destroyed before it can be freed. + * + * @param listener Listener to free + */ +void listener_free(SERV_LISTENER* listener); + +/** + * Destroy a listener + * + * This deactivates the listener and closes the network port it listens on. Once destroyed, the listener + * can no longer be used. + * + * @param listener Listener to destroy + */ +void listener_destroy(SERV_LISTENER* listener); + +/** + * Stop a listener + * + * @param listener Listener to stop + * + * @return True if listener was successfully stopped + */ +bool listener_stop(SERV_LISTENER* listener); + +/** + * Start a stopped listener + * + * @param listener Listener to start + * + * @return True if listener was successfully started + */ +bool listener_start(SERV_LISTENER* listener); + +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); + +/** + * @brief Check if listener is active + * + * @param listener Listener to check + * + * @return True if listener is active + */ +bool listener_is_active(SERV_LISTENER* listener); + +/** + * @brief Modify listener active state + * + * @param listener Listener to modify + * @param active True to activate, false to disable + */ +void listener_set_active(SERV_LISTENER* listener, bool active); + +/** + * @brief Initialize a listener iterator for iterating service listeners + * + * @param service Service whose listeners are iterated + * @param iter Pointer to iterator to initialize + * + * @return The first value pointed by the iterator + */ +SERV_LISTENER* listener_iterator_init(const SERVICE* service, LISTENER_ITERATOR* iter); + +/** + * @brief Get the next listener + * + * @param iter Listener iterator + * + * @return The next listener or NULL on end of list + */ +SERV_LISTENER* listener_iterator_next(LISTENER_ITERATOR* iter); + +/** + * Get listener state as a string + * + * @param listener Listener to inspect + * + * @return State of the listener as a string + */ +const char* listener_state_to_string(const SERV_LISTENER* listener); diff --git a/include/maxscale/users.h b/include/maxscale/users.h index 036aa5fbe..a3946dbea 100644 --- a/include/maxscale/users.h +++ b/include/maxscale/users.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include diff --git a/server/core/authenticator.cc b/server/core/authenticator.cc index 602ae0ae9..6ab1d88e0 100644 --- a/server/core/authenticator.cc +++ b/server/core/authenticator.cc @@ -47,11 +47,11 @@ bool authenticator_init(void** dest, const char* authenticator, const char* opti else if (func->initialize) { char* optarray[AUTHENTICATOR_MAX_OPTIONS + 1]; - size_t optlen = options ? strlen(options) : 0; + size_t optlen = options && *options ? strlen(options) : 0; char optcopy[optlen + 1]; int optcount = 0; - if (options) + if (options && *options) { strcpy(optcopy, options); char* opt = optcopy; diff --git a/server/core/config.cc b/server/core/config.cc index a84e4dd9e..fc4c8f123 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -327,9 +327,9 @@ const MXS_MODULE_PARAM config_listener_params[] = {CN_PORT, MXS_MODULE_PARAM_COUNT}, // Either port or socket, // checked when created {CN_SOCKET, MXS_MODULE_PARAM_STRING}, - {CN_AUTHENTICATOR_OPTIONS, MXS_MODULE_PARAM_STRING}, + {CN_AUTHENTICATOR_OPTIONS, MXS_MODULE_PARAM_STRING, ""}, {CN_ADDRESS, MXS_MODULE_PARAM_STRING, "::"}, - {CN_AUTHENTICATOR, MXS_MODULE_PARAM_STRING}, + {CN_AUTHENTICATOR, MXS_MODULE_PARAM_STRING, "MySQLAuth"}, {CN_SSL, MXS_MODULE_PARAM_ENUM, "false", MXS_MODULE_OPT_ENUM_UNIQUE, ssl_values}, @@ -3860,7 +3860,7 @@ int create_new_listener(CONFIG_CONTEXT* obj) "listener '%s' already listens on the %s %s.", obj->object, service->name, - l->name, + l->name.c_str(), socket ? "socket" : "port", socket ? socket : port); return 1; diff --git a/server/core/dcb.cc b/server/core/dcb.cc index 9e4ee265a..d231ca861 100644 --- a/server/core/dcb.cc +++ b/server/core/dcb.cc @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include @@ -2451,9 +2451,9 @@ DCB* dcb_accept(DCB* dcb) } } memcpy(&client_dcb->func, protocol_funcs, sizeof(MXS_PROTOCOL)); - if (dcb->listener->authenticator) + if (!dcb->listener->authenticator.empty()) { - authenticator_name = dcb->listener->authenticator; + authenticator_name = dcb->listener->authenticator.c_str(); } else if (client_dcb->func.auth_default != NULL) { diff --git a/server/core/listener.cc b/server/core/listener.cc index 788d06913..3a6e3d4f6 100644 --- a/server/core/listener.cc +++ b/server/core/listener.cc @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include #include @@ -47,6 +47,40 @@ static RSA* rsa_1024 = NULL; static RSA* tmp_rsa_callback(SSL* s, int is_export, int keylength); +SERV_LISTENER::SERV_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) + : name(name) + , protocol(protocol) + , port(port) + , address(address) + , authenticator(authenticator) + , auth_options(auth_opts) + , auth_instance(auth_instance) + , ssl(ssl) + , listener(nullptr) + , users(nullptr) + , service(service) + , active(1) + , next(nullptr) +{ +} + +SERV_LISTENER::~SERV_LISTENER() +{ + if (users) + { + users_free(users); + } + + if (listener) + { + dcb_close(listener); + } + + SSL_LISTENER_free(ssl); +} + /** * Create a new listener structure * @@ -67,84 +101,27 @@ SERV_LISTENER* listener_alloc(SERVICE* service, const char* auth_options, SSL_LISTENER* ssl) { - char* my_address = NULL; - if (address) + if (!authenticator) { - my_address = MXS_STRDUP(address); - if (!my_address) + if ((authenticator = get_default_authenticator(protocol)) == NULL) { - return NULL; + MXS_ERROR("No authenticator defined for listener '%s' and could not get " + "default authenticator for protocol '%s'.", name, protocol); + return nullptr; } } - char* my_auth_options = NULL; - - if (auth_options && (my_auth_options = MXS_STRDUP(auth_options)) == NULL) - { - MXS_FREE(my_address); - return NULL; - } - - char* my_authenticator = NULL; - - if (authenticator) - { - my_authenticator = MXS_STRDUP(authenticator); - } - else if ((authenticator = get_default_authenticator(protocol)) == NULL - || (my_authenticator = MXS_STRDUP(authenticator)) == NULL) - { - MXS_ERROR("No authenticator defined for listener '%s' and could not get " - "default authenticator for protocol '%s'.", - name, - protocol); - MXS_FREE(my_address); - return NULL; - } - void* auth_instance = NULL; - if (!authenticator_init(&auth_instance, my_authenticator, my_auth_options)) + if (!authenticator_init(&auth_instance, authenticator, auth_options)) { - MXS_ERROR("Failed to initialize authenticator module '%s' for " - "listener '%s'.", - my_authenticator, - name); - MXS_FREE(my_address); - MXS_FREE(my_authenticator); - return NULL; + MXS_ERROR("Failed to initialize authenticator module '%s' for listener '%s'.", + authenticator, name); + return nullptr; } - char* my_protocol = MXS_STRDUP(protocol); - char* my_name = MXS_STRDUP(name); - SERV_LISTENER* proto = (SERV_LISTENER*)MXS_MALLOC(sizeof(SERV_LISTENER)); - - if (!my_protocol || !proto || !my_name || !my_authenticator) - { - MXS_FREE(my_authenticator); - MXS_FREE(my_protocol); - MXS_FREE(my_address); - MXS_FREE(my_name); - MXS_FREE(proto); - return NULL; - } - - proto->active = 1; - proto->name = my_name; - proto->listener = NULL; - proto->service = service; - proto->protocol = my_protocol; - proto->address = my_address; - proto->port = port; - proto->authenticator = my_authenticator; - proto->auth_options = my_auth_options; - proto->ssl = ssl; - proto->users = NULL; - proto->next = NULL; - proto->auth_instance = auth_instance; - pthread_mutex_init(&proto->lock, NULL); - - return proto; + return new(std::nothrow) SERV_LISTENER(service, name, address, port, protocol, authenticator, + auth_options, auth_instance, ssl); } /** @@ -154,26 +131,7 @@ SERV_LISTENER* listener_alloc(SERVICE* service, */ void listener_free(SERV_LISTENER* listener) { - if (listener) - { - if (listener->users) - { - users_free(listener->users); - } - - if (listener->listener) - { - dcb_close(listener->listener); - } - - SSL_LISTENER_free(listener->ssl); - MXS_FREE(listener->address); - MXS_FREE(listener->authenticator); - MXS_FREE(listener->auth_options); - MXS_FREE(listener->name); - MXS_FREE(listener->protocol); - MXS_FREE(listener); - } + delete listener; } /** @@ -480,24 +438,24 @@ static bool create_listener_config(const SERV_LISTENER* listener, const char* fi { MXS_ERROR("Failed to open file '%s' when serializing listener '%s': %d, %s", filename, - listener->name, + listener->name.c_str(), errno, mxs_strerror(errno)); return false; } // TODO: Check for return values on all of the dprintf calls - dprintf(file, "[%s]\n", listener->name); + dprintf(file, "[%s]\n", listener->name.c_str()); dprintf(file, "type=listener\n"); - dprintf(file, "protocol=%s\n", listener->protocol); + dprintf(file, "protocol=%s\n", listener->protocol.c_str()); dprintf(file, "service=%s\n", listener->service->name); - dprintf(file, "address=%s\n", listener->address); + dprintf(file, "address=%s\n", listener->address.c_str()); dprintf(file, "port=%u\n", listener->port); - dprintf(file, "authenticator=%s\n", listener->authenticator); + dprintf(file, "authenticator=%s\n", listener->authenticator.c_str()); - if (listener->auth_options) + if (!listener->auth_options.empty()) { - dprintf(file, "authenticator_options=%s\n", listener->auth_options); + dprintf(file, "authenticator_options=%s\n", listener->auth_options.c_str()); } if (listener->ssl) @@ -518,7 +476,7 @@ bool listener_serialize(const SERV_LISTENER* listener) sizeof(filename), "%s/%s.cnf.tmp", get_config_persistdir(), - listener->name); + listener->name.c_str()); if (unlink(filename) == -1 && errno != ENOENT) { @@ -555,11 +513,11 @@ bool listener_serialize(const SERV_LISTENER* listener) json_t* listener_to_json(const SERV_LISTENER* listener) { json_t* param = json_object(); - json_object_set_new(param, "address", json_string(listener->address)); + json_object_set_new(param, "address", json_string(listener->address.c_str())); json_object_set_new(param, "port", json_integer(listener->port)); - json_object_set_new(param, "protocol", json_string(listener->protocol)); - json_object_set_new(param, "authenticator", json_string(listener->authenticator)); - json_object_set_new(param, "auth_options", json_string(listener->auth_options)); + json_object_set_new(param, "protocol", json_string(listener->protocol.c_str())); + json_object_set_new(param, "authenticator", json_string(listener->authenticator.c_str())); + json_object_set_new(param, "auth_options", json_string(listener->auth_options.c_str())); if (listener->ssl) { @@ -589,7 +547,7 @@ json_t* listener_to_json(const SERV_LISTENER* listener) } json_t* rval = json_object(); - json_object_set_new(rval, CN_ID, json_string(listener->name)); + json_object_set_new(rval, CN_ID, json_string(listener->name.c_str())); json_object_set_new(rval, CN_TYPE, json_string(CN_LISTENERS)); json_object_set_new(rval, CN_ATTRIBUTES, attr); diff --git a/server/core/service.cc b/server/core/service.cc index b1b6bf708..0f7178b6c 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include @@ -351,7 +351,7 @@ static int serviceStartPort(Service* service, SERV_LISTENER* port) int listeners = 0; size_t config_bind_len = - (port->address ? strlen(port->address) : ANY_IPV4_ADDRESS_LEN) + 1 + UINTLEN(port->port); + (!port->address.empty() ? port->address.length() : ANY_IPV4_ADDRESS_LEN) + 1 + UINTLEN(port->port); char config_bind[config_bind_len + 1]; // +1 for NULL MXS_PROTOCOL* funcs; @@ -375,10 +375,10 @@ static int serviceStartPort(Service* service, SERV_LISTENER* port) port->listener->service = service; - if ((funcs = (MXS_PROTOCOL*)load_module(port->protocol, MODULE_PROTOCOL)) == NULL) + if ((funcs = (MXS_PROTOCOL*)load_module(port->protocol.c_str(), MODULE_PROTOCOL)) == NULL) { MXS_ERROR("Unable to load protocol module %s. Listener for service %s not started.", - port->protocol, + port->protocol.c_str(), service->name); close_port(port); return 0; @@ -388,9 +388,9 @@ static int serviceStartPort(Service* service, SERV_LISTENER* port) const char* authenticator_name = "NullAuthDeny"; - if (port->authenticator) + if (!port->authenticator.empty()) { - authenticator_name = port->authenticator; + authenticator_name = port->authenticator.c_str(); } else if (port->listener->func.auth_default) { @@ -403,13 +403,13 @@ static int serviceStartPort(Service* service, SERV_LISTENER* port) { MXS_ERROR("Failed to load authenticator module '%s' for listener '%s'", authenticator_name, - port->name); + port->name.c_str()); close_port(port); return 0; } // Add protocol and authenticator capabilities from the listener - const MXS_MODULE* proto_mod = get_module(port->protocol, MODULE_PROTOCOL); + const MXS_MODULE* proto_mod = get_module(port->protocol.c_str(), MODULE_PROTOCOL); const MXS_MODULE* auth_mod = get_module(authenticator_name, MODULE_AUTHENTICATOR); mxb_assert(proto_mod && auth_mod); service->capabilities |= proto_mod->module_capabilities | auth_mod->module_capabilities; @@ -421,9 +421,9 @@ static int serviceStartPort(Service* service, SERV_LISTENER* port) * listeners aren't normal DCBs, we can skip that. */ - if (port->address) + if (!port->address.empty()) { - sprintf(config_bind, "%s|%d", port->address, port->port); + sprintf(config_bind, "%s|%d", port->address.c_str(), port->port); } else { @@ -439,7 +439,7 @@ static int serviceStartPort(Service* service, SERV_LISTENER* port) MXS_ERROR("[%s] Fatal error when loading users for listener '%s', " "service is not started.", service->name, - port->name); + port->name.c_str()); close_port(port); return 0; @@ -447,7 +447,7 @@ static int serviceStartPort(Service* service, SERV_LISTENER* port) MXS_WARNING("[%s] Failed to load users for listener '%s', authentication" " might not work.", service->name, - port->name); + port->name.c_str()); break; default: @@ -594,7 +594,7 @@ bool serviceStopListener(SERVICE* svc, const char* name) for (SERV_LISTENER* listener = listener_iterator_init(service, &iter); listener; listener = listener_iterator_next(&iter)) { - if (listener_is_active(listener) && strcmp(listener->name, name) == 0) + if (listener_is_active(listener) && listener->name == name) { if (poll_remove_dcb(listener->listener) == 0) { @@ -617,7 +617,7 @@ bool serviceStartListener(SERVICE* svc, const char* name) for (SERV_LISTENER* listener = listener_iterator_init(service, &iter); listener; listener = listener_iterator_next(&iter)) { - if (listener_is_active(listener) && strcmp(listener->name, name) == 0) + if (listener_is_active(listener) && listener->name == name) { if (listener->listener && listener->listener->session->state == SESSION_STATE_LISTENER_STOPPED && poll_add_dcb(listener->listener) == 0) @@ -752,7 +752,7 @@ bool service_remove_listener(Service* service, const char* target) for (SERV_LISTENER* listener = listener_iterator_init(service, &iter); listener; listener = listener_iterator_next(&iter)) { - if (listener_is_active(listener) && strcmp(listener->name, target) == 0) + if (listener_is_active(listener) && listener->name == target) { listener_set_active(listener, false); @@ -821,28 +821,10 @@ SERV_LISTENER* service_find_listener(Service* service, for (SERV_LISTENER* listener = listener_iterator_init(service, &iter); listener; listener = listener_iterator_next(&iter)) { - if (listener_is_active(listener)) + if (listener_is_active(listener) && port == listener->port) { - bool is_same_port = false; - - if (port && (port == listener->port) - && ((address && listener->address && strcmp(listener->address, address) == 0) - || (address == NULL && listener->address == NULL))) - { - is_same_port = true; - } - - bool is_same_socket = false; - - if (!is_same_port) - { - if (socket && listener->address && strcmp(listener->address, socket) == 0) - { - is_same_socket = true; - } - } - - if (is_same_port || is_same_socket) + if ((!address && listener->address.empty()) || listener->address == address + || (!socket && listener->address.empty()) || listener->address == socket) { return listener; } @@ -872,15 +854,12 @@ bool serviceHasListener(Service* service, for (SERV_LISTENER* listener = listener_iterator_init(service, &iter); listener; listener = listener_iterator_next(&iter)) { - if (listener_is_active(listener) - && // Listener with same name exists - (strcmp(listener->name, name) == 0 - || // Listener listening on the same interface and port exists - ((strcmp(listener->protocol, protocol) == 0 && listener->port == port - && ((address && listener->address && strcmp(listener->address, address) == 0) - || (address == NULL && listener->address == NULL)))))) + if (listener_is_active(listener) && listener->port == port) { - return true; + if ((!address && listener->address.empty()) || listener->address == address) + { + return true; + } } } @@ -894,7 +873,7 @@ bool service_has_named_listener(Service* service, const char* name) for (SERV_LISTENER* listener = listener_iterator_init(service, &iter); listener; listener = listener_iterator_next(&iter)) { - if (listener_is_active(listener) && strcmp(listener->name, name) == 0) + if (listener_is_active(listener) && listener->name == name) { return true; } @@ -1403,10 +1382,10 @@ void dListListeners(DCB* dcb) { dcb_printf(dcb, "%-20s | %-19s | %-18s | %-15s | %5d | %s\n", - listener->name, + listener->name.c_str(), service->name, - listener->protocol, - (listener && listener->address) ? listener->address : "*", + listener->protocol.c_str(), + (listener && !listener->address.empty()) ? listener->address.c_str() : "*", listener->port, listener_state_to_string(listener)); } @@ -1473,7 +1452,7 @@ bool Service::refresh_users() MXS_ERROR("[%s] Fatal error when loading users for listener '%s'," " authentication will not work.", m_name.c_str(), - listener->name); + listener->name.c_str()); ret = false; break; @@ -1481,7 +1460,7 @@ bool Service::refresh_users() MXS_WARNING("[%s] Failed to load users for listener '%s', authentication" " might not work.", m_name.c_str(), - listener->name); + listener->name.c_str()); ret = false; break; @@ -1938,7 +1917,7 @@ void service_print_users(DCB* dcb, const SERVICE* service) if (listener_is_active(listener) && listener->listener && listener->listener->authfunc.diagnostic) { - dcb_printf(dcb, "User names (%s): ", listener->name); + dcb_printf(dcb, "User names (%s): ", listener->name.c_str()); listener->listener->authfunc.diagnostic(dcb, listener); @@ -2048,7 +2027,7 @@ static json_t* service_listener_json_data(const SERVICE* service, const char* na for (SERV_LISTENER* listener = listener_iterator_init(service, &iter); listener; listener = listener_iterator_next(&iter)) { - if (listener_is_active(listener) && strcmp(listener->name, name) == 0) + if (listener_is_active(listener) && listener->name == name) { return listener_to_json(listener); } diff --git a/server/core/test/test_dcb.cc b/server/core/test/test_dcb.cc index 959e620d3..7ec3c69ac 100644 --- a/server/core/test/test_dcb.cc +++ b/server/core/test/test_dcb.cc @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include "../dcb.cc" @@ -48,10 +48,10 @@ static int test1() { DCB* dcb; - SERV_LISTENER dummy; + SERV_LISTENER* dummy = nullptr; /* Single buffer tests */ fprintf(stderr, "testdcb : creating buffer with type DCB_ROLE_INTERNAL"); - dcb = dcb_alloc(DCB_ROLE_INTERNAL, &dummy); + dcb = dcb_alloc(DCB_ROLE_INTERNAL, dummy); printDCB(dcb); fprintf(stderr, "\t..done\nAllocated dcb."); // TODO: Without running workers, the following will hang. As it does not diff --git a/server/core/test/test_poll.cc b/server/core/test/test_poll.cc index f67b1f442..d26d08534 100644 --- a/server/core/test/test_poll.cc +++ b/server/core/test/test_poll.cc @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include "test_utils.h" @@ -49,7 +49,7 @@ static int test1() DCB* dcb; int result; int eno = 0; - SERV_LISTENER dummy; + SERV_LISTENER* dummy = nullptr; SERVICE service; service.routerModule = (char*)"required by a check in dcb.cc"; @@ -59,7 +59,7 @@ static int test1() "testpoll : Initialise the polling system."); init_test_env(NULL); fprintf(stderr, "\t..done\nAdd a DCB"); - dcb = dcb_alloc(DCB_ROLE_CLIENT_HANDLER, &dummy); + dcb = dcb_alloc(DCB_ROLE_CLIENT_HANDLER, dummy); if (dcb == NULL) { diff --git a/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.cc b/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.cc index 9b890e4ec..9ac822fc9 100644 --- a/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.cc +++ b/server/modules/authenticator/CDCPlainAuth/cdc_plain_auth.cc @@ -556,8 +556,6 @@ int cdc_replace_users(SERV_LISTENER* listener) int i = cdc_read_users(newusers, path); USERS* oldusers = NULL; - pthread_mutex_lock(&listener->lock); - if (i > 0) { /** Successfully loaded at least one user */ @@ -578,8 +576,6 @@ int cdc_replace_users(SERV_LISTENER* listener) cdc_set_service_user(listener); - pthread_mutex_unlock(&listener->lock); - if (oldusers) { users_free(oldusers); diff --git a/server/modules/authenticator/MySQLAuth/mysql_auth.cc b/server/modules/authenticator/MySQLAuth/mysql_auth.cc index 6be26757e..21b5470ef 100644 --- a/server/modules/authenticator/MySQLAuth/mysql_auth.cc +++ b/server/modules/authenticator/MySQLAuth/mysql_auth.cc @@ -635,8 +635,8 @@ static int mysql_auth_load_users(SERV_LISTENER* port) { MXS_ERROR("[%s] Unable to load users for listener %s listening at [%s]:%d.", service->name, - port->name, - port->address ? port->address : "::", + port->name.c_str(), + !port->address.empty() ? port->address.c_str() : "::", port->port); } @@ -673,7 +673,7 @@ static int mysql_auth_load_users(SERV_LISTENER* port) } else if (loaded > 0 && first_load) { - MXS_NOTICE("[%s] Loaded %d MySQL users for listener %s.", service->name, loaded, port->name); + MXS_NOTICE("[%s] Loaded %d MySQL users for listener %s.", service->name, loaded, port->name.c_str()); } return rc; diff --git a/server/modules/protocol/HTTPD/httpd.cc b/server/modules/protocol/HTTPD/httpd.cc index 6be53640e..1a16ee1f8 100644 --- a/server/modules/protocol/HTTPD/httpd.cc +++ b/server/modules/protocol/HTTPD/httpd.cc @@ -206,7 +206,7 @@ static int httpd_read_event(DCB* dcb) /** If listener->authenticator is the default authenticator, it means that * we don't need to check the user credentials. All other authenticators * cause a 401 Unauthorized to be returned on the first try. */ - bool auth_ok = strcmp(httpd_default_auth(), dcb->listener->authenticator) == 0; + bool auth_ok = httpd_default_auth() == dcb->listener->authenticator; /** * Get the request headers