diff --git a/README.md b/README.md index df969ef..490dd2d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Over engineered custom network protocol experiment -ABANDONED! Because I hated how complicated the protocol was, and just had no more motivation to continue. +This was created based of the youtube, but was heavily modified. Didn't like it. Youtube tutorial: https://www.youtube.com/watch?v=AS_nxNS6YKY diff --git a/build.zig b/build.zig index d80fd44..7d8a7a7 100644 --- a/build.zig +++ b/build.zig @@ -1,11 +1,12 @@ const std = @import("std"); +const Build = std.Build; -fn linkPkgConfigOutput(b: *std.build.Builder, obj: *std.build.LibExeObjStep, pkg_config_args: []const []const u8) !void { +fn linkPkgConfigOutput(b: *Build, obj: *Build.Step.Compile, pkg_config_args: []const []const u8) !void { var argv = std.ArrayList([]const u8).init(b.allocator); try argv.append("pkg-config"); try argv.appendSlice(pkg_config_args); - const result = try std.ChildProcess.exec(.{ + const result = try std.ChildProcess.run(.{ .allocator = b.allocator, .argv = argv.items }); @@ -21,7 +22,7 @@ fn linkPkgConfigOutput(b: *std.build.Builder, obj: *std.build.LibExeObjStep, pkg } } -pub fn build(b: *std.build.Builder) !void { +pub fn build(b: *Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); @@ -31,22 +32,21 @@ pub fn build(b: *std.build.Builder) !void { .optimize = optimize, }); libflex.addCSourceFile(.{ - .file = .{ .path = "libflex/libflex.c" }, + .file = b.path("libflex/libflex.c"), .flags = &.{} }); libflex.linkLibC(); - libflex.installHeader("libflex/libflex.h", "libflex.h"); + libflex.installHeader(b.path("libflex/libflex.h"), "libflex.h"); { const rolexhound = b.addExecutable(.{ .name = "rolexhound", .target = target, - .optimize = optimize, - .root_source_file = .{ .path = "rolexhound/main.c" } + .optimize = optimize }); + rolexhound.addCSourceFile(.{ .file = b.path("rolexhound/main.c") }); rolexhound.linkLibrary(libflex); rolexhound.linkLibC(); - try linkPkgConfigOutput(b, rolexhound, &.{ "--cflags", "--libs", "libnotify" }); b.installArtifact(rolexhound); @@ -63,11 +63,12 @@ pub fn build(b: *std.build.Builder) !void { const smartwatch = b.addExecutable(.{ .name = "smartwatch", .target = target, - .optimize = optimize, - .root_source_file = .{ .path = "smartwatch/main.c" } + .optimize = optimize }); + smartwatch.addCSourceFile(.{ .file = b.path("smartwatch/main.c") }); smartwatch.linkLibrary(libflex); smartwatch.linkLibC(); + try linkPkgConfigOutput(b, smartwatch, &.{ "--cflags", "--libs", "libnotify" }); b.installArtifact(smartwatch); diff --git a/libflex/libflex.c b/libflex/libflex.c index 7939747..1c9cc6b 100644 --- a/libflex/libflex.c +++ b/libflex/libflex.c @@ -1,206 +1,212 @@ +#include #include #include +#include #include +#include #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_quit(struct flx_msg *msg, enum flx_opt_quit opt) { + memset(msg, 0, sizeof(*msg)); + msg->action = FLX_ACT_QUIT; + msg->option = opt; } -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_init_add_watch(struct flx_msg *msg, const char *filename) { + memset(msg, 0, sizeof(*msg)); + msg->action = FLX_ACT_WATCH; + msg->option = FLX_WATCH_ADD; + msg->data_len = 1; + msg->data[0].ptr = filename; + msg->data[0].len = strlen(filename); } -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_init_notify(struct flx_msg *msg, enum flx_opt_notify opt, const char *base_path, const char *path) { + memset(msg, 0, sizeof(*msg)); + msg->action = FLX_ACT_NOTIFY; + msg->option = opt; + msg->data_len = 2; + msg->data[0].ptr = base_path; + msg->data[0].len = strlen(base_path); + msg->data[1].ptr = path; + msg->data[1].len = strlen(path); } -void flx_msg_reset(struct flx_msg *msg) { - flx_msg_free(msg); - flx_msg_init(msg); +void flx_msg_init_remove_watch(struct flx_msg *msg, const char *filename) { + memset(msg, 0, sizeof(*msg)); + msg->action = FLX_ACT_WATCH; + msg->option = FLX_WATCH_REM; + msg->data_len = 1; + msg->data[0].ptr = filename; + msg->data[0].len = strlen(filename); } -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); +static bool write_uint8(uint8_t *buffer, size_t capacity, size_t *cursor, uint8_t value) { + if ((*cursor) + 1 < capacity) { + buffer[*cursor] = value; + (*cursor)++; + return true; + } + return false; +} - 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; +static uint8_t *read_uint8_array(uint8_t *buffer, size_t capacity, size_t *cursor, uint8_t byte_count) { + if ((*cursor) + byte_count > capacity) { + return NULL; } - if (valid_data_length != msg->data_len) { - result->reply = FLX_REPLY_BAD_SIZE; - return; + uint8_t *array = &buffer[*cursor]; + (*cursor) += byte_count; + return array; +} + +static bool read_uint8(uint8_t *buffer, size_t capacity, size_t *cursor, uint8_t *value) { + uint8_t *array = read_uint8_array(buffer, capacity, cursor, 1); + if (array) { + *value = array[0]; + return true; + } + return false; +} + +int flx_serialize(uint8_t *out_buffer, size_t capacity, struct flx_msg *msg) { + size_t cursor = 0; + + if (!write_uint8(out_buffer, capacity, &cursor, msg->action)) { + return -1; } - if (msg->option > OPTION_RANGES[msg->option]) { - result->reply = FLX_REPLY_BAD_OPTION; - return; + uint32_t expected_data_len = 0; + if (msg->action == FLX_ACT_WATCH) { + expected_data_len = 1; + } else if (msg->action == FLX_ACT_NOTIFY) { + expected_data_len = 2; } - out_buffer[1] = msg->option; + if (expected_data_len != msg->data_len) { + return -1; + } - if (valid_data_length != 0 && msg->data == NULL) { - result->reply = FLX_REPLY_INVALID_DATA; - return; + if (!write_uint8(out_buffer, capacity, &cursor, msg->option)) { + return -1; + } + + if (!write_uint8(out_buffer, capacity, &cursor, msg->data_len)) { + return -1; + } + + if (msg->data_len > FLX_DATA_MAX) { + return -1; } for (int i = 0; i < msg->data_len; i++) { - if (msg->data[i] == NULL) { - result->reply = FLX_REPLY_INVALID_DATA; - return; + struct char_slice *data_i = &msg->data[i]; + + if (!write_uint8(out_buffer, capacity, &cursor, data_i->len)) { + return -1; } - 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; + for (int j = 0; j < data_i->len; j++) { + if (!write_uint8(out_buffer, capacity, &cursor, data_i->ptr[j])) { + return -1; } - 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; + return cursor; } +int flx_deserialize(uint8_t *in_buffer, size_t capacity, struct flx_msg *msg) { + size_t cursor = 0; + + uint8_t action = 0; + if (!read_uint8(in_buffer, capacity, &cursor, &action)) { + return -1; + } + msg->action = action; + + if (!read_uint8(in_buffer, capacity, &cursor, &msg->option)) { + return -1; + } + + if (!read_uint8(in_buffer, capacity, &cursor, &msg->data_len)) { + return -1; + } + + if (msg->data_len > FLX_DATA_MAX) { + return -1; + } + + for (int i = 0; i < msg->data_len; i++) { + struct char_slice *data_i = &msg->data[i]; + + if (!read_uint8(in_buffer, capacity, &cursor, &data_i->len)) { + return -1; + } + + data_i->ptr = (char *)read_uint8_array(in_buffer, capacity, &cursor, data_i->len); + if (!data_i->ptr) { + return -1; + } + } + + return cursor; +} + +int flx_write(int fd, struct flx_msg *msg) { + uint8_t buffer[255]; + int msg_size = flx_serialize(buffer, sizeof(buffer), msg); + if (msg_size < 0) { + return -1; + } + + int written = 0; + while (written < msg_size) { + int result = write(fd, buffer + written, msg_size - written); + if (result == 0) { + return 0; + } + if (result < 0) { + return -1; + } + + written += result; + } + + return msg_size; +} + +int flx_read(uint8_t *buffer, size_t capacity, size_t *count, int fd, struct flx_msg *msg) { + while (*count < capacity) { + int result = read(fd, buffer + (*count), capacity - (*count)); + if (result == 0) { + return 0; + } + if (result <= 0) { + return -1; + } + + (*count) += result; + int msg_size = flx_deserialize(buffer, (*count), msg); + if (msg_size > 0) { + return msg_size; + } + + if (*count == capacity) { + memmove(buffer, buffer+1, capacity-1); + (*count)--; + } + } + + return -1; +} + +char *char_slice_dupe(struct char_slice slice) { + char *str = calloc(slice.len + 1, sizeof(char)); + if (!str) { + return NULL; + } + memcpy(str, slice.ptr, slice.len); + return str; +} diff --git a/libflex/libflex.h b/libflex/libflex.h index 5b69a3c..6134087 100644 --- a/libflex/libflex.h +++ b/libflex/libflex.h @@ -1,71 +1,74 @@ #include +#include -typedef uint8_t flx_act; typedef uint8_t flx_opt; -#define FLX_ACT_WATCH 0x00 -#define FLX_ACT_QUIT 0x01 -#define FLX_ACT_NOTIFY 0x02 -#define FLX_ACT_REPLY 0x03 -#define FLX_ACT_STATUS 0x04 -#define FLX_ACT_UNSET 0xFF +enum flx_act { + FLX_ACT_WATCH, + FLX_ACT_QUIT, + FLX_ACT_NOTIFY, + FLX_ACT_STATUS, +}; -#define FLX_WATCH_ADD 0x00 -#define FLX_WATCH_REM 0x01 +enum flx_opt_watch { + FLX_WATCH_ADD, + FLX_WATCH_REM, +}; -#define FLX_QUIT_USER 0x00 -#define FLX_QUIT_ERROR 0x01 +enum flx_opt_quit { + FLX_QUIT_USER, + FLX_QUIT_ERROR, +}; -#define FLX_NOTIFY_CREATE 0x00 -#define FLX_NOTIFY_DELETE 0x01 -#define FLX_NOTIFY_ACCESS 0x02 -#define FLX_NOTIFY_CLOSE 0x03 -#define FLX_NOTIFY_MODIFY 0x04 -#define FLX_NOTIFY_MOVE 0x05 +enum flx_opt_notify { + FLX_NOTIFY_CREATE, + FLX_NOTIFY_DELETE, + FLX_NOTIFY_ACCESS, + FLX_NOTIFY_CLOSE, + FLX_NOTIFY_MODIFY, + FLX_NOTIFY_MOVE, +}; -#define FLX_REPLY_VALID 0x00 -#define FLX_REPLY_BAD_SIZE 0x01 -#define FLX_REPLY_BAD_ACTION 0x02 -#define FLX_REPLY_BAD_OPTION 0x03 -#define FLX_REPLY_BAD_PATH 0x04 -#define FLX_REPLY_INVALID_DATA 0x05 -#define FLX_REPLY_UNSET 0xFF +enum flx_opt_status { + FLX_STATUS_SUCCESS, + FLX_STATUS_ERR_INIT_INOTIFY, + FLX_STATUS_ERR_ADD_WATCH, + FLX_STATUS_ERR_READ_INOTIFY, +}; -#define FLX_STATUS_SUCCESS 0x00 -#define FLX_STATUS_ERR_INIT_INOTIFY 0x01 -#define FLX_STATUS_ERR_ADD_WATCH 0x02 -#define FLX_STATUS_ERR_READ_INOTIFY 0x03 +enum flx_serialize_result { + FLX_REPLY_VALID, + FLX_REPLY_BAD_SIZE, + FLX_REPLY_BAD_ACTION, + FLX_REPLY_BAD_OPTION, + FLX_REPLY_INVALID_DATA, +}; -#define FLX_UNSET_UNSET 0xFF - -#define FLX_PKT_MINIMUM_SIZE 3 -#define FLX_PKT_MAXIMUM_SIZE 255 - -#define FLX_DLEN_WATCH 1 -#define FLX_DLEN_QUIT 0 -#define FLX_DLEN_NOTIFY 2 -#define FLX_DLEN_REPLY 0 -#define FLX_DLEN_STATUS 0 -#define FLX_DLEN_UNSET 0 +#define FLX_DATA_MAX 2 +struct char_slice { + const char *ptr; + uint8_t len; +}; struct flx_msg { - flx_act action; + enum flx_act action; flx_opt option; uint8_t size; - char **data; - uint32_t data_len; + struct char_slice data[FLX_DATA_MAX]; + uint8_t data_len; }; -struct flx_serialize_result { - int size; - flx_opt reply; -}; +void flx_msg_init_quit(struct flx_msg *msg, enum flx_opt_quit opt); +void flx_msg_init_add_watch(struct flx_msg *msg, const char *filename); +void flx_msg_init_remove_watch(struct flx_msg *msg, const char *filename); +void flx_msg_init_notify(struct flx_msg *msg, enum flx_opt_notify opt, const char *base_path, const char *path); -void flx_serialize_result_init(struct flx_serialize_result *result); -void flx_msg_init(struct flx_msg *msg); -void flx_msg_free(struct flx_msg *msg); -void flx_msg_reset(struct flx_msg *msg); -void flx_serialize(uint8_t out_buffer[FLX_PKT_MAXIMUM_SIZE], struct flx_msg *msg, struct flx_serialize_result *result); -void flx_deserialize(uint8_t in_buffer[FLX_PKT_MINIMUM_SIZE], struct flx_msg *msg, struct flx_serialize_result *result); +int flx_serialize(uint8_t *out_buffer, size_t capacity, struct flx_msg *msg); +int flx_deserialize(uint8_t *in_buffer, size_t capacity, struct flx_msg *msg); + +int flx_write(int fd, struct flx_msg *msg); +int flx_read(uint8_t *buffer, size_t capacity, size_t *count, int fd, struct flx_msg *msg); + +char *char_slice_dupe(struct char_slice slice); diff --git a/rolexhound/main.c b/rolexhound/main.c index 4868517..769ec66 100644 --- a/rolexhound/main.c +++ b/rolexhound/main.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -71,44 +72,34 @@ int main() { printf("Accepted connection!\n"); - struct flx_msg *read_msg = malloc(sizeof(struct flx_msg)); - struct flx_msg *send_msg = malloc(sizeof(struct flx_msg)); - struct flx_serialize_result result; + char *path = NULL; - flx_msg_init(read_msg); - flx_msg_init(send_msg); - flx_serialize_result_init(&result); - - uint8_t socket_buffer[FLX_PKT_MAXIMUM_SIZE]; + struct flx_msg read_msg = { 0 }; + uint8_t read_buffer[255] = { 0 }; + size_t read_buffer_size = 0; while (true) { - int bytes_read = recv(client_fd, socket_buffer, sizeof(socket_buffer), 0); - if (bytes_read == 0 || bytes_read == -1) { - perror("recv"); - return -1; + int msg_size = flx_read(read_buffer, sizeof(read_buffer), &read_buffer_size, client_fd, &read_msg); + if (msg_size == 0) { + break; } - - flx_deserialize(socket_buffer, read_msg, &result); - if (result.reply != FLX_REPLY_VALID) { - printf("Received error %x from client\n", result.reply); - - send_msg->action = FLX_ACT_REPLY; - send_msg->option = result.reply; - send_msg = 0; - - flx_serialize(socket_buffer, send_msg, &result); - write(client_fd, socket_buffer, result.size); + if (msg_size < 0) { continue; } - if (read_msg->action != FLX_ACT_WATCH) { - continue; + + if (read_msg.action == FLX_ACT_WATCH && read_msg.option == FLX_WATCH_ADD) { + path = char_slice_dupe(read_msg.data[0]); + assert(path != NULL); } - break; + memmove(read_buffer, read_buffer + msg_size, sizeof(read_buffer) - msg_size); + read_buffer_size -= msg_size; + + if (path != NULL) { + break; + } } - char *path = strdup(read_msg->data[0]); - printf("Watching path: %s\n", path); int inotify_fd = inotify_init(); @@ -130,6 +121,7 @@ int main() { base_path += 1; } + signal(SIGPIPE, SIG_IGN); signal(SIGABRT, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); @@ -147,40 +139,46 @@ int main() { int buffer_used = 0; while (buffer_used < read_length) { struct inotify_event *event = (struct inotify_event*)&buffer[buffer_used]; - - if (event->mask & IN_CREATE) { - send_msg->option = FLX_NOTIFY_CREATE; - } - if (event->mask & IN_DELETE) { - send_msg->option = FLX_NOTIFY_DELETE; - } - if (event->mask & IN_ACCESS) { - send_msg->option = FLX_NOTIFY_ACCESS; - } - if (event->mask & IN_CLOSE_WRITE) { - send_msg->option = FLX_NOTIFY_CLOSE; - } - if (event->mask & IN_MODIFY) { - send_msg->option = FLX_NOTIFY_MODIFY; - } - if (event->mask & IN_MOVE_SELF) { - send_msg->option = FLX_NOTIFY_MOVE; - } - buffer_used += sizeof(struct inotify_event) + event->len; - if (send_msg->option == FLX_UNSET_UNSET) { - continue; + struct flx_msg msg = { 0 }; + + if (event->mask & IN_CREATE) { + flx_msg_init_notify(&msg, FLX_NOTIFY_CREATE, base_path, path); + if (flx_write(client_fd, &msg) <= 0) { + g_state.running = false; + } + } + if (event->mask & IN_DELETE) { + flx_msg_init_notify(&msg, FLX_NOTIFY_DELETE, base_path, path); + if (flx_write(client_fd, &msg) <= 0) { + g_state.running = false; + } + } + if (event->mask & IN_ACCESS) { + flx_msg_init_notify(&msg, FLX_NOTIFY_ACCESS, base_path, path); + if (flx_write(client_fd, &msg) <= 0) { + g_state.running = false; + } + } + if (event->mask & IN_CLOSE_WRITE) { + flx_msg_init_notify(&msg, FLX_NOTIFY_CLOSE, base_path, path); + if (flx_write(client_fd, &msg) <= 0) { + g_state.running = false; + } + } + if (event->mask & IN_MODIFY) { + flx_msg_init_notify(&msg, FLX_NOTIFY_MODIFY, base_path, path); + if (flx_write(client_fd, &msg) <= 0) { + g_state.running = false; + } + } + if (event->mask & IN_MOVE_SELF) { + flx_msg_init_notify(&msg, FLX_NOTIFY_MOVE, base_path, path); + if (flx_write(client_fd, &msg) <= 0) { + g_state.running = false; + } } - - send_msg->action = FLX_ACT_NOTIFY; - send_msg->data_len = FLX_DLEN_NOTIFY; - send_msg->data = malloc(sizeof(char*) * FLX_DLEN_NOTIFY); - - send_msg->data[0] = base_path; - send_msg->data[1] = path; - - flx_serialize(socket_buffer, send_msg, &result); } } diff --git a/smartwatch/main.c b/smartwatch/main.c index 01fd7db..281cab5 100644 --- a/smartwatch/main.c +++ b/smartwatch/main.c @@ -4,13 +4,20 @@ #include #include #include +#include #include +#include #include #define PORT 12345 int main(int argc, char **argv) { + if (!notify_init("smartwatch")) { + perror("notify_init"); + return -1; + } + if (argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return -1; @@ -34,16 +41,61 @@ int main(int argc, char **argv) { return -1; } - uint8_t payload_buffer[256]; - struct flex_byte_buffer bb = flex_bb_init(payload_buffer, sizeof(payload_buffer)); - flex_bb_push_buffer8(&bb, (uint8_t*)path, strlen(path)); + struct flx_msg msg = { 0 }; + flx_msg_init_add_watch(&msg, path); - uint8_t send_buffer[512]; - int send_size = flex_serialize(send_buffer, sizeof(send_buffer), 1, bb.data, bb.size); - - write(client_fd, send_buffer, send_size); + int rc = flx_write(client_fd, &msg); + assert(rc > 0); + struct flx_msg read_msg = { 0 }; + uint8_t read_buffer[255] = { 0 }; + size_t read_buffer_size = 0; while (true) { + int msg_size = flx_read(read_buffer, sizeof(read_buffer), &read_buffer_size, client_fd, &read_msg); + if (msg_size == 0) { + break; + } + if (msg_size < 0) { + continue; + } + + if (read_msg.action == FLX_ACT_NOTIFY) { + const char *notify_message = "Unknown.\n"; + switch (read_msg.option) { + case FLX_NOTIFY_CREATE: + notify_message = "File created.\n"; + break; + case FLX_NOTIFY_DELETE: + notify_message = "File deleted.\n"; + break; + case FLX_NOTIFY_ACCESS: + notify_message = "File accessed.\n"; + break; + case FLX_NOTIFY_CLOSE: + notify_message = "File written and closed.\n"; + break; + case FLX_NOTIFY_MODIFY: + notify_message = "File modified.\n"; + break; + case FLX_NOTIFY_MOVE: + notify_message = "File moved.\n"; + break; + } + + char *base_path = char_slice_dupe(read_msg.data[0]); + assert(base_path != NULL); + + NotifyNotification *notification = notify_notification_new(base_path, notify_message, "dialog-information"); + assert(notification != NULL); + + notify_notification_set_urgency(notification, NOTIFY_URGENCY_CRITICAL); + notify_notification_show(notification, NULL); + g_object_unref(G_OBJECT(notification)); + free(base_path); + } + + memmove(read_buffer, read_buffer + msg_size, sizeof(read_buffer) - msg_size); + read_buffer_size -= msg_size; } close(client_fd);