#include "httpd_commands.h" #include "music.h" #include "transcode.h" #include "decoder.h" #include "encoder.h" #include #include #include static void send_404(GSocketConnection *connection) { GError *error = NULL; GString *string = g_string_new(NULL); g_string_append(string, "HTTP/1.1 404 Not Found\r\n"); g_string_append(string, "\r\n"); GOutputStream *os = g_io_stream_get_output_stream((GIOStream*)connection); if(g_output_stream_write_all(os, string->str, string->len, NULL, NULL, &error) == FALSE) { g_warning(error->message); g_error_free(error); } } static void commands_get_raw(GSocketConnection *connection, const gchar *cmd) { GError *error = NULL; gchar **data = g_strsplit(cmd, " ", 2); g_assert(data[0] != NULL && data[1] != NULL); gchar *path = g_strdup(data[1]); g_strfreev(data); struct file *f = music_find_file(path); if(f == NULL) { g_warning("couldn't find %s", path); send_404(connection); goto commands_get_raw_free_path; } GOutputStream *os = g_io_stream_get_output_stream((GIOStream*)connection); gchar *full_path = music_get_full_path(path); GFile *file = g_file_new_for_path(full_path); g_free(full_path); GFileInputStream *is = g_file_read(file, NULL, &error); if(is == NULL) { g_warning(error->message); g_error_free(error); goto commands_get_raw_file_unref; } GFileInfo *fi = g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, &error); if(fi == NULL) { g_warning(error->message); g_error_free(error); goto commands_get_raw_file_unref; } goffset filesize = g_file_info_get_size(fi); g_object_unref(fi); GString *string = g_string_new(NULL); g_string_append(string, "HTTP/1.1 200 OK\r\n"); g_string_append(string, "content-type: application/octet-stream\r\n"); g_string_append_printf(string, "content-length: %lu\r\n", filesize); g_string_append(string, "\r\n"); if(g_output_stream_write_all(os, string->str, string->len, NULL, NULL, &error) == FALSE) { g_warning(error->message); g_error_free(error); g_string_free(string, TRUE); goto commands_get_raw_file_unref; } g_string_free(string, TRUE); gssize size = g_output_stream_splice(os, (GInputStream*)is, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE || G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error); if(size == -1) { g_warning(error->message); } else { g_debug("wrote %lu bytes of file data", size); } commands_get_raw_file_unref: g_object_unref(is); g_object_unref(file); commands_get_raw_free_path: g_free(path); } static void commands_get_mp3(GSocketConnection *connection, const gchar *cmd) { GError *error = NULL; gchar **data = g_strsplit(cmd, " ", 2); g_assert(data[0] != NULL && data[1] != NULL); gchar *path = g_strdup(data[1]); g_strfreev(data); struct file *f = music_find_file(path); if(f == NULL) { g_warning("couldn't find %s", path); send_404(connection); goto commands_get_mp3_free_path; } GOutputStream *os = g_io_stream_get_output_stream((GIOStream*)connection); gchar *full_path = music_get_full_path(path); GFile *file = g_file_new_for_path(full_path); g_free(full_path); GFileInputStream *is = g_file_read(file, NULL, &error); if(is == NULL) { g_warning(error->message); g_error_free(error); goto commands_get_mp3_file_unref; } GString *string = g_string_new(NULL); g_string_append(string, "HTTP/1.1 200 OK\r\n"); g_string_append(string, "content-type: application/octet-stream\r\n"); g_string_append(string, "\r\n"); if(g_output_stream_write_all(os, string->str, string->len, NULL, NULL, &error) == FALSE) { g_warning(error->message); g_error_free(error); g_string_free(string, TRUE); goto commands_get_mp3_file_unref; } g_string_free(string, TRUE); const struct decoder_plugin *decoder = decoder_find(path); const struct encoder_plugin *encoder = encoder_get("lame"); if(decoder == NULL) { g_warning("no suitable decoder found"); goto commands_get_mp3_file_unref; } else { g_debug("using decoder %s", decoder->name); } if(encoder == NULL) { g_warning("no encoder found"); goto commands_get_mp3_file_unref; } transcode((GInputStream*)is, decoder, os, encoder); commands_get_mp3_file_unref: g_object_unref(is); g_object_unref(file); commands_get_mp3_free_path: g_free(path); } void httpd_commands_handle(GSocketConnection *connection, const gchar *cmd) { g_debug("handling command string %s", cmd); if(g_ascii_strncasecmp(cmd, "/get_raw", 8) == 0) { commands_get_raw(connection, cmd); } else if(g_ascii_strncasecmp(cmd, "/get_mp3", 8) == 0) { commands_get_mp3(connection, cmd); } else { g_warning("no command handlers found"); } }