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.
This commit is contained in:
Markus Mäkelä 2018-10-26 11:01:03 +03:00
parent 262f1d7e47
commit 7e21e3aedd
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
3 changed files with 51 additions and 17 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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;