From b4cbca161a1638e96d9e0a6fe12a29ed43173e43 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Mon, 16 Aug 2010 00:51:20 +0200 Subject: Committed some work. --- SConstruct | 17 ++++++++++++ commands.c | 31 +++++++++++++++++++++ commands.h | 8 ++++++ httpd.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ httpd.h | 9 ++++++ main.c | 22 +++++++++++++++ music.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ music.h | 29 ++++++++++++++++++++ 8 files changed, 298 insertions(+) create mode 100644 SConstruct create mode 100644 commands.c create mode 100644 commands.h create mode 100644 httpd.c create mode 100644 httpd.h create mode 100644 main.c create mode 100644 music.c create mode 100644 music.h diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..bf87dfe --- /dev/null +++ b/SConstruct @@ -0,0 +1,17 @@ +AddOption('--release', action = 'store_true') + +env = Environment(CPPPATH = ['.']) + +env.Append(CCFLAGS = ['-std=c99']) + +if GetOption('release'): + env.Append(CCFLAGS = ['-O2']) +else: + env.Append(CCFLAGS = ['-Wall', '-g']) + +env.ParseConfig('pkg-config --cflags --libs glib-2.0') +env.ParseConfig('pkg-config --cflags --libs gio-2.0') + +env.Program('foo', Glob('*.c')) + +# vim: syn=python diff --git a/commands.c b/commands.c new file mode 100644 index 0000000..b11b09c --- /dev/null +++ b/commands.c @@ -0,0 +1,31 @@ +#include "commands.h" +#include "music.h" + +#include +#include + +static void commands_list(GSocketConnection *connection, const gchar *cmd) { + gchar **data = g_strsplit(cmd, " ", 2); + for(gint i = 0; data[i]; i++) { + g_debug("\tdata[%d] = %s", i, data[i]); + } + g_assert(data[0] != NULL && data[1] != NULL); + + gchar *dirname = g_strdup(data[1]); + + struct directory *directory = music_find_dir(dirname); + g_assert(directory != NULL); + + GSocket *socket = g_socket_connection_get_socket(connection); + for(struct file *f = directory->files; f; f = f->next) { + g_socket_send(socket, f->name, strlen(f->name), NULL, NULL); + g_socket_send(socket, "\n", 1, NULL, NULL); + } +} + +void commands_handle(GSocketConnection *connection, const gchar *cmd) { + g_debug("handling command string %s", cmd); + if(g_ascii_strncasecmp(cmd, "/list", 5) == 0) { + commands_list(connection, cmd); + } +} diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..7b90f95 --- /dev/null +++ b/commands.h @@ -0,0 +1,8 @@ +#ifndef _COMMANDS_H_ +#define _COMMANDS_H_ + +#include + +void commands_handle(GSocketConnection *connection, const gchar *cmd); + +#endif diff --git a/httpd.c b/httpd.c new file mode 100644 index 0000000..49b6b1e --- /dev/null +++ b/httpd.c @@ -0,0 +1,92 @@ +#include "httpd.h" +#include "commands.h" + +#include +#include + +GSocketService *ss = NULL; + +static gboolean service_incoming(GSocketService *service, + GSocketConnection *connection, GObject *source_object, + gpointer user_data) { + GSocket *socket; + GError *error = NULL; + + g_debug("incoming connection to service"); + + socket = g_socket_connection_get_socket(connection); + if(socket == NULL) { + g_error("g_socket_connection_get_socket() returned NULL"); + return FALSE; + } + + GString *string = g_string_new(NULL); + gboolean done = FALSE; + gssize tot = 0; + + while(done == FALSE) { + gchar buffer[0x400]; + gssize len = g_socket_receive(socket, buffer, 0x400, NULL, &error); + if(len == -1) { + g_error(error->message); + g_error_free(error); + return FALSE; + } + tot += len; + g_string_append_len(string, buffer, len); + + /* TODO: find a more sane way to stop reading */ + if(string->len >= 4 && g_strcmp0(string->str + string->len - 4, "\r\n\r\n") == 0) { + done = TRUE; + } + } + g_debug("read %lu bytes", tot); + g_debug("HTTP header:\n%s", string->str); + + /* split headers */ + gchar **data = g_strsplit(string->str, "\r\n", 0); + + g_string_free(string, TRUE); + + gchar **firstline = g_strsplit(data[0], " ", 0); + /* this sets the first character of the last string in + * firstline to \0 (HTTP version) */ + firstline[g_strv_length(firstline)-1] = '\0'; + /* now join from the second string to get the request path */ + gchar *path = g_strjoinv(" ", firstline + 1); + + g_strfreev(firstline); + + for(gint i = 1; strlen(data[i]); i++) { + g_debug("data[%d] = %s", i, data[i]); + } + + g_strfreev(data); + + commands_handle(connection, path); + + if(g_socket_close(socket, &error) == FALSE) { + g_error(error->message); + g_error_free(error); + return FALSE; + } + + return FALSE; +} + +gboolean httpd_start() { + ss = g_threaded_socket_service_new(10); + + g_socket_listener_add_inet_port((GSocketListener*)ss, 8000, NULL, NULL); + + g_signal_connect(ss, "incoming", (GCallback)service_incoming, NULL); + g_socket_service_start(ss); + + return TRUE; +} + +void httpd_stop() { + g_socket_service_stop(ss); + g_free(ss); + ss = NULL; +} diff --git a/httpd.h b/httpd.h new file mode 100644 index 0000000..73b2c2f --- /dev/null +++ b/httpd.h @@ -0,0 +1,9 @@ +#ifndef _HTTPD_H_ +#define _HTTPD_H_ + +#include + +gboolean httpd_start(); +void httpd_stop(); + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..bcf52d8 --- /dev/null +++ b/main.c @@ -0,0 +1,22 @@ +#include "music.h" +#include "httpd.h" + +#include +#include + +int main(int argc, char **argv) { + g_type_init(); + + music_init(argv[1]); + music_scan_root(); + + httpd_start(); + + GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(main_loop); + + httpd_stop(); + music_free(); + + return 0; +} diff --git a/music.c b/music.c new file mode 100644 index 0000000..2e618bd --- /dev/null +++ b/music.c @@ -0,0 +1,90 @@ +#include "music.h" + +#include + +struct directory *music_root = NULL; + +gboolean music_init(const gchar *path) { + music_root = g_new0(struct directory, 1); + music_root->path = g_strdup(path); + + return 1; +} + +gboolean music_scan(struct directory *directory) { + GError *error = NULL; + GDir *dir = g_dir_open(directory->path, 0, &error); + + if(dir == NULL) { + g_error("%s", error->message); + g_error_free(error); + return 0; + } + + const gchar *entry; + while((entry = g_dir_read_name(dir)) != NULL) { + struct file *f = g_new0(struct file, 1); + f->name = g_strdup(entry); + + if(directory->files == NULL) { + directory->files = f; + } else { + struct file *last = directory->files; + while(last->next) last = last->next; + last->next = f; + } + } + + g_dir_close(dir); + + return 1; +} + +gboolean music_scan_root() { + g_assert(music_root != NULL); + + return music_scan(music_root); +} + +static struct directory *music_find_dir_rec(struct directory *root, const gchar *path) { + if(g_strcmp0(root->path, path) == 0) + return root; + + /* TODO: implement this */ + g_error("not implemented"); + + return NULL; +} + +struct directory *music_find_dir(const gchar *path) { + return music_find_dir_rec(music_root, path); +} + +static void music_do_free(struct directory *root) { + struct directory *node; + + g_assert(root != NULL); + + for(node = root->sub; node; node = node->next) { + music_do_free(node); + } + + for(node = root->next; node; node = node->next) { + music_do_free(node); + } + + for(struct file *f = root->files; f; f = f->next) { + g_free(f->name); + g_free(f); + } + + g_free(root->path); + g_free(root); +} + +void music_free() { + g_assert(music_root != NULL); + + music_do_free(music_root); + music_root = NULL; +} diff --git a/music.h b/music.h new file mode 100644 index 0000000..a51204e --- /dev/null +++ b/music.h @@ -0,0 +1,29 @@ +#ifndef _MUSIC_H_ +#define _MUSIC_H_ + +/* for size_t */ +#include + +#include + +struct file { + gchar *name; + gssize size; + struct file *next; +}; + +struct directory { + char *path; + struct directory *sub, *next; + struct file *files; +}; + +extern struct directory *music_root; + +gboolean music_init(const gchar *path); +gboolean music_scan(struct directory *directory); +gboolean music_scan_root(); +struct directory *music_find_dir(const gchar *path); +void music_free(); + +#endif -- cgit v1.2.3