/** * Copyright (c) 2021 OceanBase * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX RPC_OBMYSQL #include "rpc/obmysql/ob_mysql_packet.h" #include "lib/utility/ob_macro_utils.h" #include "rpc/obmysql/ob_mysql_util.h" using namespace oceanbase::common; using namespace oceanbase::obmysql; namespace oceanbase { namespace obmysql { int ObMySQLPacket::encode_packet(char *buf, int64_t &len, int64_t &pos, const ObMySQLPacket &pkt) { int ret = OB_SUCCESS; if (OB_ISNULL(buf) || len <= 0 || pos < 0) { LOG_WARN("invalid buf or len", KP(buf), K(len), K(pos), K(ret)); ret = OB_INVALID_ARGUMENT; } else { int64_t seri_size = 0; if (OB_FAIL(pkt.encode(buf + pos, len, seri_size))) { LOG_WARN("serialize response packet fail", K(ret)); } else { len -= seri_size; pos += seri_size; } } return ret; } int ObMySQLPacket::encode(char *buffer, int64_t length, int64_t &pos) const { int ret = OB_SUCCESS; if (OB_ISNULL(buffer) || 0 >= length || pos < 0) { LOG_WARN("invalid argument", KP(buffer), K(length), K(pos)); ret = OB_INVALID_ARGUMENT; } else { const int64_t orig_pos = pos; pos += OB_MYSQL_HEADER_LENGTH; if (OB_FAIL(serialize(buffer, length, pos))) { LOG_WARN("encode packet data failed", K(ret)); } else { int32_t payload = static_cast(pos - orig_pos - OB_MYSQL_HEADER_LENGTH); pos = orig_pos; if (OB_FAIL(ObMySQLUtil::store_int3(buffer, length, payload, pos))) { LOG_ERROR("failed to encode int", K(ret)); // OB_ASSERT(false); } else if (OB_FAIL(ObMySQLUtil::store_int1(buffer, length, hdr_.seq_, pos))) { LOG_ERROR("failed to encode int", K(ret)); // OB_ASSERT(false); } else { pos += payload; } } if (OB_FAIL(ret)) { pos = orig_pos; } } return ret; } int64_t ObMySQLPacket::get_serialize_size() const { BACKTRACE(ERROR, 1, "not a serializiable packet"); return -1; } int64_t ObMySQLRawPacket::get_serialize_size() const { return static_cast(get_clen()) + 1; // add 1 for cmd_ } // serialize content in string by default int ObMySQLRawPacket::serialize(char *buf, const int64_t length, int64_t &pos) const { int ret = OB_SUCCESS; if (OB_UNLIKELY(NULL == buf || length <= 0 || pos < 0 || length - pos < get_serialize_size() || NULL == cdata_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KP(buf), K(length), K(get_serialize_size()), K(pos), K(ret)); } else if (OB_FAIL(ObMySQLUtil::store_int1(buf, length, cmd_, pos))) { LOG_WARN("fail to store cmd", K(length), K(cmd_), K(pos), K(ret)); } else if (OB_FAIL(ObMySQLUtil::store_str_vnzt(buf, length, get_cdata(), get_clen(), pos))) { LOG_WARN("fail to store content", K(length), K(get_cdata()), K(get_clen()), K(pos), K(ret)); } return ret; } int ObMySQLRawPacket::encode_packet_meta(char *buf, int64_t &len, int64_t &pos) const { int ret = OB_SUCCESS; // healder len + cmd len = 4 + 1 = 5 if (OB_UNLIKELY(NULL == buf || len <= 0 || pos < 0 || len - pos < 5)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", KP(buf), K(len), K(pos), K(ret)); } else { int32_t payload = 1 + hdr_.len_; // payload = cmd + request = 1 + hdr_.len if (OB_FAIL(ObMySQLUtil::store_int3(buf, len, payload, pos))) { LOG_ERROR("failed to encode int", K(ret)); } else if (OB_FAIL(ObMySQLUtil::store_int1(buf, len, hdr_.seq_, pos))) { LOG_ERROR("failed to encode int", K(ret)); } else if (OB_FAIL(ObMySQLUtil::store_int1(buf, len, cmd_, pos))) { LOG_WARN("fail to store cmd", K(len), K(cmd_), K(pos), K(ret)); } } return ret; } char const *get_info_func_name(const ObInformationFunctions func) { const char *str = NULL; static const char *func_name_array[MAX_INFO_FUNC] = { "benchmark", "charset", "coercibility", "coliation", "connection_id", "current_user", "database", "found_rows", "last_insert_id", "row_count", "schema", "session_user", "system user", "user", "version", }; if (func >= BENCHMARK_FUNC && func < MAX_INFO_FUNC) { str = func_name_array[func]; } return str; } char const *get_mysql_cmd_str(ObMySQLCmd mysql_cmd) { const char *str = "invalid"; static const char *mysql_cmd_array[OB_MYSQL_COM_MAX_NUM] = { "Sleep", // OB_MYSQL_COM_SLEEP, "Quit", // OB_MYSQL_COM_QUIT, "Init DB", // OB_MYSQL_COM_INIT_DB, "Query", // OB_MYSQL_COM_QUERY, "Field List", // OB_MYSQL_COM_FIELD_LIST, "Create DB", // OB_MYSQL_COM_CREATE_DB, "Drop DB", // OB_MYSQL_COM_DROP_DB, "Refresh", // OB_MYSQL_COM_REFRESH, "Shutdown", // OB_MYSQL_COM_SHUTDOWN, "Statistics", // OB_MYSQL_COM_STATISTICS, "Process Info", // OB_MYSQL_COM_PROCESS_INFO, "Connect", // OB_MYSQL_COM_CONNECT, "Process Kill", // OB_MYSQL_COM_PROCESS_KILL, "Debug", // OB_MYSQL_COM_DEBUG, "Ping", // OB_MYSQL_COM_PING, "Time", // OB_MYSQL_COM_TIME, "Delayed insert", // OB_MYSQL_COM_DELAYED_INSERT, "Change user", // OB_MYSQL_COM_CHANGE_USER, "Binlog dump", // OB_MYSQL_COM_BINLOG_DUMP, "Table dump", // OB_MYSQL_COM_TABLE_DUMP, "Connect out", // OB_MYSQL_COM_CONNECT_OUT, "Register slave", // OB_MYSQL_COM_REGISTER_SLAVE, "Prepare", // OB_MYSQL_COM_STMT_PREPARE, "Execute", // OB_MYSQL_COM_STMT_EXECUTE, "Stmt send long data", // OB_MYSQL_COM_STMT_SEND_LONG_DATA, "Close stmt", // OB_MYSQL_COM_STMT_CLOSE, "Stmt reset", // OB_MYSQL_COM_STMT_RESET, "Set option", // OB_MYSQL_COM_SET_OPTION, "Stmt fetch", // OB_MYSQL_COM_STMT_FETCH, "Daemno", // OB_MYSQL_COM_DAEMON, "Binlog dump gtid", // OB_MYSQL_COM_BINLOG_DUMP_GTID, // "Reset connection", // COM_RESET_CONNECTION, "Prepare Execute", // OB_MYSQL_COM_STMT_PREPARE_EXECUTE, "SEND PIECE DATA", "GET PIECE DATA", "End", // OB_MYSQL_COM_END, "Delete session", // OB_MYSQL_COM_DELETE_SESSION "Handshake", // OB_MYSQL_COM_HANDSHAKE, "Login" // OB_MYSQL_COM_LOGIN, }; if (mysql_cmd >= OB_MYSQL_COM_SLEEP && mysql_cmd <= OB_MYSQL_COM_BINLOG_DUMP_GTID) { str = mysql_cmd_array[mysql_cmd]; } else if (mysql_cmd >= OB_MYSQL_COM_STMT_PREPARE_EXECUTE && mysql_cmd <= OB_MYSQL_COM_END) { int start = OB_MYSQL_COM_BINLOG_DUMP_GTID + 1; str = mysql_cmd_array[mysql_cmd - OBPROXY_NEW_MYSQL_CMD_START + start]; } else if (mysql_cmd > OB_MYSQL_COM_END && mysql_cmd < OB_MYSQL_COM_MAX_NUM) { int start = OB_MYSQL_COM_BINLOG_DUMP_GTID + 1 + OB_MYSQL_COM_END - OB_MYSQL_COM_STMT_PREPARE_EXECUTE + 1; str = mysql_cmd_array[mysql_cmd - OBPROXY_MYSQL_CMD_START + start]; } return str; } } // end of namespace obmysql } // end of namespace oceanbase