207 lines
4.3 KiB
C
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;
|
|
}
|
|
|