简化协议,

/**
 * Request
 * Cmd: 	| OP(1) | argc(1) | repeat { arglen(4) | arg } |
 *
 * Response
 * Rsp:		| OP(1) | status(1) | datalen(4) | data |
 */

封装客户端进行批处理和单条命令测试。
This commit is contained in:
2026-01-06 19:16:12 +08:00
parent 0dc86f5aa5
commit 144b374aa2
13 changed files with 815 additions and 634 deletions

View File

@@ -62,195 +62,125 @@ int kvs_write_u32(uint8_t **pp, const uint8_t *end, uint32_t v) {
}
// return: -1 fail, 0 half, >0 consumed
int kvs_parse_request(const uint8_t *msg, int length, kvs_request_t *req_out) {
if (!msg || length <= 0 || !req_out) return -1;
memset(req_out, 0, sizeof(*req_out));
int kvs_parse_one_cmd(const uint8_t *request, int request_length, kvs_req_t *req_out){
if (!request || request_length <= 0 || !req_out) return -1;
req_out->op = 0;
req_out->argc = 0;
req_out->args = NULL;
if(length < KVS_HDR_LEN) return 0;
const uint8_t *p = request;
const uint8_t *end = request + (size_t)request_length;
// header parser
uint32_t magic_be;
memcpy(&magic_be, msg, 4);
uint32_t magic = ntohl(magic_be);
if (magic != KVS_MAGIC) return -1;
// OP + ARGC
if (kvs_need(p, end, 2)) {
return 0; // NEED_MORE
}
//
uint8_t type = *(msg+4);
uint8_t op = 0, argc = 0;
if (kvs_read_u8(&p, end, &op) < 0) return -1;
if (kvs_read_u8(&p, end, &argc) < 0) return -1;
uint32_t payloadlen_be;
memcpy(&payloadlen_be, msg+5, 4);
uint32_t payloadlen = ntohl(payloadlen_be);
if (argc > KVS_MAX_ARGC) return -1;
uint32_t reqId_be;
memcpy(&reqId_be, msg + 9, 4);
uint32_t reqId = ntohl(reqId_be);
uint8_t flag1 = *(msg + 13);
uint16_t flag2_be;
memcpy(&flag2_be, msg + 14, 2);
uint16_t flag2 = ntohs(flag2_be);
uint32_t totalLen = (uint32_t)KVS_HDR_LEN + payloadlen;
if ((uint32_t)length < totalLen) return 0; // 半包
// payload parser
const uint8_t *ptr = msg + KVS_HDR_LEN;
const uint8_t *end = ptr + payloadlen;
uint32_t opcount = 0;
if(kvs_read_u32(&ptr, end, &opcount) < 0) return -1;
if (opcount > KVS_MAX_OPCOUNT) return -1;
kvs_op_t *ops = (kvs_op_t *)kvs_malloc(sizeof(kvs_op_t) * opcount);
if (!ops) return -1;
memset(ops, 0, sizeof(kvs_op_t) * opcount);
// operator parser
for (uint32_t i = 0; i < opcount; i++) {
uint8_t op = 0;
uint32_t argc = 0;
if (kvs_read_u8(&ptr, end, &op) < 0) goto FAIL;
if (kvs_read_u32(&ptr, end, &argc) < 0) goto FAIL;
if (argc > 16) goto FAIL;
char **argv = NULL;
if (argc > 0) {
argv = (char **)kvs_malloc(sizeof(char*) * argc);
if (!argv) goto FAIL;
memset(argv, 0, sizeof(char*) * argc);
}
// operator args parser
for (uint32_t a = 0; a < argc; a++) {
uint32_t arglen = 0;
if (kvs_read_u32(&ptr, end, &arglen) < 0) goto FAIL;
if (kvs_need(ptr, end, arglen) < 0) goto FAIL;
char *s = (char *)kvs_malloc((size_t)arglen + 1);
if (!s) goto FAIL;
memcpy(s, ptr, arglen);
s[arglen] = '\0';
argv[a] = s;
ptr += arglen;
}
ops[i].op = op;
ops[i].argc = argc;
ops[i].argv = argv;
}
req_out->magic = magic;
req_out->type = type;
req_out->payloadLen = payloadlen;
req_out->reqId = reqId;
req_out->flag1 = flag1;
req_out->flag2 = flag2;
req_out->opcount = opcount;
req_out->ops = ops;
req_out->consumed = totalLen;
return (int)totalLen;
FAIL:
if (ops) {
for (uint32_t i = 0; i < opcount; i++) {
if (ops[i].argv) {
for (uint32_t a = 0; a < ops[i].argc; a++) {
if (ops[i].argv[a]) kvs_free(ops[i].argv[a]);
}
kvs_free(ops[i].argv);
// 先扫描一遍确认整条命令数据都在 buffer 里
const uint8_t *scan = p;
uint32_t lens[KVS_MAX_ARGC];
if (argc > 0) {
for (uint8_t i = 0; i < argc; i++) {
if (kvs_need(scan, end, 4)) {
return 0; // NEED_MORE
}
}
kvs_free(ops);
}
return -1;
}
uint32_t alen = 0;
if (kvs_read_u32(&scan, end, &alen) < 0) return -1;
void kvs_free_request(kvs_request_t *req) {
if (!req) return;
if (req->ops) {
for (uint32_t i = 0; i < req->opcount; i++) {
if (req->ops[i].argv) {
for (uint32_t a = 0; a < req->ops[i].argc; a++) {
if (req->ops[i].argv[a]) kvs_free(req->ops[i].argv[a]);
}
kvs_free(req->ops[i].argv);
// 防御:单个参数长度限制
if (alen > KVS_MAX_ARGLEN) return -1;
// 防御scan + alen 越界 / 半包
if (kvs_need(scan, end, (size_t)alen)) {
return 0; // NEED_MORE
}
}
kvs_free(req->ops);
lens[i] = alen;
scan += alen;
}
}
memset(req, 0, sizeof(*req));
size_t total_len = (size_t)(scan - request);
if (total_len > KVS_MAX_CMD_BYTES) return -1;
req_out->op = op;
req_out->argc = argc;
if (argc == 0) {
return (int)total_len;
}
kvs_arg_t *args = (kvs_arg_t *)kvs_malloc((size_t)argc * sizeof(kvs_arg_t));
if (!args) {
kvs_free_request(req_out);
return -1;
}
memset(args, 0, (size_t)argc * sizeof(kvs_arg_t));
for (uint8_t i = 0; i < argc; i++) {
uint32_t alen = 0;
if (kvs_read_u32(&p, end, &alen) < 0) {
kvs_free(args);
kvs_free_request(req_out);
return -1;
}
// alen 与 lens[i] 应当一致(扫描时读过),不一致说明解析器/输入异常
if (alen != lens[i]) {
kvs_free(args);
kvs_free_request(req_out);
return -1;
}
args[i].len = alen;
args[i].data = p; // 直接指向输入 buffer零拷贝
p += alen;
}
req_out->args = args;
return (int)(p - request);
}
int kvs_execute_request(const kvs_request_t *req, kvs_response_t *results /* size opcount */) {
if (!req || !results) return -1;
for (uint32_t i = 0; i < req->opcount; i++) {
uint8_t status = KVS_STATUS_ERROR;
const char *data = NULL;
uint32_t dlen = 0;
kvs_exec_one_op(req->ops[i].op, req->ops[i].argc, req->ops[i].argv,
&status, &data, &dlen);
results[i].status = status;
results[i].datalen = dlen;
results[i].data_ptr = data;
}
return 0;
void kvs_free_request(kvs_req_t *req) {
if (!req) return;
if (req->args) {
kvs_free(req->args);
req->args = NULL;
}
req->op = 0;
req->argc = 0;
}
int kvs_build_one_rsp(const kvs_rsp_t *results, uint8_t *response, size_t response_cap){
if (!results || !response) return -1;
int kvs_build_response(const kvs_request_t *req,
const kvs_response_t *results,
uint8_t *response, int response_cap) {
if (!req || !results || !response || response_cap < KVS_HDR_LEN) return -1;
const uint8_t *end = response + response_cap;
uint8_t *p = response;
uint8_t *out = response;
uint8_t *w = out + KVS_HDR_LEN;
const uint8_t *w_end = out + response_cap;
// 计算所需长度1 + 1 + 4 + dlen
// 注意防止 size_t 溢出
size_t need = 1u + 1u + 4u + (size_t)results->dlen;
if (need > response_cap) return -1;
// payload: opcount
if (kvs_write_u32(&w, w_end, req->opcount) < 0) return -1;
if (kvs_write_u8(&p, end, results->op) < 0) return -1;
if (kvs_write_u8(&p, end, results->status) < 0) return -1;
if (kvs_write_u32(&p, end, results->dlen) < 0) return -1;
for (uint32_t i = 0; i < req->opcount; i++) {
if (kvs_write_u8(&w, w_end, results[i].status) < 0) return -1;
if (kvs_write_u32(&w, w_end, results[i].datalen) < 0) return -1;
if (results->dlen > 0) {
if (!results->data) return -1; // 有长度却没指针,视为错误
if (kvs_need(p, end, (size_t)results->dlen) < 0) return -1;
memcpy(p, results->data, results->dlen);
p += results->dlen;
}
if (results[i].datalen > 0) {
if (kvs_need(w, w_end, results[i].datalen) < 0) return -1;
memcpy(w, results[i].data_ptr, results[i].datalen);
w += results[i].datalen;
}
}
uint32_t respPayloadLen = (uint32_t)(w - (out + KVS_HDR_LEN));
uint32_t total = KVS_HDR_LEN + respPayloadLen;
// header
{
uint32_t be = htonl(KVS_MAGIC);
memcpy(out + 0, &be, 4);
}
out[4] = (uint8_t)KVS_TYPE_RESP;
{
uint32_t be = htonl(respPayloadLen);
memcpy(out + 5, &be, 4);
}
{
uint32_t be = htonl(req->reqId);
memcpy(out + 9, &be, 4);
}
out[13] = req->flag1;
{
uint16_t be = htons(req->flag2);
memcpy(out + 14, &be, 2);
}
return (int)total;
return (int)(p - response);
}