diff options
Diffstat (limited to 'src/input/curl_input_plugin.c')
-rw-r--r-- | src/input/curl_input_plugin.c | 128 |
1 files changed, 75 insertions, 53 deletions
diff --git a/src/input/curl_input_plugin.c b/src/input/curl_input_plugin.c index 95d269ce5..c6e5a30af 100644 --- a/src/input/curl_input_plugin.c +++ b/src/input/curl_input_plugin.c @@ -17,12 +17,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "input/curl_input_plugin.h" #include "input_plugin.h" #include "conf.h" -#include "config.h" #include "tag.h" #include "icy_metadata.h" +#include "glib_compat.h" #include <assert.h> @@ -42,7 +43,7 @@ #define G_LOG_DOMAIN "input_curl" /** rewinding is possible after up to 64 kB */ -static const off_t max_rewind_size = 64 * 1024; +static const goffset max_rewind_size = 64 * 1024; /** * Buffers created by input_curl_writefunction(). @@ -102,8 +103,15 @@ static struct curl_slist *http_200_aliases; static const char *proxy, *proxy_user, *proxy_password; static unsigned proxy_port; +static inline GQuark +curl_quark(void) +{ + return g_quark_from_static_string("curl"); +} + static bool -input_curl_init(const struct config_param *param) +input_curl_init(const struct config_param *param, + G_GNUC_UNUSED GError **error_r) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); if (code != CURLE_OK) { @@ -150,11 +158,6 @@ buffer_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) g_free(data); } -/* g_queue_clear() was introduced in GLib 2.14 */ -#if !GLIB_CHECK_VERSION(2,14,0) -#define g_queue_clear(q) do { g_queue_free(q); q = g_queue_new(); } while (0) -#endif - /** * Frees the current "libcurl easy" handle, and everything associated * with it. @@ -219,7 +222,7 @@ input_curl_tag(struct input_stream *is) } static bool -input_curl_multi_info_read(struct input_stream *is) +input_curl_multi_info_read(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMsg *msg; @@ -232,8 +235,9 @@ input_curl_multi_info_read(struct input_stream *is) is->ready = true; if (msg->data.result != CURLE_OK) { - g_warning("curl failed: %s\n", c->error); - is->error = -1; + g_set_error(error_r, curl_quark(), + msg->data.result, + "curl failed: %s", c->error); return false; } } @@ -249,7 +253,7 @@ input_curl_multi_info_read(struct input_stream *is) * available */ static int -input_curl_select(struct input_curl *c) +input_curl_select(struct input_curl *c, GError **error_r) { fd_set rfds, wfds, efds; int max_fd, ret; @@ -268,8 +272,9 @@ input_curl_select(struct input_curl *c) mcode = curl_multi_fdset(c->multi, &rfds, &wfds, &efds, &max_fd); if (mcode != CURLM_OK) { - g_warning("curl_multi_fdset() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_fdset() failed: %s", + curl_multi_strerror(mcode)); return -1; } @@ -277,13 +282,15 @@ input_curl_select(struct input_curl *c) ret = select(max_fd + 1, &rfds, &wfds, &efds, &timeout); if (ret < 0) - g_warning("select() failed: %s\n", strerror(errno)); + g_set_error(error_r, g_quark_from_static_string("errno"), + errno, + "select() failed: %s\n", g_strerror(errno)); return ret; } static bool -fill_buffer(struct input_stream *is) +fill_buffer(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMcode mcode = CURLM_CALL_MULTI_PERFORM; @@ -295,7 +302,7 @@ fill_buffer(struct input_stream *is) if (mcode != CURLM_CALL_MULTI_PERFORM) { /* if we're still here, there is no input yet - wait for input */ - int ret = input_curl_select(c); + int ret = input_curl_select(c, error_r); if (ret <= 0) /* no data yet or error */ return false; @@ -303,14 +310,15 @@ fill_buffer(struct input_stream *is) mcode = curl_multi_perform(c->multi, &running_handles); if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); c->eof = true; is->ready = true; return false; } - bret = input_curl_multi_info_read(is); + bret = input_curl_multi_info_read(is, error_r); if (!bret) return false; } @@ -407,14 +415,15 @@ copy_icy_tag(struct input_curl *c) if (c->tag != NULL) tag_free(c->tag); - if (c->meta_name != NULL && !tag_has_type(tag, TAG_ITEM_NAME)) - tag_add_item(tag, TAG_ITEM_NAME, c->meta_name); + if (c->meta_name != NULL && !tag_has_type(tag, TAG_NAME)) + tag_add_item(tag, TAG_NAME, c->meta_name); c->tag = tag; } static size_t -input_curl_read(struct input_stream *is, void *ptr, size_t size) +input_curl_read(struct input_stream *is, void *ptr, size_t size, + GError **error_r) { struct input_curl *c = is->data; bool success; @@ -425,7 +434,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size) #ifndef NDEBUG if (c->rewind != NULL && (!g_queue_is_empty(c->rewind) || is->offset == 0)) { - off_t offset = 0; + goffset offset = 0; struct buffer *buffer; for (GList *list = g_queue_peek_head_link(c->rewind); @@ -446,7 +455,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size) do { /* fill the buffer */ - success = fill_buffer(is); + success = fill_buffer(is, error_r); if (!success) return 0; @@ -474,11 +483,11 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size) if (icy_defined(&c->icy_metadata)) copy_icy_tag(c); - is->offset += (off_t)nbytes; + is->offset += (goffset)nbytes; #ifndef NDEBUG if (rewind_buffers != NULL) { - off_t offset = 0; + goffset offset = 0; struct buffer *buffer; for (GList *list = g_queue_peek_head_link(c->rewind); @@ -521,7 +530,7 @@ input_curl_eof(G_GNUC_UNUSED struct input_stream *is) } static int -input_curl_buffer(struct input_stream *is) +input_curl_buffer(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLMcode mcode; @@ -534,7 +543,8 @@ input_curl_buffer(struct input_stream *is) /* not ready yet means the caller is waiting in a busy loop; relax that by calling select() on the socket */ - input_curl_select(c); + if (input_curl_select(c, error_r) < 0) + return -1; do { mcode = curl_multi_perform(c->multi, &running_handles); @@ -542,14 +552,15 @@ input_curl_buffer(struct input_stream *is) g_queue_is_empty(c->buffers)); if (mcode != CURLM_OK && mcode != CURLM_CALL_MULTI_PERFORM) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); c->eof = true; is->ready = true; return -1; } - ret = input_curl_multi_info_read(is); + ret = input_curl_multi_info_read(is, error_r); if (!ret) return -1; @@ -614,7 +625,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream) tag_free(c->tag); c->tag = tag_new(); - tag_add_item(c->tag, TAG_ITEM_NAME, c->meta_name); + tag_add_item(c->tag, TAG_NAME, c->meta_name); } else if (g_ascii_strcasecmp(name, "icy-metaint") == 0) { char buffer[64]; size_t icy_metaint; @@ -675,7 +686,7 @@ input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream) } static bool -input_curl_easy_init(struct input_stream *is) +input_curl_easy_init(struct input_stream *is, GError **error_r) { struct input_curl *c = is->data; CURLcode code; @@ -685,13 +696,18 @@ input_curl_easy_init(struct input_stream *is) c->easy = curl_easy_init(); if (c->easy == NULL) { - g_warning("curl_easy_init() failed\n"); + g_set_error(error_r, curl_quark(), 0, + "curl_easy_init() failed"); return false; } mcode = curl_multi_add_handle(c->multi, c->easy); - if (mcode != CURLM_OK) + if (mcode != CURLM_OK) { + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_add_handle() failed: %s", + curl_multi_strerror(mcode)); return false; + } curl_easy_setopt(c->easy, CURLOPT_USERAGENT, "Music Player Daemon " VERSION); @@ -721,8 +737,12 @@ input_curl_easy_init(struct input_stream *is) } code = curl_easy_setopt(c->easy, CURLOPT_URL, c->url); - if (code != CURLE_OK) + if (code != CURLE_OK) { + g_set_error(error_r, curl_quark(), code, + "curl_easy_setopt() failed: %s", + curl_easy_strerror(code)); return false; + } c->request_headers = NULL; c->request_headers = curl_slist_append(c->request_headers, @@ -733,7 +753,7 @@ input_curl_easy_init(struct input_stream *is) } static bool -input_curl_send_request(struct input_curl *c) +input_curl_send_request(struct input_curl *c, GError **error_r) { CURLMcode mcode; int running_handles; @@ -743,8 +763,9 @@ input_curl_send_request(struct input_curl *c) } while (mcode == CURLM_CALL_MULTI_PERFORM); if (mcode != CURLM_OK) { - g_warning("curl_multi_perform() failed: %s\n", - curl_multi_strerror(mcode)); + g_set_error(error_r, curl_quark(), mcode, + "curl_multi_perform() failed: %s", + curl_multi_strerror(mcode)); return false; } @@ -772,7 +793,7 @@ input_curl_can_rewind(struct input_stream *is) /* rewind is possible if this is the very first buffer of the resource */ buffer = (struct buffer*)g_queue_peek_head(c->buffers); - return (off_t)buffer->consumed == is->offset; + return (goffset)buffer->consumed == is->offset; } static void @@ -780,7 +801,7 @@ input_curl_rewind(struct input_stream *is) { struct input_curl *c = is->data; #ifndef NDEBUG - off_t offset = 0; + goffset offset = 0; #endif assert(c->rewind != NULL); @@ -818,7 +839,8 @@ input_curl_rewind(struct input_stream *is) } static bool -input_curl_seek(struct input_stream *is, off_t offset, int whence) +input_curl_seek(struct input_stream *is, goffset offset, int whence, + GError **error_r) { struct input_curl *c = is->data; bool ret; @@ -884,7 +906,7 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence) buffer = (struct buffer *)g_queue_pop_head(c->buffers); length = buffer->size - buffer->consumed; - if (offset - is->offset < (off_t)length) + if (offset - is->offset < (goffset)length) length = offset - is->offset; buffer = consume_buffer(buffer, length, rewind_buffers); @@ -910,7 +932,7 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence) return true; } - ret = input_curl_easy_init(is); + ret = input_curl_easy_init(is, error_r); if (!ret) return false; @@ -921,15 +943,15 @@ input_curl_seek(struct input_stream *is, off_t offset, int whence) curl_easy_setopt(c->easy, CURLOPT_RANGE, c->range); } - ret = input_curl_send_request(c); + ret = input_curl_send_request(c, error_r); if (!ret) return false; - return input_curl_multi_info_read(is); + return input_curl_multi_info_read(is, error_r); } static bool -input_curl_open(struct input_stream *is, const char *url) +input_curl_open(struct input_stream *is, const char *url, GError **error_r) { struct input_curl *c; bool ret; @@ -947,8 +969,8 @@ input_curl_open(struct input_stream *is, const char *url) c->multi = curl_multi_init(); if (c->multi == NULL) { - g_warning("curl_multi_init() failed\n"); - + g_set_error(error_r, curl_quark(), 0, + "curl_multi_init() failed"); input_curl_free(is); return false; } @@ -956,19 +978,19 @@ input_curl_open(struct input_stream *is, const char *url) icy_clear(&c->icy_metadata); c->tag = NULL; - ret = input_curl_easy_init(is); + ret = input_curl_easy_init(is, error_r); if (!ret) { input_curl_free(is); return false; } - ret = input_curl_send_request(c); + ret = input_curl_send_request(c, error_r); if (!ret) { input_curl_free(is); return false; } - ret = input_curl_multi_info_read(is); + ret = input_curl_multi_info_read(is, error_r); if (!ret) { input_curl_free(is); return false; |