1
0
Fork 0

Cleanup: move libcurl specifc code into curl.c

This cleans the libcurl usage up a bit. It moves common code used
to interact with libcurl into a single new file curl.[ch].

Notes:
* It does not alter any features nor fixes any bugs.
* Thew REVIEW about strdup(self->url) in event_url.c as been processed.
  According to the manpage for curl_easy_setopt()/CURLOPT_URL
  there is no need for us to copy.
* URL Auth as well as URL triggers have sent ICECAST_VERSION_STRING
  as User-Agent:, this has be corrected to what is set in the config
  file.
* As curl.c is now a single point for setting parameters all the TLS
  parameters should be reviewed and set (based on config).

Please test!
This commit is contained in:
Philipp Schafft 2015-04-08 07:44:36 +00:00
parent a1f204c184
commit 7402383448
7 changed files with 134 additions and 93 deletions

View File

@ -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 \

View File

@ -67,8 +67,7 @@
# define strncasecmp strnicmp
#endif
#include <curl/curl.h>
#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;

91
src/curl.c Normal file
View File

@ -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 <lion@lion.leolix.org>,
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#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;
}

26
src/curl.h Normal file
View File

@ -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 <lion@lion.leolix.org>,
*/
#ifndef __CURL_H__
#define __CURL_H__
#include <curl/curl.h>
/* 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

View File

@ -11,8 +11,8 @@
#endif
#include <string.h>
#include <curl/curl.h>
#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) {

View File

@ -22,7 +22,7 @@
#include <errno.h>
#ifdef HAVE_CURL
#include <curl/curl.h>
#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. */

View File

@ -18,10 +18,10 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <curl/curl.h>
#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");