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. * @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); mxs::Buffer b(pPacket);
uint32_t packet_no = MYSQL_GET_PACKET_NO(header); int nRemaining = b.length();
auto it = b.begin();
uint32_t command = std::numeric_limits<uint32_t>::max(); while (nRemaining > MYSQL_HEADER_LEN + 1)
if (gwbuf_length(pPacket) > MYSQL_HEADER_LEN)
{ {
command = MYSQL_GET_COMMAND(header); if (!ss.str().empty())
{
ss << "\n";
} }
const int buflen = 1024; // Should be enough. uint8_t header[MYSQL_HEADER_LEN + 1];
thread_local char buffer[buflen]; auto start = it;
auto end = std::next(it, sizeof(header));
std::copy(it, end, header);
it = end;
int len = buflen; uint32_t payload_len = MYSQL_GET_PAYLOAD_LEN(header);
char* z = buffer; 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);
int l = snprintf(z, len, "Packet no: %u, Payload len: %u", packet_no, payload_len); ss << "Packet no: " << packet_no << ", Payload len: " << payload_len;
z += l;
len -= l;
switch (command) switch (command)
{ {
case 0x00: case 0x00:
snprintf(z, len, ", Command : OK"); ss << ", Command : OK";
break; break;
case 0xff: case 0xff:
{ {
l = snprintf(z, len, ", Command : ERR"); ss << ", Command : ERR";
z += l;
len -= l;
uint8_t error[payload_len]; uint8_t error[payload_len];
error[0] = *it;
gwbuf_copy_data(pPacket, MYSQL_HEADER_LEN, payload_len, error); 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]); uint32_t error_code = gw_mysql_get_byte2(&error[1]);
l = snprintf(z, len, ", Code: %u", error_code); ss << ", Code: " << error_code;
z += l;
len -= l;
const int message_index = 1 + 2 + 1 + 5; const int message_index = 1 + 2 + 1 + 5;
uint8_t* pMessage = &error[message_index]; uint8_t* pMessage = &error[message_index];
l = snprintf(z, len, ", Message : ");
z += l;
len -= l;
int message_len = payload_len - message_index; int message_len = payload_len - message_index;
if (message_len + 1 > len) ss << ", Message : ";
{
message_len = len - 1;
}
strncpy(z, (char*)pMessage, message_len); ss.write(reinterpret_cast<const char*>(pMessage), message_len);
z[message_len] = 0;
} }
break; break;
case 0xfb: case 0xfb:
snprintf(z, len, ", Command : GET_MORE_CLIENT_DATA"); ss << ", Command : GET_MORE_CLIENT_DATA";
break;
case std::numeric_limits<uint32_t>::max():
break; break;
default: default:
snprintf(z, len, ", Command : Result Set"); ss << ", Command : Result Set";
} }
return buffer; it = std::next(start, MYSQL_HEADER_LEN + payload_len);
nRemaining -= MYSQL_HEADER_LEN;
nRemaining -= payload_len;
}
b.release();
rv = ss.str();
return rv.c_str();
} }
#endif #endif