From 7e21e3aedd4efba890419480a25ac080d0545ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 26 Oct 2018 11:01:03 +0300 Subject: [PATCH] MXS-2115: Fix handshake version string The intention was to send the lowest backend version string automatically to the client instead of the default handshake version. This did not work as the service version string was used instead of the server version. --- maxscale-system-test/CMakeLists.txt | 3 ++ .../mxs2115_version_string.cpp | 21 +++++++++ .../MySQL/mariadbclient/mysql_client.cc | 44 ++++++++++++------- 3 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 maxscale-system-test/mxs2115_version_string.cpp diff --git a/maxscale-system-test/CMakeLists.txt b/maxscale-system-test/CMakeLists.txt index 994fa48e2..0ddff7c5b 100644 --- a/maxscale-system-test/CMakeLists.txt +++ b/maxscale-system-test/CMakeLists.txt @@ -981,6 +981,9 @@ add_test_executable(mxs2043_select_for_update.cpp mxs2043_select_for_update repl # MXS-2054: Hybrid clusters add_test_executable(mxs2054_hybrid_cluster.cpp mxs2054_hybrid_cluster mxs2054_hybrid_cluster LABELS REPL_BACKEND) +# MXS-2115: Automatic version_string detection +add_test_executable(mxs2115_version_string.cpp mxs2115_version_string replication LABELS REPL_BACKEND) + configure_file(templates.h.in templates.h @ONLY) include(CTest) diff --git a/maxscale-system-test/mxs2115_version_string.cpp b/maxscale-system-test/mxs2115_version_string.cpp new file mode 100644 index 000000000..48530c3ae --- /dev/null +++ b/maxscale-system-test/mxs2115_version_string.cpp @@ -0,0 +1,21 @@ +/** + * MXS-2115: Automatic version string detection doesn't work + * + * When servers are available, the backend server and Maxscale should return the + * same version string. + */ + +#include "testconnections.h" + +int main(int argc, char **argv) +{ + TestConnections test(argc, argv); + test.repl->connect(); + test.maxscales->connect(); + + std::string direct = mysql_get_server_info(test.repl->nodes[0]); + std::string mxs = mysql_get_server_info(test.maxscales->conn_rwsplit[0]); + test.expect(direct == mxs, "MaxScale sends wrong version: %s != %s", direct.c_str(), mxs.c_str()); + + return test.global_result; +} diff --git a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc index 12d81dbd0..2f79a36c6 100644 --- a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc +++ b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc @@ -196,6 +196,29 @@ static char *gw_default_auth() return (char*)"MySQLAuth"; } +std::string get_version_string(SERVICE* service) +{ + std::string rval; + uint64_t intver = UINT64_MAX; + + for (SERVER_REF* ref = service->dbref; ref; ref = ref->next) + { + if (ref->server->version && ref->server->version < intver) + { + rval = ref->server->version_string; + intver = ref->server->version; + } + } + + // Get the version string from service if no server version is available + if (rval.empty()) + { + rval = service->version_string[0] ? service->version_string : GW_MYSQL_VERSION; + } + + return rval; +} + /** * MySQLSendHandshake * @@ -222,8 +245,6 @@ int MySQLSendHandshake(DCB* dcb) uint8_t mysql_filler_ten[10] = {}; /* uint8_t mysql_last_byte = 0x00; not needed */ char server_scramble[GW_MYSQL_SCRAMBLE_SIZE + 1] = ""; - char *version_string; - int len_version_string = 0; bool is_maria = false; @@ -240,18 +261,7 @@ int MySQLSendHandshake(DCB* dcb) MySQLProtocol *protocol = DCB_PROTOCOL(dcb, MySQLProtocol); GWBUF *buf; - - /* get the version string from service property if available*/ - if (dcb->service->version_string[0]) - { - version_string = dcb->service->version_string; - len_version_string = strlen(version_string); - } - else - { - version_string = (char*)GW_MYSQL_VERSION; - len_version_string = strlen(GW_MYSQL_VERSION); - } + std::string version = get_version_string(dcb->service); gw_generate_random_str(server_scramble, GW_MYSQL_SCRAMBLE_SIZE); @@ -285,7 +295,7 @@ int MySQLSendHandshake(DCB* dcb) int plugin_name_len = strlen(plugin_name); mysql_payload_size = - sizeof(mysql_protocol_version) + (len_version_string + 1) + sizeof(mysql_thread_id_num) + 8 + + sizeof(mysql_protocol_version) + (version.length() + 1) + sizeof(mysql_thread_id_num) + 8 + sizeof(/* mysql_filler */ uint8_t) + sizeof(mysql_server_capabilities_one) + sizeof(mysql_server_language) + sizeof(mysql_server_status) + sizeof(mysql_server_capabilities_two) + sizeof(mysql_scramble_len) + sizeof(mysql_filler_ten) + 12 + sizeof(/* mysql_last_byte */ uint8_t) + plugin_name_len + @@ -314,8 +324,8 @@ int MySQLSendHandshake(DCB* dcb) mysql_handshake_payload = mysql_handshake_payload + sizeof(mysql_protocol_version); // write server version plus 0 filler - strcpy((char *)mysql_handshake_payload, version_string); - mysql_handshake_payload = mysql_handshake_payload + len_version_string; + strcpy((char *)mysql_handshake_payload, version.c_str()); + mysql_handshake_payload = mysql_handshake_payload + version.length(); *mysql_handshake_payload = 0x00;