113 lines
4.5 KiB
C++
113 lines
4.5 KiB
C++
#include <nlohmann/json.hpp>
|
||
#include <string>
|
||
#include <cstring>
|
||
#include <cstdint>
|
||
#include <vector>
|
||
#include "native_logger.hpp"
|
||
#include "msg_handler.hpp"
|
||
#include "utils.hpp"
|
||
|
||
namespace py = pybind11;
|
||
using json = nlohmann::json;
|
||
|
||
namespace netcore {
|
||
// 打包 TCP 数据包
|
||
py::bytes make_packet(int msg_type, py::dict body_dict) {
|
||
netcore::log_debug(std::string("make_packet msg_type=") + std::to_string(msg_type));
|
||
// 1) 将 py::dict 转为 JSON 字符串
|
||
json j = netcore::py_dict_to_json(body_dict);
|
||
std::string body_str = j.dump();
|
||
|
||
// 2) 计算 body_len 和 checksum
|
||
uint32_t body_len = body_str.size();
|
||
uint32_t checksum = body_len + msg_type;
|
||
|
||
// 3) 打包头部(大端序)
|
||
std::vector<uint8_t> packet;
|
||
packet.reserve(12 + body_len);
|
||
|
||
// body_len (big-endian, 4 bytes)
|
||
packet.push_back((body_len >> 24) & 0xFF);
|
||
packet.push_back((body_len >> 16) & 0xFF);
|
||
packet.push_back((body_len >> 8) & 0xFF);
|
||
packet.push_back(body_len & 0xFF);
|
||
|
||
// msg_type (big-endian, 4 bytes)
|
||
packet.push_back((msg_type >> 24) & 0xFF);
|
||
packet.push_back((msg_type >> 16) & 0xFF);
|
||
packet.push_back((msg_type >> 8) & 0xFF);
|
||
packet.push_back(msg_type & 0xFF);
|
||
|
||
// checksum (big-endian, 4 bytes)
|
||
packet.push_back((checksum >> 24) & 0xFF);
|
||
packet.push_back((checksum >> 16) & 0xFF);
|
||
packet.push_back((checksum >> 8) & 0xFF);
|
||
packet.push_back(checksum & 0xFF);
|
||
|
||
// 4) 追加 body
|
||
packet.insert(packet.end(), body_str.begin(), body_str.end());
|
||
|
||
netcore::log_debug(std::string("make_packet done bytes=") + std::to_string(packet.size()));
|
||
return py::bytes(reinterpret_cast<const char*>(packet.data()), packet.size());
|
||
}
|
||
|
||
// 解析 TCP 数据包
|
||
py::tuple parse_packet(py::bytes data) {
|
||
// 1) 转换为 bytes view
|
||
py::buffer_info buf = py::buffer(data).request();
|
||
if (buf.size < 12) {
|
||
netcore::log_error(std::string("parse_packet too_short len=") + std::to_string(buf.size));
|
||
return py::make_tuple(py::none(), py::none());
|
||
}
|
||
|
||
const uint8_t* ptr = static_cast<const uint8_t*>(buf.ptr);
|
||
|
||
// 2) 解析头部(大端序)
|
||
uint32_t body_len = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
|
||
uint32_t msg_type = (ptr[4] << 24) | (ptr[5] << 16) | (ptr[6] << 8) | ptr[7];
|
||
uint32_t checksum = (ptr[8] << 24) | (ptr[9] << 16) | (ptr[10] << 8) | ptr[11];
|
||
|
||
// 3) 校验 checksum(可选,你现有代码不强制校验)
|
||
// if (checksum != (body_len + msg_type)) {
|
||
// return py::make_tuple(py::none(), py::none());
|
||
// }
|
||
|
||
// 4) 检查长度
|
||
uint32_t expected_len = 12 + body_len;
|
||
if (buf.size < expected_len) {
|
||
// 半包
|
||
netcore::log_warn(std::string("parse_packet incomplete got=") + std::to_string(buf.size) +
|
||
" expected=" + std::to_string(expected_len));
|
||
return py::make_tuple(py::none(), py::none());
|
||
}
|
||
|
||
// 5) 防御性检查:如果 data 比预期长,说明可能有粘包
|
||
// (只解析第一个包,忽略多余数据)
|
||
if (buf.size > expected_len) {
|
||
netcore::log_warn(std::string("parse_packet concat got=") + std::to_string(buf.size) +
|
||
" expected=" + std::to_string(expected_len) +
|
||
" body_len=" + std::to_string(body_len) +
|
||
" msg_type=" + std::to_string(msg_type));
|
||
}
|
||
|
||
// 6) 提取 body 并解析 JSON
|
||
std::string body_str(reinterpret_cast<const char*>(ptr + 12), body_len);
|
||
|
||
try {
|
||
json j = json::parse(body_str);
|
||
py::dict body_dict = netcore::json_to_py_dict(j);
|
||
return py::make_tuple(py::int_(msg_type), body_dict);
|
||
} catch (const json::parse_error& e) {
|
||
// JSON 解析失败,返回 raw(兼容你现有的逻辑)
|
||
netcore::log_error(std::string("parse_packet json_parse_error: ") + e.what());
|
||
py::dict raw_dict;
|
||
raw_dict["raw"] = body_str;
|
||
return py::make_tuple(py::int_(msg_type), raw_dict);
|
||
} catch (const std::exception& e) {
|
||
netcore::log_error(std::string("parse_packet json_parse_error: ") + e.what());
|
||
py::dict raw_dict;
|
||
raw_dict["raw"] = body_str;
|
||
return py::make_tuple(py::int_(msg_type), raw_dict);
|
||
}
|
||
}
|
||
} |