2021-05-03 22:44:39 +00:00
|
|
|
#include "packet_utils.h"
|
2021-05-04 14:01:47 +00:00
|
|
|
#include "compress.h"
|
2021-05-03 19:53:28 +00:00
|
|
|
#include "cwpack/cwpack.h"
|
2021-01-26 19:16:08 +00:00
|
|
|
|
2021-05-05 13:14:02 +00:00
|
|
|
// NOTE(zaklaus): packets
|
|
|
|
|
2021-05-06 15:30:38 +00:00
|
|
|
#include "packets/pkt_00_init.h"
|
2021-05-05 13:14:02 +00:00
|
|
|
#include "packets/pkt_01_welcome.h"
|
|
|
|
#include "packets/pkt_send_keystate.h"
|
|
|
|
#include "packets/pkt_send_librg_update.h"
|
|
|
|
|
2021-05-06 15:30:38 +00:00
|
|
|
#define PKT_HEADER_ELEMENTS 3
|
2021-01-26 19:16:08 +00:00
|
|
|
|
|
|
|
pkt_handler pkt_handlers[] = {
|
2021-05-06 15:30:38 +00:00
|
|
|
{.id = MSG_ID_00_INIT, .handler = pkt_00_init_handler},
|
2021-05-03 22:44:39 +00:00
|
|
|
{.id = MSG_ID_01_WELCOME, .handler = pkt_01_welcome_handler},
|
2021-05-05 13:14:02 +00:00
|
|
|
{.id = MSG_ID_LIBRG_UPDATE, .handler = pkt_send_librg_update_handler},
|
2021-05-07 14:43:54 +00:00
|
|
|
{.id = MSG_ID_SEND_KEYSTATE, .handler = pkt_send_keystate_handler},
|
2021-01-26 19:16:08 +00:00
|
|
|
};
|
|
|
|
|
2021-05-03 22:44:39 +00:00
|
|
|
uint8_t pkt_buffer[PKT_BUFSIZ];
|
|
|
|
|
2021-05-06 15:30:38 +00:00
|
|
|
int32_t pkt_header_encode(pkt_messages id, uint16_t view_id, void *data, size_t datalen) {
|
2021-05-04 17:39:50 +00:00
|
|
|
cw_pack_context pc = {0};
|
|
|
|
pkt_pack_msg(&pc, PKT_HEADER_ELEMENTS);
|
|
|
|
cw_pack_unsigned(&pc, id);
|
2021-05-06 15:30:38 +00:00
|
|
|
cw_pack_unsigned(&pc, view_id);
|
2021-05-04 17:39:50 +00:00
|
|
|
cw_pack_bin(&pc, data, datalen);
|
|
|
|
return pkt_pack_msg_size(&pc);
|
|
|
|
}
|
|
|
|
|
2021-01-26 19:16:08 +00:00
|
|
|
int32_t pkt_header_decode(pkt_header *table, void *data, size_t datalen) {
|
|
|
|
cw_unpack_context uc = {0};
|
2021-05-03 22:44:39 +00:00
|
|
|
pkt_unpack_msg_raw(&uc, data, datalen, PKT_HEADER_ELEMENTS);
|
2021-07-18 11:23:59 +00:00
|
|
|
|
2021-01-26 19:16:08 +00:00
|
|
|
cw_unpack_next(&uc);
|
|
|
|
if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER || uc.item.as.u64 > UINT16_MAX) {
|
2021-05-03 22:44:39 +00:00
|
|
|
return -1; // invalid packet id
|
2021-01-26 19:16:08 +00:00
|
|
|
}
|
2021-07-18 11:23:59 +00:00
|
|
|
|
2021-01-26 19:16:08 +00:00
|
|
|
uint16_t pkt_id = (uint16_t)uc.item.as.u64;
|
2021-05-06 15:30:38 +00:00
|
|
|
|
|
|
|
cw_unpack_next(&uc);
|
|
|
|
if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER || uc.item.as.u64 > UINT16_MAX) {
|
|
|
|
return -1; // invalid view id
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t view_id = (uint16_t)uc.item.as.u64;
|
|
|
|
|
2021-01-26 19:16:08 +00:00
|
|
|
cw_unpack_next(&uc);
|
|
|
|
const void *packed_blob = uc.item.as.bin.start;
|
2021-05-03 19:53:28 +00:00
|
|
|
uint32_t packed_size = uc.item.as.bin.length;
|
2021-07-18 11:23:59 +00:00
|
|
|
|
2021-01-26 19:16:08 +00:00
|
|
|
table->id = pkt_id;
|
2021-05-06 15:30:38 +00:00
|
|
|
table->view_id = view_id;
|
2021-01-26 19:16:08 +00:00
|
|
|
table->data = packed_blob;
|
|
|
|
table->datalen = packed_size;
|
|
|
|
table->ok = 1;
|
2021-07-18 11:23:59 +00:00
|
|
|
|
2021-05-04 17:39:50 +00:00
|
|
|
return pkt_validate_eof_msg(&uc) != -1;
|
2021-01-26 19:16:08 +00:00
|
|
|
}
|
2021-05-03 23:38:47 +00:00
|
|
|
|
|
|
|
int32_t pkt_unpack_struct(cw_unpack_context *uc, pkt_desc *desc, void *raw_blob, uint32_t blob_size) {
|
|
|
|
uint8_t *blob = (uint8_t*)raw_blob;
|
2021-05-04 08:08:00 +00:00
|
|
|
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) {
|
2021-05-03 23:38:47 +00:00
|
|
|
cw_unpack_next(uc);
|
2021-08-09 13:57:56 +00:00
|
|
|
if (field->skip_count != 0) {
|
2021-07-18 11:23:59 +00:00
|
|
|
if (uc->item.type != CWP_ITEM_POSITIVE_INTEGER) return -1; // unexpected field
|
|
|
|
field += uc->item.as.u64;
|
|
|
|
continue;
|
|
|
|
}
|
2021-05-03 23:38:47 +00:00
|
|
|
if (uc->item.type != field->type) return -1; // unexpected field
|
2021-05-04 11:04:15 +00:00
|
|
|
if (blob + field->offset + field->size > blob + blob_size) return -1; // field does not fit
|
2021-05-03 23:38:47 +00:00
|
|
|
switch (field->type) {
|
2021-05-06 18:24:01 +00:00
|
|
|
case CWP_ITEM_DOUBLE: {
|
|
|
|
zpl_memcopy(blob + field->offset, (uint8_t*)&uc->item.as.long_real, field->size);
|
|
|
|
}break;
|
|
|
|
case CWP_ITEM_FLOAT: {
|
|
|
|
zpl_memcopy(blob + field->offset, (uint8_t*)&uc->item.as.real, field->size);
|
|
|
|
} break;
|
|
|
|
case CWP_ITEM_NEGATIVE_INTEGER: {
|
|
|
|
zpl_memcopy(blob + field->offset, (uint8_t*)&uc->item.as.i64, field->size);
|
|
|
|
}break;
|
2021-05-03 23:38:47 +00:00
|
|
|
case CWP_ITEM_POSITIVE_INTEGER: {
|
2021-05-04 08:08:00 +00:00
|
|
|
zpl_memcopy(blob + field->offset, (uint8_t*)&uc->item.as.u64, field->size);
|
2021-05-03 23:38:47 +00:00
|
|
|
}break;
|
2021-05-04 11:04:15 +00:00
|
|
|
case CWP_ITEM_BIN: {
|
2021-05-04 14:01:47 +00:00
|
|
|
if (uc->item.as.bin.length >= PKT_BUFSIZ) return -1; // bin blob too big
|
|
|
|
static uint8_t bin_buf[PKT_BUFSIZ] = {0};
|
|
|
|
uint32_t actual_size = decompress_rle(uc->item.as.bin.start, uc->item.as.bin.length, bin_buf);
|
|
|
|
if (actual_size != field->size) return -1; // bin size mismatch
|
|
|
|
zpl_memcopy(blob + field->offset, bin_buf, actual_size);
|
2021-05-04 11:04:15 +00:00
|
|
|
}break;
|
2021-05-03 23:38:47 +00:00
|
|
|
default: {
|
|
|
|
zpl_printf("[WARN] unsupported pkt field type %lld !\n", field->type);
|
|
|
|
return -1; // unsupported field
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2021-05-03 23:57:19 +00:00
|
|
|
|
2021-05-04 11:04:15 +00:00
|
|
|
int32_t pkt_pack_struct(cw_pack_context *pc, pkt_desc *desc, void *raw_blob, uint32_t blob_size) {
|
|
|
|
uint8_t *blob = (uint8_t*)raw_blob;
|
|
|
|
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) {
|
2021-08-09 13:57:56 +00:00
|
|
|
if (field->skip_count != 0) {
|
2021-07-18 11:23:59 +00:00
|
|
|
uint8_t val = *(uint8_t*)(blob + field->offset);
|
2021-08-09 14:33:46 +00:00
|
|
|
if ((field->skip_count > 0 && val == field->skip_eq) ||
|
|
|
|
(field->skip_count < 0 && val != field->skip_eq)) {
|
|
|
|
cw_pack_unsigned(pc, zpl_abs(field->skip_count));
|
|
|
|
field += zpl_abs(field->skip_count);
|
2021-07-18 11:23:59 +00:00
|
|
|
} else {
|
|
|
|
cw_pack_unsigned(pc, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-05-04 11:04:15 +00:00
|
|
|
switch (field->type) {
|
|
|
|
case CWP_ITEM_BIN: {
|
2021-05-04 14:01:47 +00:00
|
|
|
if (field->size >= PKT_BUFSIZ) return -1; // bin blob too big
|
|
|
|
static uint8_t bin_buf[PKT_BUFSIZ] = {0};
|
|
|
|
uint32_t size = compress_rle(blob + field->offset, field->size, bin_buf);
|
|
|
|
cw_pack_bin(pc, bin_buf, size);
|
2021-05-04 11:04:15 +00:00
|
|
|
}break;
|
|
|
|
case CWP_ITEM_POSITIVE_INTEGER: {
|
|
|
|
uint64_t num;
|
|
|
|
zpl_memcopy(&num, blob + field->offset, field->size);
|
|
|
|
cw_pack_unsigned(pc, num);
|
|
|
|
}break;
|
2021-05-06 16:26:52 +00:00
|
|
|
case CWP_ITEM_NEGATIVE_INTEGER: {
|
|
|
|
int64_t num;
|
|
|
|
zpl_memcopy(&num, blob + field->offset, field->size);
|
|
|
|
cw_pack_signed(pc, num);
|
|
|
|
}break;
|
|
|
|
case CWP_ITEM_DOUBLE: {
|
|
|
|
double num;
|
|
|
|
zpl_memcopy(&num, blob + field->offset, field->size);
|
|
|
|
cw_pack_double(pc, num);
|
|
|
|
}break;
|
|
|
|
case CWP_ITEM_FLOAT: {
|
|
|
|
float num;
|
|
|
|
zpl_memcopy(&num, blob + field->offset, field->size);
|
|
|
|
cw_pack_float(pc, num);
|
|
|
|
}break;
|
2021-05-04 11:04:15 +00:00
|
|
|
default: {
|
|
|
|
zpl_printf("[WARN] unsupported pkt field type %lld !\n", field->type);
|
|
|
|
return -1; // unsupported field
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2021-05-09 10:27:10 +00:00
|
|
|
|
|
|
|
void pkt_dump_struct(pkt_desc *desc, void* raw_blob, uint32_t blob_size) {
|
|
|
|
uint8_t *blob = (uint8_t*)raw_blob;
|
|
|
|
zpl_printf("{\n");
|
|
|
|
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) {
|
2021-07-18 11:23:59 +00:00
|
|
|
if (field->skip_count) {
|
|
|
|
uint8_t val = *(uint8_t*)(blob + field->offset);
|
|
|
|
if (val == field->skip_eq) {
|
|
|
|
field += field->skip_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2021-05-09 10:27:10 +00:00
|
|
|
zpl_printf(" \"%s\": ", field->name);
|
|
|
|
switch (field->type) {
|
|
|
|
case CWP_ITEM_BIN: {
|
|
|
|
// TODO(zaklaus): print memory dump as array of hex bytes
|
|
|
|
}break;
|
|
|
|
case CWP_ITEM_POSITIVE_INTEGER: {
|
|
|
|
zpl_printf("%u\n", *(uint64_t*)(blob + field->offset));
|
|
|
|
}break;
|
|
|
|
case CWP_ITEM_NEGATIVE_INTEGER: {
|
|
|
|
zpl_printf("%d\n", *(int64_t*)(blob + field->offset));
|
|
|
|
}break;
|
|
|
|
case CWP_ITEM_FLOAT: {
|
|
|
|
zpl_printf("%f\n", *(float*)(blob + field->offset));
|
|
|
|
}break;
|
|
|
|
case CWP_ITEM_DOUBLE: {
|
|
|
|
zpl_printf("%f\n", *(double*)(blob + field->offset));
|
|
|
|
}break;
|
|
|
|
default: {
|
|
|
|
zpl_printf("[WARN] unsupported pkt field type %lld !\n", field->type);
|
|
|
|
return; // unsupported field
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
zpl_printf("}\n");
|
|
|
|
}
|