MXS-2512 Extend dbg_decode_response()

Now capable of decoding GWBUF containing multiple packets.
This commit is contained in:
Johan Wikman 2019-06-06 12:04:22 +03:00
parent b49aeae1c8
commit b50193a868

View File

@ -297,87 +297,85 @@ std::unique_ptr<mxq::QueryResult> execute_query(MYSQL* conn, const std::string&
*
* @return The packet decoded into a descriptive string.
*/
char* dbg_decode_response(GWBUF* pPacket)
const char* dbg_decode_response(GWBUF* pPacket)
{
uint8_t header[MYSQL_HEADER_LEN + 1];
thread_local std::string rv;
gwbuf_copy_data(pPacket, 0, sizeof(header), header);
std::stringstream ss;
uint32_t payload_len = MYSQL_GET_PAYLOAD_LEN(header);
uint32_t packet_no = MYSQL_GET_PACKET_NO(header);
mxs::Buffer b(pPacket);
int nRemaining = b.length();
auto it = b.begin();
uint32_t command = std::numeric_limits<uint32_t>::max();
if (gwbuf_length(pPacket) > MYSQL_HEADER_LEN)
while (nRemaining > MYSQL_HEADER_LEN + 1)
{
command = MYSQL_GET_COMMAND(header);
}
const int buflen = 1024; // Should be enough.
thread_local char buffer[buflen];
int len = buflen;
char* z = buffer;
int l = snprintf(z, len, "Packet no: %u, Payload len: %u", packet_no, payload_len);
z += l;
len -= l;
switch (command)
{
case 0x00:
snprintf(z, len, ", Command : OK");
break;
case 0xff:
if (!ss.str().empty())
{
l = snprintf(z, len, ", Command : ERR");
z += l;
len -= l;
uint8_t error[payload_len];
gwbuf_copy_data(pPacket, MYSQL_HEADER_LEN, payload_len, error);
uint32_t error_code = gw_mysql_get_byte2(&error[1]);
l = snprintf(z, len, ", Code: %u", error_code);
z += l;
len -= l;
const int message_index = 1 + 2 + 1 + 5;
uint8_t* pMessage = &error[message_index];
l = snprintf(z, len, ", Message : ");
z += l;
len -= l;
int message_len = payload_len - message_index;
if (message_len + 1 > len)
{
message_len = len - 1;
}
strncpy(z, (char*)pMessage, message_len);
z[message_len] = 0;
ss << "\n";
}
break;
case 0xfb:
snprintf(z, len, ", Command : GET_MORE_CLIENT_DATA");
break;
uint8_t header[MYSQL_HEADER_LEN + 1];
case std::numeric_limits<uint32_t>::max():
break;
auto start = it;
auto end = std::next(it, sizeof(header));
std::copy(it, end, header);
it = end;
default:
snprintf(z, len, ", Command : Result Set");
uint32_t payload_len = MYSQL_GET_PAYLOAD_LEN(header);
uint32_t packet_len = MYSQL_HEADER_LEN + payload_len;
uint32_t packet_no = MYSQL_GET_PACKET_NO(header);
uint32_t command = MYSQL_GET_COMMAND(header);
ss << "Packet no: " << packet_no << ", Payload len: " << payload_len;
switch (command)
{
case 0x00:
ss << ", Command : OK";
break;
case 0xff:
{
ss << ", Command : ERR";
uint8_t error[payload_len];
error[0] = *it;
end = std::next(it, sizeof(error) - 1); // -1 due to the 1 in 'header' above.
std::copy(it, end, error + 1);
uint32_t error_code = gw_mysql_get_byte2(&error[1]);
ss << ", Code: " << error_code;
const int message_index = 1 + 2 + 1 + 5;
uint8_t* pMessage = &error[message_index];
int message_len = payload_len - message_index;
ss << ", Message : ";
ss.write(reinterpret_cast<const char*>(pMessage), message_len);
}
break;
case 0xfb:
ss << ", Command : GET_MORE_CLIENT_DATA";
break;
default:
ss << ", Command : Result Set";
}
it = std::next(start, MYSQL_HEADER_LEN + payload_len);
nRemaining -= MYSQL_HEADER_LEN;
nRemaining -= payload_len;
}
return buffer;
b.release();
rv = ss.str();
return rv.c_str();
}
#endif