#include "kvstore.h" #include "kvs_rw_tools.h" #include int kvs_need(const uint8_t *p, const uint8_t *end, size_t n) { return (p + n <= end) ? 0 : -1; } // 注意u8类型不需要ntoh或者hton int kvs_read_u8(const uint8_t **pp, const uint8_t *end, uint8_t *out) { const uint8_t *p = *pp; if (kvs_need(p, end, 1) < 0) return -1; *out = *p; *pp = p + 1; return 0; } int kvs_read_u16(const uint8_t **pp, const uint8_t *end, uint16_t *out) { const uint8_t *p = *pp; if (kvs_need(p, end, 2) < 0) return -1; uint16_t v; memcpy(&v, p, 2); *out = ntohs(v); *pp = p + 2; return 0; } int kvs_read_u32(const uint8_t **pp, const uint8_t *end, uint32_t *out) { const uint8_t *p = *pp; if (kvs_need(p, end, 4) < 0) return -1; uint32_t v; memcpy(&v, p, 4); *out = ntohl(v); *pp = p + 4; return 0; } int kvs_write_u8(uint8_t **pp, const uint8_t *end, uint8_t v) { uint8_t *p = *pp; if (kvs_need(p, end, 1) < 0) return -1; *p = v; *pp = p + 1; return 0; } int kvs_write_u16(uint8_t **pp, const uint8_t *end, uint16_t v) { uint8_t *p = *pp; if (kvs_need(p, end, 2) < 0) return -1; uint16_t be = htons(v); memcpy(p, &be, 2); *pp = p + 2; return 0; } int kvs_write_u32(uint8_t **pp, const uint8_t *end, uint32_t v) { uint8_t *p = *pp; if (kvs_need(p, end, 4) < 0) return -1; uint32_t be = htonl(v); memcpy(p, &be, 4); *pp = p + 4; return 0; } // 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)); if(length < KVS_HDR_LEN) return 0; // header parser uint32_t magic_be; memcpy(&magic_be, msg, 4); uint32_t magic = ntohl(magic_be); if (magic != KVS_MAGIC) return -1; // uint8_t type = *(msg+4); uint32_t payloadlen_be; memcpy(&payloadlen_be, msg+5, 4); uint32_t payloadlen = ntohl(payloadlen_be); 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); } } kvs_free(ops); } 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); } } kvs_free(req->ops); } memset(req, 0, sizeof(*req)); } 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; } 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; uint8_t *out = response; uint8_t *w = out + KVS_HDR_LEN; const uint8_t *w_end = out + response_cap; // payload: opcount if (kvs_write_u32(&w, w_end, req->opcount) < 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[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; }