diff --git a/src/Makefile.am b/src/Makefile.am index 00fd6730..dc36e8e3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ bin_PROGRAMS = icecast INCLUDES = -I./common/ noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \ - global.h util.h slave.h source.h stats.h refbuf.h client.h playlist.h \ + global.h util.h curl.h slave.h source.h stats.h refbuf.h client.h playlist.h \ compat.h fserve.h xslt.h yp.h md5.h \ event.h event_log.h event_exec.h event_url.h \ acl.h auth.h \ @@ -17,7 +17,7 @@ noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \ format_vorbis.h format_theora.h format_flac.h format_speex.h format_midi.h \ format_kate.h format_skeleton.h format_opus.h icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c \ - util.c slave.c source.c stats.c refbuf.c client.c playlist.c \ + util.c curl.c slave.c source.c stats.c refbuf.c client.c playlist.c \ xslt.c fserve.c admin.c md5.c \ format.c format_ogg.c format_mp3.c format_midi.c format_flac.c format_ebml.c \ format_kate.c format_skeleton.c format_opus.c \ diff --git a/src/auth_url.c b/src/auth_url.c index 5e928fd3..0b2bb86d 100644 --- a/src/auth_url.c +++ b/src/auth_url.c @@ -67,8 +67,7 @@ # define strncasecmp strnicmp #endif -#include - +#include "curl.h" #include "auth.h" #include "source.h" #include "client.h" @@ -105,7 +104,7 @@ static void auth_url_clear(auth_t *self) ICECAST_LOG_INFO("Doing auth URL cleanup"); url = self->state; self->state = NULL; - curl_easy_cleanup(url->handle); + icecast_curl_free(url->handle); free(url->username); free(url->password); free(url->pass_headers); @@ -120,17 +119,6 @@ static void auth_url_clear(auth_t *self) free(url); } - -#ifdef CURLOPT_PASSWDFUNCTION -/* make sure that prompting at the console does not occur */ -static int my_getpass(void *client, char *prompt, char *buffer, int buflen) -{ - buffer[0] = '\0'; - return 0; -} -#endif - - static size_t handle_returned_header(void *ptr, size_t size, size_t nmemb, @@ -165,16 +153,6 @@ static size_t handle_returned_header(void *ptr, return (int)bytes; } -/* capture returned data, but don't do anything with it */ -static size_t handle_returned_data(void *ptr, - size_t size, - size_t nmemb, - void *stream) -{ - return (int)(size*nmemb); -} - - static auth_result url_remove_client(auth_client *auth_user) { client_t *client = auth_user->client; @@ -494,7 +472,7 @@ int auth_get_url_auth(auth_t *authenticator, config_options_t *options) url_info->addaction = util_url_escape(addaction); url_info->removeaction = util_url_escape(removeaction); - url_info->handle = curl_easy_init(); + url_info->handle = icecast_curl_new(NULL, &url_info->errormsg[0]); if (url_info->handle == NULL) { auth_url_clear(authenticator); return -1; @@ -505,16 +483,7 @@ int auth_get_url_auth(auth_t *authenticator, config_options_t *options) if (url_info->timelimit_header) url_info->timelimit_header_len = strlen (url_info->timelimit_header); - curl_easy_setopt(url_info->handle, CURLOPT_USERAGENT, ICECAST_VERSION_STRING); curl_easy_setopt(url_info->handle, CURLOPT_HEADERFUNCTION, handle_returned_header); - curl_easy_setopt(url_info->handle, CURLOPT_WRITEFUNCTION, handle_returned_data); - curl_easy_setopt(url_info->handle, CURLOPT_WRITEDATA, url_info->handle); - curl_easy_setopt(url_info->handle, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(url_info->handle, CURLOPT_TIMEOUT, 15L); -#ifdef CURLOPT_PASSWDFUNCTION - curl_easy_setopt(url_info->handle, CURLOPT_PASSWDFUNCTION, my_getpass); -#endif - curl_easy_setopt(url_info->handle, CURLOPT_ERRORBUFFER, &url_info->errormsg[0]); if (url_info->username && url_info->password) { int len = strlen(url_info->username) + strlen(url_info->password) + 2; diff --git a/src/curl.c b/src/curl.c new file mode 100644 index 00000000..d928c1b0 --- /dev/null +++ b/src/curl.c @@ -0,0 +1,91 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2015, Philipp "ph3-der-loewe" Schafft , + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "curl.h" + +#include "logging.h" +#define CATMODULE "curl" + +#ifdef CURLOPT_PASSWDFUNCTION +/* make sure that prompting at the console does not occur */ +static int my_getpass(void *client, char *prompt, char *buffer, int buflen) { + buffer[0] = '\0'; + return 0; +} +#endif + +static size_t handle_returned (void *ptr, size_t size, size_t nmemb, void *stream) { + return size * nmemb; +} + +int icecast_curl_initialize(void) +{ +#ifdef HAVE_CURL_GLOBAL_INIT + CURLcode ret = curl_global_init(CURL_GLOBAL_ALL); + if (ret != 0) + return -1; +#endif + + return 0; +} + +int icecast_curl_shutdown(void) +{ + curl_global_cleanup(); + return 0; +} + +CURL *icecast_curl_new(const char *url, char * errors) +{ + ice_config_t *config; + CURL *curl = curl_easy_init(); + + if (!curl) + return NULL; + +#if XXXX + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, handle_returned_header); + curl_easy_setopt(url->handle, CURLOPT_USERPWD, url->userpwd); + curl_easy_setopt(self->handle, CURLOPT_POSTFIELDS, post); +#endif + + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3L); + curl_easy_setopt(curl, CURLOPT_WRITEHEADER, NULL); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_returned); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl); + +#ifdef CURLOPT_PASSWDFUNCTION + curl_easy_setopt(curl, CURLOPT_PASSWDFUNCTION, my_getpass); +#endif + + if (url) + curl_easy_setopt(curl, CURLOPT_URL, url); + if (errors) + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errors); + + config = config_get_config(); + curl_easy_setopt(curl, CURLOPT_USERAGENT, config->server_id); + config_release_config(); + + return curl; +} + +int icecast_curl_free(CURL *curl) +{ + if (!curl) + return -1; + curl_easy_cleanup(curl); + return 0; +} diff --git a/src/curl.h b/src/curl.h new file mode 100644 index 00000000..f57666b2 --- /dev/null +++ b/src/curl.h @@ -0,0 +1,26 @@ +/* Icecast + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2015, Philipp "ph3-der-loewe" Schafft , + */ + +#ifndef __CURL_H__ +#define __CURL_H__ + +#include + +/* initialize/shutdown libcurl. + * Those two functions are fully thread unsafe + * and must only be run by the main thread and + * only when no other thread is running. + */ +int icecast_curl_initialize(void); +int icecast_curl_shutdown(void); + +/* creator and destructor function for CURL* object. */ +CURL *icecast_curl_new(const char *url, char * errors); +int icecast_curl_free(CURL *curl); + +#endif diff --git a/src/event_url.c b/src/event_url.c index c8a92ab5..ed568551 100644 --- a/src/event_url.c +++ b/src/event_url.c @@ -11,8 +11,8 @@ #endif #include -#include +#include "curl.h" #include "event.h" #include "logging.h" #define CATMODULE "event_url" @@ -26,13 +26,6 @@ typedef struct event_url { char errormsg[CURL_ERROR_SIZE]; } event_url_t; -#ifdef CURLOPT_PASSWDFUNCTION -/* make sure that prompting at the console does not occur */ -static int my_getpass(void *client, char *prompt, char *buffer, int buflen) { - buffer[0] = '\0'; - return 0; -} -#endif static size_t handle_returned (void *ptr, size_t size, size_t nmemb, void *stream) { return size * nmemb; } @@ -47,7 +40,6 @@ static inline char *__escape(const char *src, const char *default_value) { static int event_url_emit(void *state, event_t *event) { event_url_t *self = state; ice_config_t *config; - char *url; char *action, *mount, *server, *role, *username, *ip, *agent; time_t duration; char post[4096]; @@ -88,29 +80,18 @@ static int event_url_emit(void *state, event_t *event) { curl_easy_setopt(self->handle, CURLOPT_USERPWD, ""); } - /* REVIEW: Why do we dup the url here? - * auth_url.c does it this way. I just copied the code. - * Maybe there is a reason for it, maybe not? - * -- Philipp Schafft, 2014-12-07. - */ - url = strdup(self->url); - - curl_easy_setopt(self->handle, CURLOPT_URL, url); + curl_easy_setopt(self->handle, CURLOPT_URL, self->url); curl_easy_setopt(self->handle, CURLOPT_POSTFIELDS, post); - curl_easy_setopt(self->handle, CURLOPT_WRITEHEADER, NULL); if (curl_easy_perform(self->handle)) - ICECAST_LOG_WARN("auth to server %s failed with %s", url, self->errormsg); - - free(url); + ICECAST_LOG_WARN("auth to server %s failed with %s", self->url, self->errormsg); return 0; } static void event_url_free(void *state) { event_url_t *self = state; - if (self->handle) - curl_easy_cleanup(self->handle); + icecast_curl_free(self->handle); free(self->url); free(self->action); free(self->userpwd); @@ -157,7 +138,7 @@ int event_get_url(event_registration_t *er, config_options_t *options) { } while ((options = options->next)); } - self->handle = curl_easy_init(); + self->handle = icecast_curl_new(NULL, NULL); /* check if we are in sane state */ if (!self->url || !self->handle) { @@ -165,15 +146,7 @@ int event_get_url(event_registration_t *er, config_options_t *options) { return -1; } - curl_easy_setopt(self->handle, CURLOPT_USERAGENT, ICECAST_VERSION_STRING); curl_easy_setopt(self->handle, CURLOPT_HEADERFUNCTION, handle_returned); - curl_easy_setopt(self->handle, CURLOPT_WRITEFUNCTION, handle_returned); - curl_easy_setopt(self->handle, CURLOPT_WRITEDATA, self->handle); - curl_easy_setopt(self->handle, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(self->handle, CURLOPT_TIMEOUT, 15L); -#ifdef CURLOPT_PASSWDFUNCTION - curl_easy_setopt(self->handle, CURLOPT_PASSWDFUNCTION, my_getpass); -#endif curl_easy_setopt(self->handle, CURLOPT_ERRORBUFFER, self->errormsg); if (username && password) { diff --git a/src/main.c b/src/main.c index 6acbc110..42759082 100644 --- a/src/main.c +++ b/src/main.c @@ -22,7 +22,7 @@ #include #ifdef HAVE_CURL -#include +#include "curl.h" #endif #ifdef WIN32 @@ -128,8 +128,8 @@ void initialize_subsystems(void) refbuf_initialize(); xslt_initialize(); -#ifdef HAVE_CURL_GLOBAL_INIT - curl_global_init (CURL_GLOBAL_ALL); +#ifdef HAVE_CURL + icecast_curl_initialize(); #endif } @@ -151,7 +151,7 @@ void shutdown_subsystems(void) thread_shutdown(); #ifdef HAVE_CURL - curl_global_cleanup(); + icecast_curl_shutdown(); #endif /* Now that these are done, we can stop the loggers. */ diff --git a/src/yp.c b/src/yp.c index a597fe99..684140b2 100644 --- a/src/yp.c +++ b/src/yp.c @@ -18,10 +18,10 @@ #include #include #include -#include #include "common/thread/thread.h" +#include "curl.h" #include "connection.h" #include "refbuf.h" #include "client.h" @@ -148,13 +148,6 @@ static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void } -/* capture returned data, but don't do anything with it, shouldn't be any */ -static size_t handle_returned_data (void *ptr, size_t size, size_t nmemb, void *stream) -{ - return (size_t)(size*nmemb); -} - - /* search the active and pending YP server lists */ static struct yp_server *find_yp_server (const char *url) { @@ -199,8 +192,7 @@ static void destroy_yp_server (struct yp_server *server) } delete_marked_yp(server); - if (server->curl) - curl_easy_cleanup (server->curl); + icecast_curl_free(server->curl); if (server->mounts) ICECAST_LOG_WARN("active ypdata not freed"); if (server->pending_mounts) ICECAST_LOG_WARN("pending ypdata not freed"); free (server->url); @@ -259,7 +251,7 @@ void yp_recheck_config (ice_config_t *config) server->url = strdup (config->yp_url[i]); server->url_timeout = config->yp_url_timeout[i]; server->touch_interval = config->yp_touch_interval[i]; - server->curl = curl_easy_init(); + server->curl = icecast_curl_new(server->url, &(server->curl_error[0])); if (server->curl == NULL) { destroy_yp_server (server); @@ -269,16 +261,7 @@ void yp_recheck_config (ice_config_t *config) server->url_timeout = 6; if (server->touch_interval < 30) server->touch_interval = 30; - curl_easy_setopt (server->curl, CURLOPT_USERAGENT, server->server_id); - curl_easy_setopt (server->curl, CURLOPT_URL, server->url); curl_easy_setopt (server->curl, CURLOPT_HEADERFUNCTION, handle_returned_header); - curl_easy_setopt (server->curl, CURLOPT_WRITEFUNCTION, handle_returned_data); - curl_easy_setopt (server->curl, CURLOPT_WRITEDATA, server->curl); - curl_easy_setopt (server->curl, CURLOPT_TIMEOUT, server->url_timeout); - curl_easy_setopt (server->curl, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt (server->curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt (server->curl, CURLOPT_MAXREDIRS, 3L); - curl_easy_setopt (server->curl, CURLOPT_ERRORBUFFER, &(server->curl_error[0])); server->next = (struct yp_server *)pending_yps; pending_yps = server; ICECAST_LOG_INFO("Adding new YP server \"%s\" (timeout %ds, default interval %ds)", @@ -1007,7 +990,6 @@ void yp_shutdown (void) yp_update = 1; if (yp_thread) thread_join (yp_thread); - curl_global_cleanup(); free ((char*)server_version); server_version = NULL; ICECAST_LOG_INFO("YP thread down");