From 1b872c246dec1c4a8b8d79b5eca303a18c849e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B4=94=E4=B8=80=E9=B8=A3?= Date: Wed, 29 May 2019 14:36:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0tfe=5Fcmsg=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E7=B1=BB,=E7=94=A8=E4=BA=8E=E5=BA=8F=E5=88=97=E5=8C=96/?= =?UTF-8?q?=E5=8F=8D=E5=BA=8F=E5=88=97=E5=8C=96=E6=8E=A7=E5=88=B6=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/CMakeLists.txt | 7 +- common/include/tfe_cmsg.h | 36 +++++++ common/src/tfe_cmsg.cpp | 201 ++++++++++++++++++++++++++++++++++++++ common/test/test_cmsg.cpp | 50 ++++++++++ 4 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 common/include/tfe_cmsg.h create mode 100644 common/src/tfe_cmsg.cpp create mode 100644 common/test/test_cmsg.cpp diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f9ce851..6c811d7 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(common src/tfe_utils.cpp src/tfe_types.cpp src/tfe_future.cpp src/tfe_http.cpp src/tfe_plugin.cpp src/tfe_rpc.cpp) +add_library(common src/tfe_utils.cpp src/tfe_types.cpp src/tfe_future.cpp src/tfe_http.cpp src/tfe_plugin.cpp src/tfe_rpc.cpp src/tfe_cmsg.cpp) target_include_directories(common PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) target_link_libraries(common PUBLIC libevent-static libevent-static-openssl libevent-static-pthreads) target_link_libraries(common PUBLIC MESA_handle_logger) @@ -10,3 +10,8 @@ target_link_libraries(test-addr PRIVATE gtest MESA_handle_logger) include(GoogleTest) gtest_discover_tests(test-addr) + +### test_cmsg +add_executable(test_cmsg test/test_cmsg.cpp) +target_include_directories(test_cmsg PRIVATE include) +target_link_libraries(test_cmsg PRIVATE common) diff --git a/common/include/tfe_cmsg.h b/common/include/tfe_cmsg.h new file mode 100644 index 0000000..fcf09a5 --- /dev/null +++ b/common/include/tfe_cmsg.h @@ -0,0 +1,36 @@ +#pragma once + +#define TFE_CMSG_TLV_NR_MAX 64 +struct tfe_cmsg; +struct tfe_cmsg_serialize_header; + + +enum tfe_cmsg_errno +{ + TFE_CMSG_INVALID_FORMAT = -1, + TFE_CMSG_BUFF_NOT_ENOUGH = -2, + TFE_CMSG_INVALID_TYPE = -3 +}; + +enum tfe_cmsg_tlv_type +{ + TCP_RESTORE_INFO_TLV_SEQ = 0, + TCP_RESTORE_INFO_TLV_ACK, + TCP_RESTORE_INFO_TLV_MSS_CLIENT, + TCP_RESTORE_INFO_TLV_MSS_SERVER, + TCP_RESTORE_INFO_TLV_WSACLE_CLIENT, + TCP_RESTORE_INFO_TLV_WSACLE_SERVER, + TCP_RESTORE_INFO_TLV_SACK_CLIENT, + TCP_RESTORE_INFO_TLV_SACK_SERVER, + TCP_RESTORE_INFO_TLV_TS_CLIENT, + TCP_RESTORE_INFO_TLV_TS_SERVER, + TCP_RESTORE_INFO_TLV_USER_DEFINED +}; + +struct tfe_cmsg* tfe_cmsg_init(); +void tfe_cmsg_destroy(struct tfe_cmsg *cmsg); +int tfe_cmsg_get(struct tfe_cmsg *cmsg, uint16_t type, uint16_t *size, unsigned char **pvalue); +int tfe_cmsg_set(struct tfe_cmsg *cmsg, uint16_t type, const unsigned char *value, uint16_t size); +uint16_t tfe_cmsg_serialize_size_get(struct tfe_cmsg *cmsg); +int tfe_cmsg_serialize(struct tfe_cmsg *cmsg, unsigned char *buff, uint16_t bufflen, uint16_t *serialize_len); +int tfe_cmsg_deserialize(const unsigned char *data, uint16_t len, struct tfe_cmsg** pcmsg); diff --git a/common/src/tfe_cmsg.cpp b/common/src/tfe_cmsg.cpp new file mode 100644 index 0000000..fcd3683 --- /dev/null +++ b/common/src/tfe_cmsg.cpp @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include "tfe_types.h" +#include "tfe_utils.h" +#include "tfe_cmsg.h" + +struct tfe_cmsg_tlv +{ + uint16_t type; + uint16_t length; + union + { + uint8_t value_as_uint8[0]; + uint16_t value_as_uint16[0]; + uint32_t value_as_uint32[0]; + unsigned char value_as_string[0]; + }; +} __attribute__((packed)); + +struct tfe_cmsg +{ + uint16_t nr_tlvs; + struct tfe_cmsg_tlv* tlvs[TFE_CMSG_TLV_NR_MAX]; + uint16_t size; +} __attribute__((packed)); + +struct tfe_cmsg_serialize_header +{ + uint8_t __magic__[2]; /* Must be 0x4d, 0x5a */ + uint16_t nr_tlvs; + struct tfe_cmsg_tlv tlvs[0]; +} __attribute__((packed)); + +struct tfe_cmsg* tfe_cmsg_init() +{ + struct tfe_cmsg *cmsg = ALLOC(struct tfe_cmsg, 1); + cmsg->size = sizeof(struct tfe_cmsg_serialize_header); + return cmsg; +} + +void tfe_cmsg_destroy(struct tfe_cmsg *cmsg) +{ + if(cmsg != NULL) + { + for(int i = 0; i < TFE_CMSG_TLV_NR_MAX; i++) + { + FREE(&(cmsg->tlvs[i])); + } + } + FREE(&cmsg); +} + +int tfe_cmsg_set(struct tfe_cmsg *cmsg, uint16_t type, const unsigned char *value, uint16_t size) +{ + if(type >= TFE_CMSG_TLV_NR_MAX) + { + return TFE_CMSG_INVALID_TYPE; + } + struct tfe_cmsg_tlv *tlv = cmsg->tlvs[type]; + uint16_t length = sizeof(struct tfe_cmsg_tlv) + size; + if(tlv == NULL) + { + tlv = (struct tfe_cmsg_tlv*)ALLOC(char, length); + cmsg->nr_tlvs++; + cmsg->size += length; + } + tlv->type = type; + tlv->length = length; + memcpy(tlv->value_as_string, value, size); + cmsg->tlvs[type] = tlv; + return 0; +} + +int tfe_cmsg_get(struct tfe_cmsg *cmsg, uint16_t type, uint16_t *size, unsigned char **pvalue) +{ + struct tfe_cmsg_tlv *tlv = NULL; + if(type >= TFE_CMSG_TLV_NR_MAX || (tlv = cmsg->tlvs[type]) == NULL) + { + *size = 0; + return TFE_CMSG_INVALID_TYPE; + } + *size = tlv->length - sizeof(struct tfe_cmsg_tlv); + *pvalue = tlv->value_as_string; + return 0; +} + +uint16_t tfe_cmsg_serialize_size_get(struct tfe_cmsg *cmsg) +{ + return cmsg->size; +} + +int tfe_cmsg_serialize(struct tfe_cmsg *cmsg, unsigned char *buff, uint16_t bufflen, uint16_t *serialize_len) +{ + //size是serialize之后的实际长度 + uint16_t size = cmsg->size; + //传入buff是否够长 + if(bufflen < size) + { + return TFE_CMSG_BUFF_NOT_ENOUGH; + } + //size是否正确 + if(size < sizeof(struct tfe_cmsg_serialize_header)) + { + return TFE_CMSG_INVALID_FORMAT; + } + struct tfe_cmsg_serialize_header *header = (struct tfe_cmsg_serialize_header*)buff; + header->__magic__[0] = 0x4d; + header->__magic__[1] = 0x5a; + header->nr_tlvs = htons(cmsg->nr_tlvs); + uint16_t offset = sizeof(struct tfe_cmsg_serialize_header); + //检查nr_tlvs是否合法 + int count = 0; + for(int i = 0; i < TFE_CMSG_TLV_NR_MAX; i++){ + if(cmsg->tlvs[i] != NULL) + { + count++; + } + } + if(count != cmsg->nr_tlvs) + { + return TFE_CMSG_INVALID_FORMAT; + } + //序列化 + for(int i = 0; i < TFE_CMSG_TLV_NR_MAX; i++) + { + struct tfe_cmsg_tlv *tlv = cmsg->tlvs[i]; + if(tlv == NULL) + { + continue; + } + if(i != tlv->type) + { + return TFE_CMSG_INVALID_FORMAT; + } + uint16_t length = tlv->length; + if(length < sizeof(struct tfe_cmsg_tlv) || offset + length > size) + { + return TFE_CMSG_INVALID_FORMAT; + } + memcpy((char*)header + offset, (void*)tlv, length); + struct tfe_cmsg_tlv *tlv1 = (struct tfe_cmsg_tlv*)((char*)header + offset); + tlv1->type = htons(tlv->type); + tlv1->length = htons(tlv->length); + offset += length; + } + //检查size是否正确 + if(offset != size) + { + return TFE_CMSG_INVALID_FORMAT; + } + *serialize_len = size; + return 0; +} + +//反序列化 +int tfe_cmsg_deserialize(const unsigned char *data, uint16_t len, struct tfe_cmsg** pcmsg) +{ + struct tfe_cmsg_serialize_header *header = (struct tfe_cmsg_serialize_header*)data; + struct tfe_cmsg *cmsg = NULL; + int offset = 0, nr_tlvs = -1; + if(len < sizeof(struct tfe_cmsg_serialize_header)) + { + goto error_out; + } + if(header->__magic__[0] != 0x4d || header->__magic__[1] != 0x5a) + { + goto error_out; + } + cmsg = ALLOC(struct tfe_cmsg, 1); + offset = sizeof(struct tfe_cmsg_serialize_header); + nr_tlvs = ntohs(header->nr_tlvs); + for(int i = 0; i < nr_tlvs; i++) + { + struct tfe_cmsg_tlv *tlv = (struct tfe_cmsg_tlv*)(data + offset); + if(offset + sizeof(struct tfe_cmsg_tlv) > len) + { + goto error_out; + } + uint16_t type = ntohs(tlv->type); + uint16_t length = ntohs(tlv->length); + if(length < sizeof(struct tfe_cmsg_tlv) || offset + length > len) + { + goto error_out; + } + int ret = tfe_cmsg_set(cmsg, type, data + offset + sizeof(struct tfe_cmsg_tlv), length - sizeof(struct tfe_cmsg_tlv)); + if(ret < 0) + { + goto error_out; + } + offset += length; + } + cmsg->size = offset; + *pcmsg = cmsg; + return 0; + +error_out: + tfe_cmsg_destroy(cmsg); + return TFE_CMSG_INVALID_FORMAT; +} diff --git a/common/test/test_cmsg.cpp b/common/test/test_cmsg.cpp new file mode 100644 index 0000000..2d02d58 --- /dev/null +++ b/common/test/test_cmsg.cpp @@ -0,0 +1,50 @@ + + +#include +#include +#include +#include +#include "tfe_types.h" +#include "tfe_utils.h" +#include "tfe_cmsg.h" + +int main(){ + //init + struct tfe_cmsg *cmsg = tfe_cmsg_init(); + + //set + uint32_t value = 0x12345678; + int ret = tfe_cmsg_set(cmsg, TCP_RESTORE_INFO_TLV_SEQ, (const unsigned char*)(&value), 4); + printf("tfe_cmsg_set: ret is %d\n", ret); + + //get TCP_RESTORE_INFO_TLV_SEQ + uint16_t size = -1; + unsigned char *value1 = NULL; + ret = tfe_cmsg_get(cmsg, TCP_RESTORE_INFO_TLV_SEQ, &size, &value1); + printf("tfe_cmsg_get: ret is %d, type is TCP_RESTORE_INFO_TLV_SEQ, value is 0x%02x, value_size is %d\n", ret, ((uint32_t*)value1)[0], size); + + //get_serialize_size + size = tfe_cmsg_serialize_size_get(cmsg); + printf("tfe_cmsg_serialize_size_get: size is %d\n", size); + + //serialize + unsigned char buff[size]; + uint16_t serialize_len = -1; + ret = tfe_cmsg_serialize(cmsg, buff, size, &serialize_len); + printf("tfe_cmsg_serialize: ret is %d, serialize_len is %d, serialize result is: ", ret, serialize_len); + for(int i = 0; i < serialize_len; i++){ + printf("%02x ", buff[i]); + } + printf("\n"); + + //deserialize + struct tfe_cmsg *cmsg1 = NULL; + ret = tfe_cmsg_deserialize(buff, serialize_len, &cmsg1); + printf("tfe_cmsg_deserialize: ret is %d\n", ret); + + //get TCP_RESTORE_INFO_TLV_SEQ + size = -1; + unsigned char *value2 = NULL; + ret = tfe_cmsg_get(cmsg1, TCP_RESTORE_INFO_TLV_SEQ, &size, &value2); + printf("tfe_cmsg_get: ret is %d, type is TCP_RESTORE_INFO_TLV_SEQ, value is 0x%02x, value_size is %d\n", ret, ((uint32_t*)value2)[0], size); +}