1
0
libflex/libflex/libflex.c
2024-03-21 21:57:00 +02:00

207 lines
4.3 KiB
C

#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include "libflex.h"
#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0])
const flx_opt OPTION_RANGES[5] = {
FLX_WATCH_REM,
FLX_QUIT_ERROR,
FLX_NOTIFY_MOVE,
FLX_REPLY_INVALID_DATA,
FLX_STATUS_ERR_READ_INOTIFY,
};
const flx_opt ACTION_SIZES[5] = {
FLX_DLEN_WATCH,
FLX_DLEN_QUIT,
FLX_DLEN_NOTIFY,
FLX_DLEN_REPLY,
FLX_DLEN_STATUS,
};
const flx_opt LAST_ACTION_INDEX = ARRAY_LEN(OPTION_RANGES) - 1;
void flx_serialize_result_init(struct flx_serialize_result *result) {
result->size = -1;
result->reply = FLX_REPLY_UNSET;
}
void flx_msg_init(struct flx_msg *msg) {
msg->action = FLX_ACT_UNSET;
msg->option = FLX_UNSET_UNSET;
msg->size = 0;
msg->data = NULL;
msg->data_len = 0;
}
void flx_msg_free(struct flx_msg *msg) {
if (msg->data == NULL) return;
for (int i = 0; i < msg->data_len; i++) {
if (msg->data[i] == NULL) continue;
free(msg->data[i]);
}
free(msg->data);
msg->data = NULL;
}
void flx_msg_reset(struct flx_msg *msg) {
flx_msg_free(msg);
flx_msg_init(msg);
}
void flx_serialize(
uint8_t out_buffer[FLX_PKT_MAXIMUM_SIZE],
struct flx_msg *msg,
struct flx_serialize_result *result
) {
int valid_data_length = -1;
uint8_t data_size = 0;
flx_serialize_result_init(result);
if (msg->action <= LAST_ACTION_INDEX) {
out_buffer[0] = msg->action;
valid_data_length = ACTION_SIZES[msg->action];
} else {
result->reply = FLX_REPLY_BAD_ACTION;
return;
}
if (valid_data_length != msg->data_len) {
result->reply = FLX_REPLY_BAD_SIZE;
return;
}
if (msg->option > OPTION_RANGES[msg->option]) {
result->reply = FLX_REPLY_BAD_OPTION;
return;
}
out_buffer[1] = msg->option;
if (valid_data_length != 0 && msg->data == NULL) {
result->reply = FLX_REPLY_INVALID_DATA;
return;
}
for (int i = 0; i < msg->data_len; i++) {
if (msg->data[i] == NULL) {
result->reply = FLX_REPLY_INVALID_DATA;
return;
}
int running_data_size = 0;
for (int j = 0; j < FLX_PKT_MINIMUM_SIZE - FLX_PKT_MAXIMUM_SIZE - data_size; j++) {
running_data_size += 1;
out_buffer[FLX_PKT_MINIMUM_SIZE + data_size + j] = msg->data[i][j];
if (msg->data[i][j] == 0) break;
}
data_size += running_data_size;
}
out_buffer[2] = data_size;
result->size = FLX_PKT_MINIMUM_SIZE + data_size;
result->reply = FLX_REPLY_VALID;
return;
}
void flx_deserialize(
uint8_t in_buffer[FLX_PKT_MINIMUM_SIZE],
struct flx_msg *msg,
struct flx_serialize_result *result
) {
int valid_data_length = -1;
int data_size_index = 0;
int *data_sizes = NULL;
int data_size = 0;
int data_offset = FLX_PKT_MINIMUM_SIZE;
flx_serialize_result_init(result);
flx_msg_reset(msg);
if (in_buffer[0] <= LAST_ACTION_INDEX) {
msg->action = in_buffer[0];
valid_data_length = ACTION_SIZES[msg->action];
} else {
result->reply = FLX_REPLY_BAD_ACTION;
return;
}
if (in_buffer[1] > OPTION_RANGES[msg->action]) {
result->reply = FLX_REPLY_BAD_OPTION;
return;
}
msg->option = in_buffer[1];
if (valid_data_length == 0) {
if (in_buffer[2] != 0) {
result->reply = FLX_REPLY_BAD_SIZE;
return;
} else {
result->reply = FLX_REPLY_VALID;
}
return;
}
msg->size = in_buffer[2];
data_sizes = (int *)malloc(sizeof(int) * valid_data_length);
for (int i = FLX_PKT_MINIMUM_SIZE; i < FLX_PKT_MAXIMUM_SIZE; i++) {
if (i > msg->size + FLX_PKT_MINIMUM_SIZE) {
free(data_sizes);
result->reply = FLX_REPLY_BAD_SIZE;
return;
}
if (data_size_index == valid_data_length) {
if (data_size == 1) {
free(data_sizes);
result->reply = FLX_REPLY_BAD_SIZE;
return;
}
break;
}
if (in_buffer[i] == 0) {
data_sizes[data_size_index] = ++data_size;
data_size_index++;
data_size = 0;
continue;
}
if (in_buffer[i] < '!' || in_buffer[i] > '~') {
free(data_sizes);
result->reply = FLX_REPLY_INVALID_DATA;
return;
}
data_size++;
}
msg->data = (char**)malloc(sizeof(char *) * valid_data_length);
msg->data_len = valid_data_length;
for (int i = 0; i < valid_data_length; i++) {
msg->data[i] = (char *)malloc(sizeof(char) * data_sizes[i]);
for (int j = 0; j < data_sizes[i]; j++) {
msg->data[i][j] = in_buffer[j + data_offset];
}
data_offset += data_sizes[i];
}
result->reply = FLX_REPLY_VALID;
result->size = FLX_PKT_MINIMUM_SIZE + msg->size;
free(data_sizes);
return;
}