#include "server_communication.h" #include "music.h" #include #include static GSocket *server_connect(struct server *server) { GError *error = NULL, *conn_error = NULL; GSocketConnectable *addr; GSocketAddressEnumerator *enumerator; GSocketAddress *sockaddr; GSocketConnection *conn = NULL; GSocketClient *client; addr = g_network_address_new(server->host, server->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(sockaddr == NULL) { if(error != NULL) { g_warning(error->message); g_error_free(error); } else { g_warning("server_connect: no connectable addresses found for host %s", server->host); } return NULL; } if(conn == NULL) { g_warning(conn_error->message); g_error_free(conn_error); return NULL; } GSocket *socket = g_socket_connection_get_socket(conn); g_debug("connected"); return socket; } gboolean server_ping(struct server *server) { GTimer *timer = g_timer_new(); GSocket *socket = server_connect(server); 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) { GSocket *socket = server_connect(server); 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) { gchar *cmd = g_strdup_printf("findl %s %s\nexit\n", type, str); gchar **data = server_get_stringlist(server, cmd); g_free(cmd); return data; } gchar **server_list(struct server *server, const gchar *directory) { gchar *cmd = g_strdup_printf("list %s\nexit\n", directory); gchar **data = server_get_stringlist(server, cmd); g_free(cmd); return data; } /* TODO: remove temporary function */ static GSocket *server_connect_port(struct server *server, gushort port) { GError *error = NULL, *conn_error = NULL; GSocketConnectable *addr; GSocketAddressEnumerator *enumerator; GSocketAddress *sockaddr; GSocketConnection *conn = NULL; GSocketClient *client; 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(sockaddr == NULL) { if(error != NULL) { g_warning(error->message); g_error_free(error); } else { g_warning("server_connect: no connectable addresses found for host %s", server->host); } return NULL; } if(conn == NULL) { g_warning(conn_error->message); g_error_free(conn_error); return NULL; } GSocket *socket = g_socket_connection_get_socket(conn); g_debug("connected"); return socket; } gboolean server_get(struct server *server, const gchar *type, const gchar *localfile, const gchar *remotefile) { GError *error = NULL; GSocket *socket = server_connect_port(server, 8000); 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) { g_warning(error->message); g_error_free(error); 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) { g_warning(error->message); g_error_free(error); 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); if(error != NULL) { g_warning(error->message); g_error_free(error); return FALSE; } g_object_unref(connection); return TRUE; }