summaryrefslogtreecommitdiff
path: root/src/tree
diff options
context:
space:
mode:
Diffstat (limited to 'src/tree')
-rw-r--r--src/tree/common.h27
-rw-r--r--src/tree/list.c247
-rw-r--r--src/tree/list.h37
-rw-r--r--src/tree/meson.build7
-rw-r--r--src/tree/resource_manager.c75
-rw-r--r--src/tree/resource_manager.h27
-rw-r--r--src/tree/tree.c460
-rw-r--r--src/tree/tree.h56
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
-};