// https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_PROTOCOL.html
#define MYSQL_COM_QUERY		    3
#define MYSQL_COM_STMT_PREPARE  0x16
#define MYSQL_COM_STMT_EXECUTE  0x17
#define MYSQL_COM_STMT_CLOSE    0x19

#define MYSQL_RESPONSE_OK    0x00
#define MYSQL_RESPONSE_EOF   0xfe
#define MYSQL_RESPONSE_ERROR 0xff

#define MYSQL_PACKAGE_HEADER_LEN 4


static __always_inline
int is_mysql_query(char *buf, __u64 buf_size, __u8 *request_type) {
    if (buf_size < 5) {
        return 0;
    }
    __u8 b[5];
    bpf_read(buf, b);
    int length = (int)b[0] | (int)b[1] << 8 | (int)b[2] << 16;
    if (length+4 != buf_size || b[3] != 0) { // sequence must be 0
        return 0;
    }
    if (b[4] ==  MYSQL_COM_QUERY || b[4] == MYSQL_COM_STMT_EXECUTE) {
        *request_type = b[4];
        return 1;
    }
    if (b[4] == MYSQL_COM_STMT_CLOSE) {
        *request_type = MYSQL_COM_STMT_CLOSE;
        return 1;
    }
    if (b[4] == MYSQL_COM_STMT_PREPARE) {
        *request_type = MYSQL_COM_STMT_PREPARE;
        return 1;
    }
    return 0;
}

static __always_inline
int is_mysql_response(char *buf, __u64 buf_size, __u8 request_type, __u32 *statement_id, __u32 *status,unsigned char *error_message) {
    __u8 b[5];
    bpf_read(buf, b);
    if (b[3] < 1) { // sequence must be > 0
        return 0;
    }
    int length = (int)b[0] | (int)b[1] << 8 | (int)b[2] << 16;
    if (length == 1 || b[4] == MYSQL_RESPONSE_EOF) {
        *status = STATUS_OK;
        return 1;
    }
    if (b[4] == MYSQL_RESPONSE_OK ) {
        if (request_type == MYSQL_COM_STMT_PREPARE) {
            bpf_read(buf+5, *statement_id);
        }
        *status = STATUS_OK;
        return 1;
    }
	if (b[4] == MYSQL_RESPONSE_ERROR) {
		// MySQL错误包格式：
		// packet_length(3) + packet_number(1) + 0xff(1) + error_code(2) + sql_state_marker(1) + sql_state(5) + error_message(variable)
		__u16 error_code = 0;
//		char error_message[128] = {};
		__u8 error_message_len = 0;

		// 读取错误代码（2字节，小端序）
		if (buf_size >= 7) {
			bpf_probe_read(&error_code, sizeof(error_code), buf + 5);
			error_code = bpf_ntohs(error_code); // 转换为主机字节序
		}

		// 读取错误消息（从第13字节开始，跳过sql_state）
		if (buf_size > 13) {
			error_message_len = (__u8) (length - 9); // 总长度 - 头部(4) - 错误码(2) - sql_state(6)
			bpf_probe_read(error_message, error_message_len, buf + 13);
			error_message[error_message_len] = '\0'; // 确保字符串结束
		}
		// 输出错误信息到内核日志
		cw_bpf_debug("MySQL Error %d: %s", error_code, error_message);
		*status = STATUS_FAILED;
		return 1;
	}
	return 0;
}
