From 6fd511dd41c8925e70c8e3c0ab2bcde8e1af06de Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Sun, 29 Aug 2010 21:09:48 +0200 Subject: Support for fetching files via HTTP, needs more work and fixes. --- commands.c | 27 +++++++++++++ server_communication.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ server_communication.h | 2 + 3 files changed, 134 insertions(+) diff --git a/commands.c b/commands.c index 4108cff..bde61cd 100644 --- a/commands.c +++ b/commands.c @@ -175,6 +175,31 @@ static void commands_exit(GSocketConnection *connection, const gchar *cmd, GErro g_socket_close(socket, NULL); } +static void commands_get(GSocketConnection *connection, const gchar *cmd, GError **error) { + gchar **data = g_strsplit(cmd, " ", 5); + + if(g_strv_length(data) != 5) { + g_strfreev(data); + *error = g_error_new(commands_quark(), 0, "syntax: get TYPE LOCALFILE REMOTEHOST REMOTEFILE"); + return; + } + + struct server *server = NULL; + + for(GSList *node = servers; node; node = g_slist_next(node)) { + struct server *temp = node->data; + if(g_strcasecmp(temp->host, data[3]) == 0) { + server = temp; + break; + } + } + + + server_get(server, data[1], data[2], data[4]); + + g_strfreev(data); +} + void commands_handle(GSocketConnection *connection, const gchar *cmd, GError **error) { g_debug(cmd); if(g_strncasecmp(cmd, "ping", 4) == 0) { @@ -185,6 +210,8 @@ void commands_handle(GSocketConnection *connection, const gchar *cmd, GError **e commands_find(connection, cmd, error); } else if(g_strncasecmp(cmd, "exit", 4) == 0) { commands_exit(connection, cmd, error); + } else if(g_strncasecmp(cmd, "get", 3) == 0) { + commands_get(connection, cmd, error); } else { g_debug("unknown command"); *error = g_error_new(commands_quark(), 0, "unknown command %s", cmd); diff --git a/server_communication.c b/server_communication.c index cc37cde..ffe6942 100644 --- a/server_communication.c +++ b/server_communication.c @@ -110,3 +110,108 @@ gchar **server_list(struct server *server, const gchar *directory) { 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; +} diff --git a/server_communication.h b/server_communication.h index 7d7bc7c..ecf1fdb 100644 --- a/server_communication.h +++ b/server_communication.h @@ -8,5 +8,7 @@ gboolean server_ping(struct server *server); gchar **server_find(struct server *server, const gchar *type, const gchar *str); gchar **server_list(struct server *server, const gchar *directory); +gboolean server_get(struct server *server, const gchar *type, + const gchar *localfile, const gchar *remotefile); #endif -- cgit v1.2.3