summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands.c27
-rw-r--r--server_communication.c105
-rw-r--r--server_communication.h2
3 files changed, 134 insertions, 0 deletions
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