c - 如何在c中处理capn_data?
问题描述
我使用c-capnproto序列化我的传感器数据。现在我需要向它添加一个 HMAC。它必须是一个capn_data
blob,但这在示例代码中没有处理。
当我尝试添加数据时,它不起作用。这是我的capnp
文件:
@0xe2d0214c41cb77af;
using C = import "c.capnp";
$C.fieldgetset;
struct Heartbeat @0x97002102216a8d67 {
temperature @0 :UInt32;
}
struct AuthenticatedHeartbeat @0xe2fa13efd2e3a9dc {
heartbeat @0 :Data;
hmac @1 :Data;
}
编译后,我使用它:
static uint8_t beat[1024];
static uint8_t hmac[32] = {0xc2, 0xf1, 0x53, 0x12, 0x4b, 0x0c, 0xa4, 0xd1,
0x22, 0xf1, 0x64, 0x22, 0x1b, 0xbc, 0xa5, 0xd2,
0xe2, 0xf2, 0x75, 0x32, 0x2b, 0x3c, 0xa6, 0xd3,
0x72, 0xf1, 0x86, 0x42, 0x6b, 0x7c, 0xa7, 0xd4};
static uint8_t auth[1024];
int main(void) {
int packed_size;
{
struct capn root;
capn_init_malloc(&root);
capn_ptr cr = capn_root(&root);
struct capn_segment *cs = cr.seg;
Heartbeat_ptr hb = new_Heartbeat(cs);
Heartbeat_set_temperature(hb, 0x25);
capn_setp(capn_root(&root), 0, hb.p);
packed_size = capn_write_mem(&root, beat, sizeof(beat), 1/*packed*/);
printf("BEAT: max_unpacked_size=%d, packed_size=%d\n", capn_size(&root), packed_size);
capn_free(&root);
}
print_buffer(beat, packed_size);
//HMAC_calc(beat, packed_size, hmac);
{
struct capn root;
capn_init_malloc(&root);
capn_ptr cr = capn_root(&root);
struct capn_segment *cs = cr.seg;
AuthenticatedHeartbeat_ptr ahb = new_AuthenticatedHeartbeat(cs);
AuthenticatedHeartbeat_set_heartbeat(ahb, buf_to_data(beat, packed_size));
AuthenticatedHeartbeat_set_hmac(ahb, buf_to_data(hmac, 32));
capn_setp(capn_root(&root), 0, ahb.p);
packed_size = capn_write_mem(&root, auth, sizeof(auth), 1/*packed*/);
printf("AUTH: max_unpacked_size=%d, packed_size=%d\n", capn_size(&root), packed_size);
capn_free(&root);
}
print_buffer(auth, packed_size);
}
我编写了一个辅助函数,类似于chars_to_text
示例中提供的函数
static capn_data buf_to_data(char *buf, const int len) {
return (capn_data) {{
.type = CAPN_NULL,
.has_ptr_tag = 0,
.is_list_member = 0,
.is_composite_list = 0,
.datasz = 0,
.ptrs = 0,
.len = len,
.data = buf,
.seg = NULL,
}};
}
但我想我错过了一些部分。结果数据
BEAT: max_unpacked_size=24, packed_size=6
[ 0] - 10021001 - ....
[ 1] - 01250000 - .%
AUTH: max_unpacked_size=32, packed_size=6
[ 0] - 10034002 - ..@.
[ 1] - 00010000 - ..
至少在经过验证的数据中不再包含温度 ( 0x25
)。HMAC也不存在,长度太短了。
您能否提示我如何处理capn_data
blob,如何填充它以及如何将其打包到根目录中。
解决方案
终于在这个已关闭的问题中找到了一个提示,这在我一开始的研究中是不可见或忽略的......
我使用此代码进行序列化capn_data
(这替换了原始问题中的较低范围):
{
struct capn root;
capn_init_malloc(&root);
capn_ptr cr = capn_root(&root);
struct capn_segment *cs = cr.seg;
capn_list8 list8 = capn_new_list8(cs, packed_size);
capn_setv8(list8, 0, beat, packed_size);
capn_list8 list9 = capn_new_list8(cs, 32);
capn_setv8(list9, 0, hmac, 32);
struct AuthenticatedHeartbeat s_ahb;
s_ahb.heartbeat.p = list8.p;
s_ahb.hmac.p = list9.p;
AuthenticatedHeartbeat_ptr pahb = new_AuthenticatedHeartbeat(cs);
write_AuthenticatedHeartbeat(&s_ahb, pahb);
capn_setp(capn_root(&root), 0, pahb.p);
packed_size = capn_write_mem(&root, auth, sizeof(auth), 1/*packed*/);
printf("AUTH: max_unpacked_size=%d, packed_size=%d\n", capn_size(&root), packed_size);
capn_free(&root);
}
因此,首先创建一个“列表”,稍后使用,因为这两个与@eqvinoxcapn_data
所述基本相同。
buf_to_data()
不再需要该功能。
作为参考,这是反序列化数据的示例代码:
{
struct capn root;
capn_init_mem(&root, auth, packed_size, 1/*packed*/);
AuthenticatedHeartbeat_ptr ahbp;
ahbp.p = capn_getp(capn_root(&root), 0, 1);
capn_data dhb = AuthenticatedHeartbeat_get_heartbeat(ahbp);
capn_data dhmac = AuthenticatedHeartbeat_get_hmac(ahbp);
printf("dhb ptr=%p, len=%d\n", dhb.p.data, dhb.p.len);
printf("dhmac ptr=%p, len=%d\n", dhmac.p.data, dhmac.p.len);
unpacked_size = dhb.p.len;
hmac2_size = dhmac.p.len;
memcpy(beat2, dhb.p.data, unpacked_size);
memcpy(hmac2, dhmac.p.data, hmac2_size);
capn_free(&root);
}
{
struct capn root;
capn_init_mem(&root, beat2, unpacked_size, 1/*packed*/);
Heartbeat_ptr hbp;
hbp.p = capn_getp(capn_root(&root), 0, 1);
uint32_t temperature = Heartbeat_get_temperature(hbp);
printf("DESER: temperature=%x\n", temperature);
capn_free(&root);
}
推荐阅读
- javascript - 添加链接到html表格列中的所有单元格
- javascript - 生成具有动态内容的字符串
- python - 为什么我会收到此类的“缺少 1 个位置参数”错误?
- c++ - 从 qmake 运行脚本以获取内部版本号
- java - 广播接收器不能静态工作
- algorithm - 给定一组格点,有多少组点?
- python - SMTPAuthenticationError - 535,b'5.7.8 用户名和密码不被接受。- 从 docker 发送电子邮件
- jinja2 - 使用列表遍历列表列表
- sql-server-2012 - SQL Server:在表变量上创建索引
- scala - 为 avro 模式创建十进制逻辑类型和字节类型的 json 表示