#define AL_LOG_SECTION "client" #include #include #include "client.h" #include "common.h" #include "../server/common.h" #include "../liana/list.h" static bool results_callback(void *userdata, struct nn_rpc_connection *conn, struct nn_packet *packet, struct nn_packet *rpacket) { struct camu_client *client = (struct camu_client *)userdata; (void)conn; (void)rpacket; u8 op = nn_packet_read_u8(packet); switch (op) { case CAMU_CLIENT_CREATE_SEARCH: { s32 id = nn_packet_read_s32(packet); client->callback(client->userdata, CAMU_CLIENT_SEARCH_CREATED, &id); break; } case CAMU_CLIENT_GET_PAGE: client->callback(client->userdata, CAMU_CLIENT_GOT_RESULTS, packet); break; } nn_packet_stream_return_packet(conn->stream, packet); return false; } static bool meta_callback(void *userdata, struct nn_rpc_connection *conn, struct nn_packet *packet, struct nn_packet *rpacket) { struct camu_client *client = (struct camu_client *)userdata; (void)conn; (void)rpacket; client->callback(client->userdata, CAMU_CLIENT_GOT_META, packet); nn_packet_stream_return_packet(conn->stream, packet); return false; } static bool visual_data_callback(void *userdata, struct nn_rpc_connection *conn, struct nn_packet *packet, struct nn_packet *rpacket) { struct camu_client *client = (struct camu_client *)userdata; (void)conn; (void)rpacket; client->callback(client->userdata, CAMU_CLIENT_GOT_VISUAL_DATA, packet); nn_packet_stream_return_packet(conn->stream, packet); return false; } static struct nn_rpc_command commands[] = { { .op = CAMU_CLIENT_RESULTS, .callback = results_callback, .userdata = NULL }, { .op = CAMU_CLIENT_META, .callback = meta_callback, .userdata = NULL }, { .op = CAMU_CLIENT_VISUAL_DATA, .callback = visual_data_callback, .userdata = NULL } }; static void idd_callback(void *userdata, struct nn_rpc_connection *conn, struct nn_packet *packet) { struct camu_client *client = (struct camu_client *)userdata; client->callback(client->userdata, CAMU_CLIENT_LOGGED_IN, packet); log_info("Logged in."); nn_packet_stream_return_packet(conn->stream, packet); } static void connection_callback(void *userdata, struct nn_rpc_connection *conn) { struct camu_client *client = (struct camu_client *)userdata; client->conn = conn; struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_IDENTIFY); nn_packet_write_u8(packet, CAMU_CLIENT); nn_packet_write_str(packet, &client->username); nn_rpc_connection_command(client->conn, packet, idd_callback, client); } static void connection_closed_callback(void *userdata, struct nn_rpc_connection *conn) { struct camu_client *client = (struct camu_client *)userdata; al_assert(client->conn == NULL || client->conn == conn); client->conn = NULL; } bool camu_client_login(struct camu_client *client, str *username, struct nn_event_loop *loop, u8 type, str *addr, u16 port) { client->loop = loop; al_str_clone(&client->username, username); client->conn = NULL; nn_rpc_init(&client->client, client->loop, connection_callback, connection_closed_callback, client); for (u32 i = 0; i < ARRAY_SIZE(commands); i++) { commands[i].userdata = client; nn_rpc_add_command(&client->client, &commands[i]); } nn_rpc_prepare_client(&client->client); #ifdef CAMU_DIRECT_MODE (void)type; (void)addr; (void)port; struct nn_rpc_connection *conn = client->client.conn; nn_multiplex_direct_connect(conn->stream, CAMU_MULTIPLEX_RPC); #else nn_rpc_connect(&client->client, CAMU_MULTIPLEX_RPC, type, addr, port); #endif return true; } void camu_client_create_list(struct camu_client *client, str *name, void (*callback)(void *, struct nn_rpc_connection *conn, struct nn_packet *), void *userdata) { struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_CLIENT_COMMAND); nn_packet_write_u8(packet, CAMU_CLIENT_CREATE_LIST); nn_packet_write_str(packet, name); nn_rpc_connection_command(client->conn, packet, callback, userdata); } void camu_client_toggle_sink(struct camu_client *client, str *sink, str *list, bool enable, void (*callback)(void *, struct nn_rpc_connection *conn, struct nn_packet *), void *userdata) { struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_CLIENT_COMMAND); nn_packet_write_u8(packet, CAMU_CLIENT_TOGGLE_SINK); nn_packet_write_str(packet, sink); nn_packet_write_str(packet, list); nn_packet_write_bool(packet, enable); nn_rpc_connection_command(client->conn, packet, callback, userdata); } void camu_client_create_search(struct camu_client *client, str *module, str *query) { struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_CLIENT_COMMAND); nn_packet_write_u8(packet, CAMU_CLIENT_CREATE_SEARCH); nn_packet_write_str(packet, module); nn_packet_write_str(packet, query); nn_rpc_connection_command(client->conn, packet, NULL, NULL); } void camu_client_get_page(struct camu_client *client, s32 id, u32 num) { struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_CLIENT_COMMAND); nn_packet_write_u8(packet, CAMU_CLIENT_GET_PAGE); nn_packet_write_s32(packet, id); nn_packet_write_u32(packet, num); nn_rpc_connection_command(client->conn, packet, NULL, NULL); } void camu_client_request_visual_data(struct camu_client *client, u32 node_id) { struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_CLIENT_COMMAND); nn_packet_write_u8(packet, CAMU_CLIENT_REQUEST_VISUAL_DATA); nn_packet_write_u32(packet, node_id); nn_rpc_connection_command(client->conn, packet, NULL, NULL); } void camu_client_skipto(struct camu_client *client, str *list, s32 i) { struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_LIST_ACTION); nn_packet_write_str(packet, list); nn_packet_write_u8(packet, CAMU_LIST_SKIPTO); nn_packet_write_s32(packet, LIANA_SEQUENCE_ANY); nn_packet_write_s32(packet, i); nn_rpc_connection_command(client->conn, packet, NULL, NULL); } void camu_client_seek(struct camu_client *client, str *list, u32 id, u64 pos) { struct nn_packet *packet = nn_rpc_get_packet(&client->client, CAMU_SERVER_LIST_ACTION); nn_packet_write_str(packet, list); nn_packet_write_u8(packet, CAMU_LIST_SEEK); nn_packet_write_s32(packet, LIANA_SEQUENCE_ANY); nn_packet_write_u32(packet, id); nn_packet_write_u64(packet, pos); nn_rpc_connection_command(client->conn, packet, NULL, NULL); } void camu_client_disconnect(struct camu_client *client) { nn_rpc_conn_flush(client->conn); }