#include "server_communication.h" #include "music.h" #include #include enum connection_type { SERVER_CONNECTION_TYPE_HTTP, SERVER_CONNECTION_TYPE_COMMAND, }; static GSocket *server_connect(struct server *server, const enum connection_type type, GError **error) { GError *conn_error = NULL; GSocketConnectable *addr; GSocketAddressEnumerator *enumerator; GSocketAddress *sockaddr; GSocketConnection *conn = NULL; GSocketClient *client; guint16 port; switch(type) { case SERVER_CONNECTION_TYPE_HTTP: port = server->http_port; break; case SERVER_CONNECTION_TYPE_COMMAND: port = server->command_port; break; } addr = g_network_address_new(server->host, port); enumerator = g_socket_connectable_enumerate(addr); g_object_unref(addr); client = g_socket_client_new(); while(conn == NULL && (sockaddr = g_socket_address_enumerator_next(enumerator, NULL, error))) { conn = g_socket_client_connect(client, (GSocketConnectable*)sockaddr, NULL, &conn_error); g_object_unref(sockaddr); } if(conn != NULL) { if(conn_error != NULL) { g_error_free(conn_error); } return g_socket_connection_get_socket(conn); } else if(*error != NULL) { if(conn_error != NULL) { g_error_free(conn_error); } return NULL; } else { g_propagate_error(error, conn_error); return NULL; } } static GSocket *server_connect_http(struct server *server, GError **error) { return server_connect(server, SERVER_CONNECTION_TYPE_HTTP, error); } static GSocket *server_connect_command(struct server *server, GError **error) { return server_connect(server, SERVER_CONNECTION_TYPE_COMMAND, error); } gboolean server_ping(struct server *server, GError **error) { GTimer *timer = g_timer_new(); GSocket *socket = server_connect_command(server, error); if(socket == NULL) { return FALSE; } gboolean result = FALSE; g_socket_send(socket, "ping\n", 5, NULL, NULL); gchar buffer[0x400]; gssize size = g_socket_receive(socket, buffer, 0x400, NULL, NULL); if(size == 5 && strncmp(buffer, "pong", 4) == 0) { g_debug("ping response: %f ms", g_timer_elapsed(timer, NULL) * 1000); result = TRUE; } g_timer_destroy(timer); g_socket_close(socket, NULL); return result; } static gchar **server_get_stringlist(struct server *server, const gchar *cmd, GError **error) { GSocket *socket = server_connect_command(server, error); if(socket == NULL) { return NULL; } g_socket_send(socket, cmd, strlen(cmd), NULL, NULL); gchar buffer[0x400]; gssize size; GString *string = g_string_new(NULL); while((size = g_socket_receive(socket, buffer, 0x400, NULL, NULL)) > 0) { g_string_append_len(string, buffer, size); } g_socket_close(socket, NULL); gchar **data = g_strsplit(string->str, "\n", 0); g_string_free(string, TRUE); return data; } gchar **server_find(struct server *server, const gchar *type, const gchar *str, GError **error) { gchar *cmd = g_strdup_printf("findl %s %s\nexit\n", type, str); gchar **data = server_get_stringlist(server, cmd, error); g_free(cmd); return data; } gchar **server_list(struct server *server, const gchar *directory, GError **error) { gchar *cmd = g_strdup_printf("list %s\nexit\n", directory); gchar **data = server_get_stringlist(server, cmd, error); g_free(cmd); return data; } gboolean server_get(struct server *server, const gchar *type, const gchar *localfile, const gchar *remotefile, GError **error) { GSocket *socket = server_connect_http(server, error); if(socket == NULL) { return FALSE; } gchar *cmd = g_strdup_printf("GET /get_%s %s HTTP/1.1\r\n\r\n", type, remotefile); g_socket_send(socket, cmd, strlen(cmd), NULL, NULL); GSocketConnection *connection = g_socket_connection_factory_create_connection(socket); GDataInputStream *input = g_data_input_stream_new(g_io_stream_get_input_stream((GIOStream*)connection)); g_data_input_stream_set_newline_type(input, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); gchar *line = NULL; gsize size; while((line = g_data_input_stream_read_line(input, &size, NULL, error)) != NULL) { g_debug(line); if(size == 0) { break; } } if(*error != NULL) { return FALSE; } GFile *file = g_file_new_for_path(localfile); GFileOutputStream *output = g_file_replace(file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); if(output == NULL) { return FALSE; } g_output_stream_splice((GOutputStream*)output, (GInputStream*)input, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, error); g_object_unref(input); g_object_unref(output); g_object_unref(file); g_object_unref(connection); g_object_unref(socket); if(*error != NULL) { return FALSE; } return TRUE; }