diff options
| author | 2024-04-09 11:24:01 -0400 | |
|---|---|---|
| committer | 2024-04-09 11:24:01 -0400 | |
| commit | 02f3d3565602146bbbfce85b2719246f24036cb9 (patch) | |
| tree | c6588ffe297b777e36260effa4fa42b958ca6ba3 /src/tree | |
| parent | bbf3314165182e402ff25acccddc004a87f81ef0 (diff) | |
| download | camu-02f3d3565602146bbbfce85b2719246f24036cb9.tar.gz camu-02f3d3565602146bbbfce85b2719246f24036cb9.tar.bz2 camu-02f3d3565602146bbbfce85b2719246f24036cb9.zip | |
Massive restructure and many changes
- The server-side list concept is still a wip
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/tree')
| -rw-r--r-- | src/tree/common.h | 27 | ||||
| -rw-r--r-- | src/tree/list.c | 247 | ||||
| -rw-r--r-- | src/tree/list.h | 37 | ||||
| -rw-r--r-- | src/tree/meson.build | 7 | ||||
| -rw-r--r-- | src/tree/resource_manager.c | 75 | ||||
| -rw-r--r-- | src/tree/resource_manager.h | 27 | ||||
| -rw-r--r-- | src/tree/tree.c | 460 | ||||
| -rw-r--r-- | src/tree/tree.h | 56 |
8 files changed, 0 insertions, 936 deletions
diff --git a/src/tree/common.h b/src/tree/common.h deleted file mode 100644 index f740a4e..0000000 --- a/src/tree/common.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include <al/str.h> - -#define TREE_PORT 14356 -#define TREE_RESOURCE_PORT 14357 -#define TREE_STREAM_PORT 14358 - -#define TREE_SERVER_IP al_str_c("127.0.0.1") -//#define TREE_SERVER_IP al_str_c("108.52.160.112") - -#define CAMU_DB_PATH al_str_c("/mnt/store/files/camu_db") - -enum { - TREE_NODE = 0, - TREE_CLIENT, - TREE_SINK -}; - -enum { - TREE_CMD_IDENTIFY = 0, - TREE_CMD_UPDATE_STATE, - TREE_CMD_CREATE_SEARCH, - TREE_CMD_GET_PAGE, - TREE_CMD_ADD, - TREE_CMD_SKIP -}; diff --git a/src/tree/list.c b/src/tree/list.c deleted file mode 100644 index 948d3cc..0000000 --- a/src/tree/list.c +++ /dev/null @@ -1,247 +0,0 @@ -#include <al/random.h> - -#ifdef AKIYO_HAS_CURL -#include "../cache/handlers/http.h" -#endif -#include "../cache/handlers/file.h" - -#include "../libsink/common.h" - -#include "list.h" -#include "tree.h" -#include "common.h" - -void tree_list_init(struct tree_list *list, struct tree_server *tree, str *name) -{ - al_str_clone(&list->name, name); - list->set = -1; - list->current = 0; - list->backwards = false; - al_array_init(list->entries); - al_array_init(list->sinks); - list->tree = tree; -} - -/* -static void send_buffer_cmd(struct tree_list *list, struct tree_sink *sink, struct tree_list_entry *entry) -{ - struct aki_packet *packet = aki_rpc_get_packet(&list->tree->server, CAMU_SINK_CMD_BUFFER); - aki_packet_write_str(packet, TREE_SERVER_IP); - aki_packet_write_s32(packet, TREE_STREAM_PORT); - aki_packet_write_u16(packet, entry->node_id); - aki_rpc_connection_command(sink->conn, packet, NULL, NULL); -} -*/ - -static void send_set_cmd(struct tree_list *list, struct tree_sink *sink, struct tree_list_entry *entry) -{ - struct aki_packet *packet = aki_rpc_get_packet(&list->tree->server, CAMU_SINK_CMD_SET); - aki_packet_write_str(packet, TREE_SERVER_IP); - aki_packet_write_s32(packet, TREE_STREAM_PORT); - aki_packet_write_u16(packet, entry->node_id); - aki_rpc_connection_command(sink->conn, packet, NULL, NULL); -} - -/* -static void send_queue_cmd(struct tree_list *list, struct tree_sink *sink, struct tree_list_entry *entry) -{ - struct aki_packet *packet = aki_rpc_get_packet(&list->tree->server, CAMU_SINK_CMD_QUEUE); - aki_packet_write_str(packet, TREE_SERVER_IP); - aki_packet_write_s32(packet, TREE_STREAM_PORT); - aki_packet_write_u16(packet, entry->node_id); - aki_rpc_connection_command(sink->conn, packet, NULL, NULL); -} -*/ - -void tree_list_add_sink(struct tree_list *list, struct tree_sink *sink) -{ - al_array_push(list->sinks, sink); - if (list->set == list->current) { - struct tree_list_entry *entry = &al_array_at(list->entries, list->current); - send_set_cmd(list, sink, entry); - } -} - -void tree_list_remove_sink(struct tree_list *list, struct tree_sink *sink) -{ - struct tree_sink *rsink; - al_array_foreach(list->sinks, i, rsink) { - if (rsink == sink) { - al_array_remove_at_iter(list->sinks, i); - break; - } - } -} - -bool tree_list_add(struct tree_list *list, str *unique_id, u32 index) -{ - struct tree_server *tree = list->tree; - struct sho_post *post = sho_post_cache_get(&tree->resources.cache, unique_id); - if (!post) return false; - - struct tree_list_entry entry; - entry.index = index; - al_str_clone(&entry.unique_id, unique_id); - entry.post = post; - - entry.entry = cch_handler_http_create(&al_array_at(entry.post->media, entry.index).url); - if (!entry.entry) return false; - entry.entry->handler->maybe_spawn_worker(entry.entry->handler, 0); - - entry.node_id = bmu_server_create_node(&tree->streams.server, entry.entry); - - al_array_push(list->entries, entry); - - tree_list_pump(list); - - return true; -} - -static struct cch_entry *entry_for_external_path(struct sho_client *client, str *path) -{ - struct cch_entry *entry = NULL; -#ifdef AKIYO_HAS_CURL - bool is_search = al_str_at(path, 0) == ';'; - if (is_search || al_str_cmp(path, al_str_c("https://"), 0, 8) == 0 || - al_str_cmp(path, al_str_c("http://"), 0, 7) == 0) { - str module; - str query; - al_str_from(&module, ""); - al_str_from(&query, ""); - if (al_str_cmp(path, al_str_c("https://twitter.com"), 0, 19) == 0 || - al_str_cmp(path, al_str_c("https://x.com"), 0, 13) == 0) { - al_str_cat(&query, al_str_c("tweet:")); - al_str_cat(&query, path); - al_str_cat(&module, al_str_c("twitter")); - } else if (al_str_cmp(path, al_str_c("https://instagram.com"), 0, 21) == 0) { - s32 slash = al_str_rfind(path, '/'); - if (slash >= 0) { - al_str_cat(&query, al_str_substr(path, slash + 1, path->len)); - } - al_str_cat(&module, al_str_c("instagram")); - } else { - if (is_search) { - al_str_cat(&query, al_str_substr(path, 1, path->len)); - } else { - al_str_cat(&query, al_str_c("link:")); - al_str_cat(&query, path); - } - al_str_cat(&module, al_str_c("youtube")); - } - s32 id = sho_client_create_search(client, &module, &query); - al_str_free(&module); - al_str_free(&query); - if (id < 0) return NULL; - struct sho_search *search = sho_client_get_search(client, id); - if (!search || !sho_search_get_page(search, 0)) return NULL; - struct sho_result_page *page = &al_array_at(search->pages, 0); - struct sho_post *post; - al_array_foreach_ptr(page->posts, i, post) { - struct sho_post_media *media; - al_array_foreach_ptr(post->media, j, media) { - if (media->url.len > 0) { - entry = cch_handler_http_create(&media->url); - break; - } - } - if (entry) break; - } - sho_client_discard_search(client, id); - if (entry) entry->handler->maybe_spawn_worker(entry->handler, 0); - } else // { -#endif - entry = cch_handler_file_create(path); - // } - return entry; -} - -bool tree_list_add_external(struct tree_list *list, str *path) -{ - struct tree_server *tree = list->tree; - - struct tree_list_entry entry; - entry.index = 0; - al_str_clone(&entry.unique_id, path); - entry.post = NULL; - - struct tree_user *user = al_array_at(tree->users, 0); - - entry.entry = entry_for_external_path(&user->search, path); - if (!entry.entry) return false; - - entry.node_id = bmu_server_create_node(&tree->streams.server, entry.entry); - - al_array_push(list->entries, entry); - - tree_list_pump(list); - - return true; -} - -void tree_list_skip(struct tree_list *list, s32 n) -{ - s32 size = (s32)list->entries.size; - if (list->current + n < 0 || list->current + n >= size) { - return; - } - list->current += n; - list->backwards = n < 0; - tree_list_pump(list); -} - -static s32 sort_list_func(void *_a, void *_b) -{ - struct tree_list_entry *a = (struct tree_list_entry *)_a; - struct tree_list_entry *b = (struct tree_list_entry *)_b; - return al_str_cmp(&a->unique_id, &b->unique_id, 0, a->unique_id.len); -} - -void tree_list_sort(struct tree_list *list) -{ - al_array_sort(list->entries, struct tree_list_entry, sort_list_func); -} - -void tree_list_shuffle(struct tree_list *list) -{ - u32 size = list->entries.size; - if (size == 0) return; - for (u32 i = 0; i < size - 1; i++) { - u32 j = i + al_rand() / (AL_RAND_MAX / (size - i) + 1); - struct tree_list_entry tmp = al_array_at(list->entries, j); - al_array_at(list->entries, j) = al_array_at(list->entries, i); - al_array_at(list->entries, i) = tmp; - } - list->set = -1; - tree_list_pump(list); -} - -void tree_list_clear(struct tree_list *list) -{ - //list->entries.size = 0; -} - -void tree_list_pump(struct tree_list *list) -{ - s32 size = (s32)list->entries.size; - if (size <= list->current) return; - struct tree_sink *sink; - if (list->current + 1 < size) { - // This needs a massive rethinking on how to sync the lists. - // - Query sinks on server side skip request? - //struct tree_list_entry *upcoming = &al_array_at(list->entries, list->current + 1); - //al_array_foreach(list->sinks, i, sink) { - // send_queue_cmd(list, sink, upcoming); - //} - } - if (list->set == list->current) return; - struct tree_list_entry *entry = &al_array_at(list->entries, list->current); - al_array_foreach(list->sinks, i, sink) { - send_set_cmd(list, sink, entry); - } - list->set = list->current; -} - -void tree_list_free(struct tree_list *list) -{ - al_str_free(&list->name); -} diff --git a/src/tree/list.h b/src/tree/list.h deleted file mode 100644 index 3702983..0000000 --- a/src/tree/list.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include <al/str.h> -#include <al/array.h> - -#include "../cache/entry.h" - -struct tree_list_entry { - u32 index; - str unique_id; - struct sho_post *post; - struct cch_entry *entry; - u16 node_id; -}; - -struct tree_sink; -struct tree_list { - str name; - s32 set; - s32 current; - bool backwards; - array(struct tree_list_entry) entries; - array(struct tree_sink *) sinks; - struct tree_server *tree; -}; - -void tree_list_init(struct tree_list *list, struct tree_server *tree, str *name); -void tree_list_add_sink(struct tree_list *list, struct tree_sink *sink); -void tree_list_remove_sink(struct tree_list *list, struct tree_sink *sink); -bool tree_list_add(struct tree_list *list, str *unique_id, u32 index); -bool tree_list_add_external(struct tree_list *list, str *path); -void tree_list_skip(struct tree_list *list, s32 n); -void tree_list_sort(struct tree_list *list); -void tree_list_shuffle(struct tree_list *list); -void tree_list_clear(struct tree_list *list); -void tree_list_pump(struct tree_list *list); -void tree_list_free(struct tree_list *list); diff --git a/src/tree/meson.build b/src/tree/meson.build deleted file mode 100644 index 3aba0a6..0000000 --- a/src/tree/meson.build +++ /dev/null @@ -1,7 +0,0 @@ -tree_src = [ - 'tree.c', - 'resource_manager.c', - 'list.c' -] -tree_deps = [common_deps, shoki, cache, bimu_server] -executable('tree', sources: tree_src, dependencies: tree_deps) diff --git a/src/tree/resource_manager.c b/src/tree/resource_manager.c deleted file mode 100644 index dd24310..0000000 --- a/src/tree/resource_manager.c +++ /dev/null @@ -1,75 +0,0 @@ -#include <al/random.h> -#include <aki/http.h> - -#include "resource_manager.h" - -static u8 packet_pool_callback(void *userdata, struct aki_packet *packet) -{ - (void)userdata; - struct tree_resource_request *request = (struct tree_resource_request *)packet->userdata; - aki_packet_stream_send_packet(request->stream, packet); - return AKI_PACKET_POOL_KEEP; -} - -static void packet_callback(void *userdata, struct aki_packet_stream *stream, struct aki_packet *packet) -{ - struct tree_resource_server *server = (struct tree_resource_server *)userdata; - struct tree_resource_request *request = al_alloc_object(struct tree_resource_request); - request->stream = stream; - request->id = aki_packet_read_u16(packet); - str unique_id; - aki_packet_read_str(packet, &unique_id); - al_str_clone(&request->unique_id, &unique_id); - request->index = aki_packet_read_u32(packet); - request->packet = aki_packet_pool_get(&server->pool); - request->packet->userdata = request; - request->server = server; - if (!server->request_resource(server->userdata, request)) { - aki_packet_pool_return(&server->pool, request->packet); - } - aki_packet_free(packet); -} - -static void connection_closed_callback(void *userdata, struct aki_packet_stream *stream) -{ - (void)userdata; - (void)stream; -} - -static void packet_sent_callback(void *userdata, struct aki_packet *packet) -{ - struct tree_resource_server *server = (struct tree_resource_server *)userdata; - struct tree_resource_request *request = (struct tree_resource_request *)packet->userdata; - aki_http_request_close(&request->request); - aki_packet_pool_return(&server->pool, packet); -} - -static void flushed_callback(void *userdata) -{ - (void)userdata; -} - -static void connection_callback(void *userdata, struct aki_packet_stream *stream) -{ - stream->userdata = userdata; - stream->packet_callback = packet_callback; - stream->packet_sent_callback = packet_sent_callback; - stream->connection_closed_callback = connection_closed_callback; - stream->flushed_callback = flushed_callback; -} - -bool tree_resource_server_init(struct tree_resource_server *server, - bool (*request_resource)(void *, struct tree_resource_request *), void *userdata) -{ - server->request_resource = request_resource; - server->userdata = userdata; - return aki_packet_stream_init(&server->server, AKI_SOCKET_TCP, connection_callback, - NULL, NULL, NULL, server); -} - -void tree_resource_server_listen(struct tree_resource_server *server, - struct aki_event_loop *loop, str *addr, s32 port) -{ - aki_packet_pool_init(&server->pool, 50, loop, packet_pool_callback, server); - aki_packet_stream_listen(&server->server, loop, addr, port); -} diff --git a/src/tree/resource_manager.h b/src/tree/resource_manager.h deleted file mode 100644 index a81e3a9..0000000 --- a/src/tree/resource_manager.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include <aki/packet_stream.h> -#include <aki/packet_pool.h> -#include <aki/http.h> - -struct tree_resource_request { - u16 id; - str unique_id; - u32 index; - struct aki_packet *packet; - struct aki_packet_stream *stream; - struct aki_http_request request; - struct tree_resource_server *server; -}; - -struct tree_resource_server { - struct aki_packet_stream server; - struct aki_packet_pool pool; - bool (*request_resource)(void *, struct tree_resource_request *); - void *userdata; -}; - -bool tree_resource_server_init(struct tree_resource_server *server, - bool (*request_resource)(void *, struct tree_resource_request *), void *userdata); -void tree_resource_server_listen(struct tree_resource_server *server, - struct aki_event_loop *loop, str *addr, s32 port); diff --git a/src/tree/tree.c b/src/tree/tree.c deleted file mode 100644 index c57d56c..0000000 --- a/src/tree/tree.c +++ /dev/null @@ -1,460 +0,0 @@ -#include <al/log.h> -#include <aki/file.h> -#include <blake3.h> -#include <jansson.h> - -#include "tree.h" -#include "common.h" - -#define USER_AGENT al_str_c("Mozilla/5.0 (Windows NT 10.0; rv:122.0) Gecko/20100101 Firefox/122.0") - -static void http_callback(void *userdata, struct aki_http_request *response, bool success) -{ - struct tree_resource_request *request = (struct tree_resource_request *)userdata; - struct aki_packet *packet = request->packet; - if (!success) { - aki_packet_pool_return(&request->server->pool, packet); - return; - } - aki_packet_write_u16(packet, request->id); - aki_packet_write_buffer(packet, &response->response); - aki_packet_pool_submit(&request->server->pool, packet); -} - -static bool request_resource(void *userdata, struct tree_resource_request *request) -{ - struct tree_server *tree = (struct tree_server *)userdata; - struct sho_post *post = sho_post_cache_get(&tree->resources.cache, &request->unique_id); - struct aki_packet *packet = request->packet; - if (!post) { - aki_packet_pool_return(&request->server->pool, packet); - return false; - } - str *url = NULL; - if (al_str_eq(&post->author.unique_id, &request->unique_id)) { - url = &post->author.profile_image_url; - } else { - if (post->media.size <= request->index) return false; - struct sho_post_media *media = &al_array_at(post->media, request->index); - url = &media->thumbnail_url; - } - aki_http_request_init(&request->request); - aki_http_set_url(&request->request.http, url); - aki_http_set_user_agent(&request->request.http, USER_AGENT); - if (!aki_http_request(&request->request, AKI_HTTP_GET, &tree->loop, http_callback, request)) { - aki_packet_pool_return(&request->server->pool, packet); - return false; - } - return true; -} - -static struct tree_user *get_user_by_username(struct tree_server *tree, str *username) -{ - struct tree_user *user; - al_array_foreach(tree->users, i, user) { - if (al_str_eq(&user->username, username)) { - return user; - } - } - return NULL; -} - -static struct tree_user *get_user_by_connection(struct tree_server *tree, struct aki_rpc_connection *conn) -{ - struct tree_user *user; - al_array_foreach(tree->users, i, user) { - struct tree_client *client; - al_array_foreach(user->clients, j, client) { - if (client->conn == conn) return user; - } - struct tree_list *list; - al_array_foreach(user->lists, j, list) { - struct tree_sink *sink; - al_array_foreach(list->sinks, k, sink) { - if (sink->conn == conn) return user; - } - } - } - return NULL; -} - -static void send_current_state(struct tree_server *server, struct tree_user *user, struct aki_rpc_connection *conn) -{ - struct aki_packet *packet = aki_rpc_get_packet(&server->server, TREE_CMD_UPDATE_STATE); - aki_packet_write_u32(packet, user->lists.size); - struct tree_list *list; - al_array_foreach(user->lists, i, list) { - aki_packet_write_str(packet, &list->name); - aki_packet_write_u32(packet, list->entries.size); - struct tree_list_entry *entry; - al_array_foreach_ptr(list->entries, i, entry) { - aki_packet_write_str(packet, &entry->unique_id); - } - aki_packet_write_s32(packet, list->current); - } - aki_packet_write_u32(packet, user->search.searches.size); - struct sho_search *search; - al_array_foreach(user->search.searches, i, search) { - aki_packet_write_s32(packet, search->id); - aki_packet_write_str(packet, &search->module); - aki_packet_write_str(packet, &search->query); - aki_packet_write_u32(packet, search->page); - } - aki_rpc_connection_command(conn, packet, NULL, NULL); -} - -static bool identify_command_callback(void *userdata, struct aki_rpc_connection *conn, - struct aki_packet *packet, struct aki_packet *rpacket) -{ - struct tree_server *tree = (struct tree_server *)userdata; - (void)rpacket; - switch (aki_packet_read_u8(packet)) { - case TREE_NODE: { - struct tree_node *node = al_alloc_object(struct tree_node); - node->conn = conn; - al_array_push(tree->nodes, node); - al_log_info("tree", "New node."); - break; - } - case TREE_CLIENT: { - str username; - aki_packet_read_str(packet, &username); - struct tree_user *user = get_user_by_username(tree, &username); - if (user) { - struct tree_client *client = al_alloc_object(struct tree_client); - client->conn = conn; - client->user = user; - al_array_push(tree->clients, client); - al_array_push(user->clients, client); - send_current_state(tree, user, conn); - al_log_info("tree", "User \"%.*s\" logged in.", AL_STR_PRINTF(&user->username)); - } - break; - } - case TREE_SINK: { - struct tree_sink *sink = al_alloc_object(struct tree_sink); - sink->conn = conn; - al_array_push(tree->sinks, sink); - struct tree_user *user = al_array_at(tree->users, 0); - struct tree_list *list = al_array_at(user->lists, 0); - tree_list_add_sink(list, sink); - al_log_info("tree", "New sink."); - break; - } - } - aki_packet_free(packet); - return true; -} - -static bool create_search_command_callback(void *userdata, struct aki_rpc_connection *conn, - struct aki_packet *packet, struct aki_packet *rpacket) -{ - struct tree_server *tree = (struct tree_server *)userdata; - struct tree_user *user = get_user_by_connection(tree, conn); - if (!user) { - aki_packet_write_s32(rpacket, -1); - goto out; - } - - str module, query; - aki_packet_read_str(packet, &module); - aki_packet_read_str(packet, &query); - aki_packet_write_s32(rpacket, sho_client_create_search(&user->search, &module, &query)); - -out: - aki_packet_free(packet); - return true; -} - -static bool get_page_command_callback(void *userdata, struct aki_rpc_connection *conn, - struct aki_packet *packet, struct aki_packet *rpacket) -{ - s32 id = aki_packet_read_s32(packet); - - // Always reciprocate the requested id, even if it turns out to be invalid. - aki_packet_write_s32(rpacket, id); - - struct tree_server *tree = (struct tree_server *)userdata; - struct tree_user *user = get_user_by_connection(tree, conn); - if (!user) { - aki_packet_write_s32(rpacket, -1); - goto out; - } - - u32 page_request = aki_packet_read_u32(packet); - - struct sho_search *search = sho_client_get_search(&user->search, id); - if (!search) { - aki_packet_write_s32(rpacket, -1); - goto out; - } - - if (!sho_search_get_page(search, page_request)) { - aki_packet_write_s32(rpacket, -1); - goto out; - } - - aki_packet_write_s32(rpacket, 0); - aki_packet_write_u32(rpacket, page_request); - struct sho_result_page *page = &al_array_at(search->pages, page_request); - aki_packet_write_u32(rpacket, page->posts.size); - struct sho_post *post; - al_array_foreach_ptr(page->posts, i, post) { - aki_packet_write_sho_post(rpacket, post); - } - aki_packet_write_u32(rpacket, page->list.size); - str *unique_id; - al_array_foreach_ptr(page->list, i, unique_id) { - aki_packet_write_str(rpacket, unique_id); - } - -out: - aki_packet_free(packet); - return true; -} - -static bool add_command_callback(void *userdata, struct aki_rpc_connection *conn, - struct aki_packet *packet, struct aki_packet *rpacket) -{ - struct tree_server *tree = (struct tree_server *)userdata; - (void)rpacket; - struct tree_user *user = get_user_by_connection(tree, conn); - if (!user) goto out; - - str unique_id; - aki_packet_read_str(packet, &unique_id); - u32 index = aki_packet_read_u32(packet); - - struct tree_list *list = al_array_at(user->lists, 0); - tree_list_add(list, &unique_id, index); - -out: - aki_packet_free(packet); - return false; -} - -static bool skip_command_callback(void *userdata, struct aki_rpc_connection *conn, - struct aki_packet *packet, struct aki_packet *rpacket) -{ - struct tree_server *tree = (struct tree_server *)userdata; - (void)rpacket; - struct tree_user *user = get_user_by_connection(tree, conn); - if (!user) goto out; - - s32 n = aki_packet_read_s32(packet); - - struct tree_list *list = al_array_at(user->lists, 0); - tree_list_skip(list, n); - -out: - aki_packet_free(packet); - return false; -} - -static void connection_callback(void *userdata, struct aki_rpc_connection *conn) -{ - (void)userdata; - (void)conn; -} - -static void cleanup_node(struct tree_node *node) -{ - al_free(node); -} - -static void cleanup_client(struct tree_client *client) -{ - al_free(client); -} - -static void cleanup_sink(struct tree_sink *sink) -{ - al_free(sink); -} - -static void connection_closed_callback(void *userdata, struct aki_rpc_connection *conn) -{ - struct tree_server *tree = (struct tree_server *)userdata; - - struct tree_node *node; - al_array_foreach(tree->nodes, i, node) { - if (node->conn == conn) { - al_log_info("tree", "Node removed."); - cleanup_node(node); - al_array_remove_at_iter(tree->nodes, i); - break; - } - } - - struct tree_client *client; - al_array_foreach(tree->clients, i, client) { - if (client->conn == conn) { - al_log_info("tree", "User \"%.*s\" logged out.", AL_STR_PRINTF(&client->user->username)); - cleanup_client(client); - al_array_remove_at_iter(tree->clients, i); - break; - } - } - - struct tree_sink *sink; - al_array_foreach(tree->sinks, i, sink) { - if (sink->conn == conn) { - al_log_info("tree", "Sink removed."); - al_array_remove_at_iter(tree->sinks, i); - struct tree_user *user = al_array_at(tree->users, 0); - struct tree_list *list = al_array_at(user->lists, 0); - tree_list_remove_sink(list, sink); - cleanup_sink(sink); - break; - } - } -} - -static struct aki_rpc_command commands[] = { - { .op = TREE_CMD_IDENTIFY, .callback = identify_command_callback, .userdata = NULL }, - { .op = TREE_CMD_CREATE_SEARCH, .callback = create_search_command_callback, .userdata = NULL }, - { .op = TREE_CMD_GET_PAGE, .callback = get_page_command_callback, .userdata = NULL }, - { .op = TREE_CMD_ADD, .callback = add_command_callback, .userdata = NULL }, - { .op = TREE_CMD_SKIP, .callback = skip_command_callback, .userdata = NULL } -}; - -static bool open_user(struct tree_server *tree, struct aki_dir_entry *dir) -{ - struct aki_file file; - if (!aki_file_open(&file, &dir->path, 0)) { - return false; - } - str s; - aki_file_read_as_str(&file, &s); - json_error_t error; - json_t *root = json_loadb(s.data, s.len, 0, &error); - if (!root) { - al_log_error("tree", "Failed to parse json: %.*s:%d:%d (%s).", AL_STR_PRINTF(&dir->path), - error.line, error.column, error.text); - return false; - } - struct tree_user *user = al_alloc_object(struct tree_user); - al_str_from(&user->username, json_string_value(json_object_get(root, "username"))); - sho_client_init(&user->search, &tree->resources.cache); - al_array_init(user->lists); - struct tree_list *default_list = al_alloc_object(struct tree_list); - tree_list_init(default_list, tree, al_str_c("default")); - al_array_push(user->lists, default_list); - al_array_init(user->clients); - al_log_info("tree", "Loaded user \"%.*s\"", AL_STR_PRINTF(&user->username)); - al_array_push(tree->users, user); - return true; -} - -static bool open_db(struct tree_server *tree, str *path) -{ - struct aki_dir camu_db; - if (!aki_dir_open(&camu_db, path)) { - return false; - } - struct aki_dir_entry entry; - while (aki_dir_read(&camu_db, &entry)) { - if (al_str_eq(&entry.name, al_str_c("users"))) { - struct aki_dir users; - if (aki_dir_open(&users, &entry.path)) { - struct aki_dir_entry user; - while (aki_dir_read(&users, &user)) { - if (user.type == AKI_ENTRY_FILE) { - open_user(tree, &user); - } - } - aki_dir_close(&users); - } - } - aki_dir_entry_free(&entry); - } - aki_dir_close(&camu_db); - return true; -} - -#if TREE_USE_SOCKET -static u8 line_callback(void *userdata, str *line) -{ - struct tree_server *tree = (struct tree_server *)userdata; - struct tree_user *user = al_array_at(tree->users, 0); - struct tree_list *list = al_array_at(user->lists, 0); - if (al_str_eq(line, al_str_c(";NEXT"))) { - tree_list_skip(list, 1); - } else if (al_str_eq(line, al_str_c(";PREV"))) { - tree_list_skip(list, -1); - } else if (al_str_eq(line, al_str_c(";SHUFFLE"))) { - tree_list_shuffle(list); - } else if (al_str_eq(line, al_str_c(";SORT"))) { - tree_list_sort(list); - } else if (al_str_eq(line, al_str_c(";CLEAR"))) { - tree_list_clear(list); - } else { - tree_list_add_external(list, line); - } - return AKI_LINE_PROCESSOR_CONTINUE; -} -#endif - -static void sigint_handler(s32 signum) -{ - (void)signum; - // explode. - exit(EXIT_SUCCESS); -} - -static struct tree_server tree = { 0 }; - -s32 main(void) -{ - aki_common_init(); - - signal(SIGINT, sigint_handler); - - al_array_init(tree.nodes); - al_array_init(tree.clients); - al_array_init(tree.sinks); - al_array_init(tree.users); - - if (!open_db(&tree, CAMU_DB_PATH)) return EXIT_FAILURE; - - sho_post_cache_init(&tree.resources.cache); - - bool py_init = sho_python_init(); - - aki_event_loop_init(&tree.loop); - - aki_rpc_init(&tree.server, AKI_SOCKET_TCP, connection_callback, - connection_closed_callback, &tree); - for (u32 i = 0; i < AL_ARRAY_SIZE(commands); i++) { - commands[i].userdata = &tree; - aki_rpc_add_command(&tree.server, &commands[i]); - } - aki_rpc_listen(&tree.server, &tree.loop, al_str_c("0.0.0.0"), TREE_PORT); - - tree_resource_server_init(&tree.resources.server, request_resource, &tree); - tree_resource_server_listen(&tree.resources.server, &tree.loop, al_str_c("0.0.0.0"), TREE_RESOURCE_PORT); - - bmu_server_init(&tree.streams.server); - bmu_server_listen(&tree.streams.server, &tree.loop, al_str_c("0.0.0.0"), TREE_STREAM_PORT); - -#if TREE_USE_SOCKET - tree.socket.type = AKI_SOCKET_UNIX; - aki_socket_init(&tree.socket); - aki_socket_set_blocking(&tree.socket, false); - tree.cli.callback = line_callback; - tree.cli.userdata = &tree; - aki_line_processor_init(&tree.cli, al_str_c("\n")); - aki_line_processor_open_socket(&tree.cli, &tree.socket); - if (aki_socket_listen(&tree.socket, al_str_c("/tmp/tree_sock"), 0)) { - aki_line_processor_run(&tree.cli, &tree.loop); - } -#endif - - aki_event_loop_run(&tree.loop); - - if (py_init) sho_python_close(); - - aki_common_close(); - - return EXIT_SUCCESS; -} diff --git a/src/tree/tree.h b/src/tree/tree.h deleted file mode 100644 index b8edaad..0000000 --- a/src/tree/tree.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#define TREE_USE_SOCKET 1 - -#include <aki/rpc2.h> -#include <sho/post.h> -#include <sho/post_cache.h> -#include <sho/search.h> -#if TREE_USE_SOCKET -#include <aki/line_processor.h> -#endif - -#include "../bimu/server.h" - -#include "resource_manager.h" -#include "list.h" - -struct tree_node { - struct aki_rpc_connection *conn; -}; - -struct tree_client { - struct aki_rpc_connection *conn; - struct tree_user *user; -}; - -struct tree_sink { - struct aki_rpc_connection *conn; -}; - -struct tree_user { - str username; - struct sho_client search; - array(struct tree_list *) lists; - array(struct tree_client *) clients; -}; - -struct tree_server { - struct aki_event_loop loop; - struct aki_rpc server; - array(struct tree_node *) nodes; - array(struct tree_client *) clients; - array(struct tree_sink *) sinks; - array(struct tree_user *) users; - struct { - struct sho_post_cache cache; - struct tree_resource_server server; - } resources; - struct { - struct bmu_server server; - } streams; -#if TREE_USE_SOCKET - struct aki_socket socket; - struct aki_line_processor cli; -#endif -}; |