From 9e168dc8707f4f78b394bc1f662ed9373e77a6fe Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 6 Feb 2003 13:10:48 +0000 Subject: [PATCH] Lots of fixes for screwy code formatting, plus: make streams public by default, send ice-private: 1 to make them private. However, default config file has yp servers commented out. A little fix for compilation on some solaris systems Redo some config file stuff: now all the passwords are inside an element , (though for now they're also accepted in the old location), and added admin username and password. Move some of the admin activities over to using the admin passwords (admin action that affect a mountpoint use the source password) Fill in some (but not yet all, maybe i'll do that later) of the infrastructure for per-mountpoint passwords. Fix lots of headers/code so that it works properly/portably on non-win32 systems. svn path=/trunk/icecast/; revision=4325 --- TODO | 22 +++++++++ conf/icecast.xml | 29 +++++++---- src/config.c | 76 +++++++++++++++++++++++----- src/config.h | 6 ++- src/configtest.c | 4 +- src/connection.c | 36 +++++++++----- src/fserve.c | 2 +- src/geturl.c | 49 +++++++++--------- src/geturl.h | 3 +- src/net/sock.c | 2 +- src/net/sock.h | 4 ++ src/source.c | 121 ++++++++++++++++++++++++++------------------- src/source.h | 4 ++ src/stats.c | 8 +-- src/yp.c | 126 ++++++++++++++++++++++++----------------------- src/yp.h | 35 +++++++------ 16 files changed, 328 insertions(+), 199 deletions(-) diff --git a/TODO b/TODO index 0ab9cfaa..a3d97ff5 100644 --- a/TODO +++ b/TODO @@ -8,6 +8,8 @@ BUGS - make install - doesn't install configs? +- pthread/bsd: -pthread instead of -lpthread (autoconf) + FEATURES -------- @@ -30,4 +32,24 @@ FEATURES - stats to list currently connected clients: ip and hostname +- stream switching (drop clients to another stream on disconnect of source) + - a) fallbacks from named location to new mountpoint + - OR b) fallbacks for connected clients to new mountpoint (so newly-connecting + clients just get a 404 on the old path) + - OR c) combination - first one, plus generic alias ability? + +- /admin/* for all admin functionality + - configuring fallbacks + - mp3 metadata injection + - remote shutdown? + +- general registerable url-handlers in connection.c rather than hard-coded list + (already getting unmaintainable) + +- httpp - split out query string for further processing + +- finish mp3 metadata: http://server:ip/admin.cgi?pass=%s&mode=updinfo&mount=%s&song=%s + + + diff --git a/conf/icecast.xml b/conf/icecast.xml index e9eafaf3..a6fb5c8b 100644 --- a/conf/icecast.xml +++ b/conf/icecast.xml @@ -11,12 +11,23 @@ 10 - hackme - hackme + + + hackme + + hackme - - http://www.oddsock.org/cgi-bin/yp-cgi - + + admin + hackme + + + + localhost 8000 @@ -30,15 +41,15 @@ 1 - /usr/local/icecast2 - /usr/local/icecast2/logs - /usr/local/icecast2/web + /usr/local/icecast + /usr/local/icecast/logs + /usr/local/icecast/web access.log error.log - 4 + 4 diff --git a/src/config.c b/src/config.c index 0681b96b..4bbe1d61 100644 --- a/src/config.c +++ b/src/config.c @@ -54,6 +54,7 @@ static void _parse_directory(xmlDocPtr doc, xmlNodePtr node); static void _parse_paths(xmlDocPtr doc, xmlNodePtr node); static void _parse_logging(xmlDocPtr doc, xmlNodePtr node); static void _parse_security(xmlDocPtr doc, xmlNodePtr node); +static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node); static void _add_server(xmlDocPtr doc, xmlNodePtr node); void config_initialize(void) @@ -171,7 +172,7 @@ static void _set_defaults(void) _configuration.relay_password = CONFIG_DEFAULT_RELAY_PASSWORD; _configuration.ice_login = CONFIG_DEFAULT_ICE_LOGIN; _configuration.fileserve = CONFIG_DEFAULT_FILESERVE; - _configuration.touch_freq = CONFIG_DEFAULT_TOUCH_FREQ; + _configuration.touch_interval = CONFIG_DEFAULT_TOUCH_FREQ; _configuration.dir_list = NULL; _configuration.hostname = CONFIG_DEFAULT_HOSTNAME; _configuration.port = CONFIG_DEFAULT_PORT; @@ -207,7 +208,10 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node) } else if (strcmp(node->name, "admin") == 0) { if (_configuration.admin && _configuration.admin != CONFIG_DEFAULT_ADMIN) xmlFree(_configuration.admin); _configuration.admin = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - } else if (strcmp(node->name, "source-password") == 0) { + } else if(strcmp(node->name, "authentication") == 0) { + _parse_authentication(doc, node->xmlChildrenNode); + } else if (strcmp(node->name, "source-password") == 0) { + /* TODO: This is the backwards-compatibility location */ char *mount, *pass; if ((mount = (char *)xmlGetProp(node, "mount")) != NULL) { pass = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); @@ -218,8 +222,9 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node) _configuration.source_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); } } else if (strcmp(node->name, "relay-password") == 0) { - if (_configuration.relay_password && _configuration.relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(_configuration.relay_password); - _configuration.relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + /* TODO: This is the backwards-compatibility location */ + if (_configuration.relay_password && _configuration.relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(_configuration.relay_password); + _configuration.relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); } else if (strcmp(node->name, "icelogin") == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); _configuration.ice_login = atoi(tmp); @@ -300,6 +305,47 @@ static void _parse_limits(xmlDocPtr doc, xmlNodePtr node) } while ((node = node->next)); } +static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node) +{ + do { + if (node == NULL) break; + if (xmlIsBlankNode(node)) continue; + + if (strcmp(node->name, "source-password") == 0) { + char *mount, *pass; + if ((mount = (char *)xmlGetProp(node, "mount")) != NULL) { + pass = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + /* FIXME: This is a placeholder for per-mount passwords */ + } + else { + if (_configuration.source_password && + _configuration.source_password != + CONFIG_DEFAULT_SOURCE_PASSWORD) + xmlFree(_configuration.source_password); + _configuration.source_password = + (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } + } else if (strcmp(node->name, "relay-password") == 0) { + if (_configuration.relay_password && + _configuration.relay_password != + CONFIG_DEFAULT_RELAY_PASSWORD) + xmlFree(_configuration.relay_password); + _configuration.relay_password = + (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } else if (strcmp(node->name, "admin-password") == 0) { + if(_configuration.admin_password) + xmlFree(_configuration.admin_password); + _configuration.admin_password = + (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } else if (strcmp(node->name, "admin-user") == 0) { + if(_configuration.admin_username) + xmlFree(_configuration.admin_username); + _configuration.admin_username = + (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + } + } while ((node = node->next)); +} + static void _parse_directory(xmlDocPtr doc, xmlNodePtr node) { char *tmp; @@ -313,16 +359,19 @@ static void _parse_directory(xmlDocPtr doc, xmlNodePtr node) if (xmlIsBlankNode(node)) continue; if (strcmp(node->name, "yp-url") == 0) { - if (_configuration.yp_url[_configuration.num_yp_directories]) xmlFree(_configuration.yp_url[_configuration.num_yp_directories]); - _configuration.yp_url[_configuration.num_yp_directories] = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (_configuration.yp_url[_configuration.num_yp_directories]) + xmlFree(_configuration.yp_url[_configuration.num_yp_directories]); + _configuration.yp_url[_configuration.num_yp_directories] = + (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); } else if (strcmp(node->name, "yp-url-timeout") == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - _configuration.yp_url_timeout[_configuration.num_yp_directories] = atoi(tmp); + _configuration.yp_url_timeout[_configuration.num_yp_directories] = + atoi(tmp); } else if (strcmp(node->name, "server") == 0) { _add_server(doc, node->xmlChildrenNode); - } else if (strcmp(node->name, "touch-freq") == 0) { + } else if (strcmp(node->name, "touch-interval") == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - _configuration.touch_freq = atoi(tmp); + _configuration.touch_interval = atoi(tmp); if (tmp) xmlFree(tmp); } } while ((node = node->next)); @@ -411,7 +460,7 @@ static void _add_server(xmlDocPtr doc, xmlNodePtr node) char *tmp; server = (ice_config_dir_t *)malloc(sizeof(ice_config_dir_t)); - server->touch_freq = _configuration.touch_freq; + server->touch_interval = _configuration.touch_interval; server->host = NULL; addnode = 0; @@ -420,11 +469,12 @@ static void _add_server(xmlDocPtr doc, xmlNodePtr node) if (xmlIsBlankNode(node)) continue; if (strcmp(node->name, "host") == 0) { - server->host = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + server->host = (char *)xmlNodeListGetString(doc, + node->xmlChildrenNode, 1); addnode = 1; - } else if (strcmp(node->name, "touch-freq") == 0) { + } else if (strcmp(node->name, "touch-interval") == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - server->touch_freq = atoi(tmp); + server->touch_interval = atoi(tmp); if (tmp) xmlFree(tmp); } server->next = NULL; diff --git a/src/config.h b/src/config.h index a91f9400..ee620335 100644 --- a/src/config.h +++ b/src/config.h @@ -11,7 +11,7 @@ typedef struct ice_config_dir_tag { char *host; - int touch_freq; + int touch_interval; struct ice_config_dir_tag *next; } ice_config_dir_t; @@ -31,8 +31,10 @@ typedef struct ice_config_tag char *source_password; char *relay_password; + char *admin_username; + char *admin_password; - int touch_freq; + int touch_interval; ice_config_dir_t *dir_list; char *hostname; diff --git a/src/configtest.c b/src/configtest.c index fa17d3dc..e98f8885 100644 --- a/src/configtest.c +++ b/src/configtest.c @@ -32,11 +32,11 @@ void _dump_config(ice_config_t *config) printf("threadpool_size = %d\n", config->threadpool_size); printf("client_timeout = %d\n", config->client_timeout); printf("source_password = %s\n", config->source_password); - printf("touch_freq = %d\n", config->touch_freq); + printf("touch_interval = %d\n", config->touch_interval); node = config->dir_list; while (node) { - printf("directory.touch_freq = %d\n", node->touch_freq); + printf("directory.touch_interval = %d\n", node->touch_interval); printf("directory.host = %s\n", node->host); node = node->next; diff --git a/src/connection.c b/src/connection.c index ec123f15..553913da 100644 --- a/src/connection.c +++ b/src/connection.c @@ -404,7 +404,17 @@ static int _check_relay_pass(http_parser_t *parser) return _check_pass_http(parser, "relay", pass); } -static int _check_source_pass(http_parser_t *parser) +static int _check_admin_pass(http_parser_t *parser) +{ + char *pass = config_get_config()->admin_password; + char *user = config_get_config()->admin_username; + if(!pass || !user) + return 0; + + return _check_pass_http(parser, "admin", pass); +} + +static int _check_source_pass(http_parser_t *parser, char *mount) { char *pass = config_get_config()->source_password; int ret; @@ -428,15 +438,15 @@ static void handle_fallback_request(client_t *client) char *mount, *value, *old; int bytes; - if(!_check_source_pass(client->parser)) { + mount = httpp_get_query_param(client->parser, "mount"); + value = httpp_get_query_param(client->parser, "fallback"); + + if(!_check_source_pass(client->parser, mount)) { INFO0("Bad or missing password on fallback configuration request"); client_send_401(client); return; } - mount = httpp_get_query_param(client->parser, "mount"); - value = httpp_get_query_param(client->parser, "fallback"); - if(value == NULL || mount == NULL) { client_send_400(client, "Missing parameter"); return; @@ -472,16 +482,16 @@ static void handle_metadata_request(client_t *client) mp3_state *state; int bytes; - if(!_check_source_pass(client->parser)) { + action = httpp_get_query_param(client->parser, "mode"); + mount = httpp_get_query_param(client->parser, "mount"); + value = httpp_get_query_param(client->parser, "song"); + + if(!_check_source_pass(client->parser, mount)) { INFO0("Metadata request with wrong or missing password"); client_send_401(client); return; } - action = httpp_get_query_param(client->parser, "mode"); - mount = httpp_get_query_param(client->parser, "mount"); - value = httpp_get_query_param(client->parser, "song"); - if(value == NULL || action == NULL || mount == NULL) { client_send_400(client, "Missing parameter"); return; @@ -533,7 +543,7 @@ static void _handle_source_request(connection_t *con, INFO1("Source logging in at mountpoint \"%s\"", uri); stats_event_inc(NULL, "source_connections"); - if (!_check_source_pass(parser)) { + if (!_check_source_pass(parser, uri)) { INFO1("Source (%s) attempted to login with invalid or missing password", uri); client_send_401(client); return; @@ -564,7 +574,7 @@ static void _handle_stats_request(connection_t *con, stats_event_inc(NULL, "stats_connections"); - if (!_check_source_pass(parser)) { + if (!_check_admin_pass(parser)) { ERROR0("Bad password for stats connection"); connection_close(con); httpp_destroy(parser); @@ -606,7 +616,7 @@ static void _handle_get_request(connection_t *con, */ /* TODO: add GUID-xxxxxx */ if (strcmp(uri, "/admin/stats.xml") == 0) { - if (!_check_source_pass(parser)) { + if (!_check_admin_pass(parser)) { INFO0("Request for /admin/stats.xml with incorrect or no password"); client_send_401(client); return; diff --git a/src/fserve.c b/src/fserve.c index 41b439b5..35b5d84c 100644 --- a/src/fserve.c +++ b/src/fserve.c @@ -226,7 +226,7 @@ static void *fserv_thread_function(void *arg) &client->buf[client->offset], client->datasize - client->offset); - // TODO: remove clients if they take too long. + /* TODO: remove clients if they take too long. */ if(sbytes >= 0) { client->offset += sbytes; client->client->con->sent_bytes += sbytes; diff --git a/src/geturl.c b/src/geturl.c index afc47552..76fbc5e3 100644 --- a/src/geturl.c +++ b/src/geturl.c @@ -1,5 +1,6 @@ #include #include +#include #include @@ -20,10 +21,10 @@ #define CATMODULE "geturl" static curl_connection curl_connections[NUM_CONNECTIONS]; -mutex_t _curl_mutex; +static mutex_t _curl_mutex; -size_t -curl_write_memory_callback(void *ptr, size_t size, size_t nmemb, void *data) +size_t curl_write_memory_callback(void *ptr, size_t size, + size_t nmemb, void *data) { register int realsize = size * nmemb; @@ -35,8 +36,9 @@ curl_write_memory_callback(void *ptr, size_t size, size_t nmemb, void *data) return realsize; } -size_t -curl_header_memory_callback(void *ptr, size_t size, size_t nmemb, void *data) + +size_t curl_header_memory_callback(void *ptr, size_t size, + size_t nmemb, void *data) { char *p1 = 0; char *p2 = 0; @@ -48,19 +50,18 @@ curl_header_memory_callback(void *ptr, size_t size, size_t nmemb, void *data) p1 = (char *)ptr + strlen("SID: "); p2 = strchr((const char *)p1, '\r'); memset(mem->sid, '\000', sizeof(mem->sid)); - if (p2) { - if (p2-p1 > sizeof(mem->sid)-1) { - copylen = sizeof(mem->sid)-1; - } - else { - copylen = p2-p1; - } - strncpy(mem->sid, p1, copylen); + if (p2) { + if (p2-p1 > sizeof(mem->sid)-1) { + copylen = sizeof(mem->sid)-1; } else { - strncpy(mem->sid, p1, sizeof(mem->sid)-1); - strcpy(mem->sid, p1); + copylen = p2-p1; } + strncpy(mem->sid, p1, copylen); + } + else { + strncpy(mem->sid, p1, sizeof(mem->sid)-1); + } } if (!strncmp(ptr, "YPMessage: ", strlen("YPMessage: "))) { p1 = (char *)ptr + strlen("YPMessage: "); @@ -77,12 +78,11 @@ curl_header_memory_callback(void *ptr, size_t size, size_t nmemb, void *data) } else { strncpy(mem->message, p1, sizeof(mem->message)-1); - strcpy(mem->message, p1); } } if (!strncmp(ptr, "TouchFreq: ", strlen("TouchFreq: "))) { p1 = (char *)ptr + strlen("TouchFreq: "); - mem->touch_freq = atoi(p1); + mem->touch_interval = atoi(p1); } if (!strncmp(ptr, "YPResponse: ", strlen("YPResponse: "))) { p1 = (char *)ptr + strlen("YPResponse: "); @@ -95,13 +95,14 @@ int curl_initialize() int i = 0; thread_mutex_create(&_curl_mutex); - memset(&curl_connections, '\000', sizeof(curl_connections)); + memset(&curl_connections, 0, sizeof(curl_connections)); for (i=0; i (%s)", mem->sid); DEBUG1("Message -> (%s)", mem->message); - DEBUG1("Touch Freq -> (%d)", mem->touch_freq); + DEBUG1("Touch Freq -> (%d)", mem->touch_interval); DEBUG1("Response -> (%d)", mem->response); } @@ -164,6 +165,7 @@ CURL *curl_get_handle(int which) { return curl_connections[which].curl_handle; } + struct curl_memory_struct *curl_get_result(int which) { return &(curl_connections[which].result); @@ -173,3 +175,4 @@ struct curl_memory_struct2 *curl_get_header_result(int which) { return &(curl_connections[which].header_result); } + diff --git a/src/geturl.h b/src/geturl.h index 396773f3..51606639 100644 --- a/src/geturl.h +++ b/src/geturl.h @@ -20,7 +20,7 @@ struct curl_memory_struct { struct curl_memory_struct2 { char sid[YP_SID_SIZE]; char message[YP_RESPONSE_SIZE]; - int touch_freq; + int touch_interval; int response; size_t size; }; @@ -41,5 +41,6 @@ struct curl_memory_struct2 *curl_get_header_result(int which); void curl_print_header_result(struct curl_memory_struct2 *mem); int curl_get_connection(); int curl_release_connection(int which); + #endif diff --git a/src/net/sock.c b/src/net/sock.c index ab5dbec1..6b8feee3 100644 --- a/src/net/sock.c +++ b/src/net/sock.c @@ -665,7 +665,7 @@ int sock_accept(sock_t serversock, char *ip, int len) ret = accept(serversock, (struct sockaddr *)&sin, &slen); if (ret >= 0 && ip != NULL) { - // inet_ntoa is not reentrant, we should protect this + /* inet_ntoa is not reentrant, we should protect this */ strncpy(ip, inet_ntoa(sin.sin_addr), len); sock_set_nolinger(ret); sock_set_keepalive(ret); diff --git a/src/net/sock.h b/src/net/sock.h index 42cf278a..fa0d261c 100644 --- a/src/net/sock.h +++ b/src/net/sock.h @@ -42,6 +42,10 @@ struct iovec #endif #endif +#ifdef HAVE_INET_PTON +#define inet_aton(a,b) inet_pton(AF_INET, (a), (b)) +#endif + typedef int sock_t; /* The following values are based on unix avoiding errno value clashes */ diff --git a/src/source.c b/src/source.c index cc82c955..f4f799f3 100644 --- a/src/source.c +++ b/src/source.c @@ -53,14 +53,17 @@ source_t *source_create(client_t *client, connection_t *con, http_parser_t *pars src->parser = parser; src->client_tree = avl_tree_new(_compare_clients, NULL); src->pending_tree = avl_tree_new(_compare_clients, NULL); + src->running = 1; src->num_yp_directories = 0; src->listeners = 0; for (i=0;inum_yp_directories;i++) { if (config_get_config()->yp_url[i]) { src->ypdata[src->num_yp_directories] = yp_create_ypdata(); - src->ypdata[src->num_yp_directories]->yp_url = config_get_config()->yp_url[i]; - src->ypdata[src->num_yp_directories]->yp_url_timeout = config_get_config()->yp_url_timeout[i]; - src->ypdata[src->num_yp_directories]->yp_touch_freq = 0; + src->ypdata[src->num_yp_directories]->yp_url = + config_get_config()->yp_url[i]; + src->ypdata[src->num_yp_directories]->yp_url_timeout = + config_get_config()->yp_url_timeout[i]; + src->ypdata[src->num_yp_directories]->yp_touch_interval = 0; src->num_yp_directories++; } } @@ -136,17 +139,15 @@ void *source_main(void *arg) client_t *client; avl_node *client_node; char *s; - long currentTime = 0; - char current_song[256]; - char prev_current_song[256]; + long current_time; + char current_song[256]; refbuf_t *refbuf, *abuf; int data_done; int listeners = 0; - int listen_url_size = 0; int i=0; - int list_on_yp = 0; + int suppress_yp = 0; timeout = config_get_config()->source_timeout; @@ -169,8 +170,7 @@ void *source_main(void *arg) if (source->ypdata[i]->server_name) { free(source->ypdata[i]->server_name); } - source->ypdata[i]->server_name = (char *)malloc(strlen(s) +1); - memset(source->ypdata[i]->server_name, '\000', strlen(s) + 1); + source->ypdata[i]->server_name = malloc(strlen(s) +1); strcpy(source->ypdata[i]->server_name, s); } stats_event(source->mount, "name", s); @@ -180,8 +180,7 @@ void *source_main(void *arg) if (source->ypdata[i]->server_url) { free(source->ypdata[i]->server_url); } - source->ypdata[i]->server_url = (char *)malloc(strlen(s) +1); - memset(source->ypdata[i]->server_url, '\000', strlen(s) + 1); + source->ypdata[i]->server_url = malloc(strlen(s) +1); strcpy(source->ypdata[i]->server_url, s); } stats_event(source->mount, "url", s); @@ -191,8 +190,7 @@ void *source_main(void *arg) if (source->ypdata[i]->server_genre) { free(source->ypdata[i]->server_genre); } - source->ypdata[i]->server_genre = (char *)malloc(strlen(s) +1); - memset(source->ypdata[i]->server_genre, '\000', strlen(s) + 1); + source->ypdata[i]->server_genre = malloc(strlen(s) +1); strcpy(source->ypdata[i]->server_genre, s); } stats_event(source->mount, "genre", s); @@ -202,8 +200,7 @@ void *source_main(void *arg) if (source->ypdata[i]->bitrate) { free(source->ypdata[i]->bitrate); } - source->ypdata[i]->bitrate = (char *)malloc(strlen(s) +1); - memset(source->ypdata[i]->bitrate, '\000', strlen(s) + 1); + source->ypdata[i]->bitrate = malloc(strlen(s) +1); strcpy(source->ypdata[i]->bitrate, s); } stats_event(source->mount, "bitrate", s); @@ -213,78 +210,97 @@ void *source_main(void *arg) if (source->ypdata[i]->server_desc) { free(source->ypdata[i]->server_desc); } - source->ypdata[i]->server_desc = (char *)malloc(strlen(s) +1); - memset(source->ypdata[i]->server_desc, '\000', strlen(s) + 1); + source->ypdata[i]->server_desc = malloc(strlen(s) +1); strcpy(source->ypdata[i]->server_desc, s); } stats_event(source->mount, "description", s); } - if ((s = httpp_getvar(source->parser, "ice-public"))) { + if ((s = httpp_getvar(source->parser, "ice-private"))) { stats_event(source->mount, "public", s); - list_on_yp = atoi(s); + suppress_yp = atoi(s); } for (i=0;inum_yp_directories;i++) { if (source->ypdata[i]->server_type) { free(source->ypdata[i]->server_type); } - source->ypdata[i]->server_type = (char *)malloc(strlen(source->format->format_description) +1); - memset(source->ypdata[i]->server_type, '\000', strlen(source->format->format_description) + 1); - strcpy(source->ypdata[i]->server_type, source->format->format_description); + source->ypdata[i]->server_type = malloc( + strlen(source->format->format_description) + 1); + strcpy(source->ypdata[i]->server_type, + source->format->format_description); } stats_event(source->mount, "type", source->format->format_description); for (i=0;inum_yp_directories;i++) { + int listen_url_size; if (source->ypdata[i]->listen_url) { free(source->ypdata[i]->listen_url); } - // 6 for max size of port - listen_url_size = strlen("http://") + strlen(config_get_config()->hostname) + strlen(":") + 6 + strlen(source->mount) + 1; - source->ypdata[i]->listen_url = (char *)malloc(listen_url_size); - memset(source->ypdata[i]->listen_url, '\000', listen_url_size); - sprintf(source->ypdata[i]->listen_url, "http://%s:%d%s", config_get_config()->hostname, config_get_config()->port, source->mount); + /* 6 for max size of port */ + listen_url_size = strlen("http://") + + strlen(config_get_config()->hostname) + + strlen(":") + 6 + strlen(source->mount) + 1; + source->ypdata[i]->listen_url = malloc(listen_url_size); + sprintf(source->ypdata[i]->listen_url, "http://%s:%d%s", + config_get_config()->hostname, config_get_config()->port, + source->mount); } - if (list_on_yp) { - yp_add(source, YP_ADD_ALL); - } - time(¤tTime); - for (i=0;inum_yp_directories;i++) { - source->ypdata[i]->yp_last_touch = currentTime; - if (source->ypdata[i]->yp_touch_freq == 0) { - source->ypdata[i]->yp_touch_freq = 30; - } - } + if(!suppress_yp) { + yp_add(source, YP_ADD_ALL); - while (global.running == ICE_RUNNING) { - time(¤tTime); - if (list_on_yp) { + current_time = time(NULL); + + for (i=0;inum_yp_directories;i++) { + source->ypdata[i]->yp_last_touch = current_time; + /* Don't permit touch intervals of less than 30 seconds */ + if (source->ypdata[i]->yp_touch_interval <= 30) { + source->ypdata[i]->yp_touch_interval = 30; + } + } + } + + while (global.running == ICE_RUNNING && source->running) { + if(!suppress_yp) { + current_time = time(NULL); for (i=0;inum_yp_directories;i++) { - if (currentTime > (source->ypdata[i]->yp_last_touch + source->ypdata[i]->yp_touch_freq)) { - memset(current_song, '\000', sizeof(current_song)); + if (current_time > (source->ypdata[i]->yp_last_touch + + source->ypdata[i]->yp_touch_interval)) { + current_song[0] = 0; if (stats_get_value(source->mount, "artist")) { - strncat(current_song, stats_get_value(source->mount, "artist"), sizeof(current_song) - 1); + strncat(current_song, + stats_get_value(source->mount, "artist"), + sizeof(current_song) - 1); if (strlen(current_song) + 4 < sizeof(current_song)) { strncat(current_song, " - ", 3); } } if (stats_get_value(source->mount, "title")) { - if (strlen(current_song) + strlen(stats_get_value(source->mount, "title")) < sizeof(current_song) -1) { - strncat(current_song, stats_get_value(source->mount, "title"), sizeof(current_song) -1 - strlen(current_song)); + if (strlen(current_song) + + strlen(stats_get_value(source->mount, "title")) + < sizeof(current_song) -1) + { + strncat(current_song, + stats_get_value(source->mount, "title"), + sizeof(current_song) - 1 - + strlen(current_song)); } } + if (source->ypdata[i]->current_song) { free(source->ypdata[i]->current_song); source->ypdata[i]->current_song = NULL; } - source->ypdata[i]->current_song = (char *)malloc(strlen(current_song) + 1); - memset(source->ypdata[i]->current_song, '\000', strlen(current_song) + 1); + source->ypdata[i]->current_song = + malloc(strlen(current_song) + 1); strcpy(source->ypdata[i]->current_song, current_song); - thread_create("YP Touch Thread", yp_touch_thread, (void *)source, THREAD_DETACHED); + thread_create("YP Touch Thread", yp_touch_thread, + (void *)source, THREAD_DETACHED); } } } + ret = source->format->get_buffer(source->format, NULL, 0, &refbuf); if(ret < 0) { WARN0("Bad data from source"); @@ -486,7 +502,7 @@ void *source_main(void *arg) done: DEBUG0("Source exiting"); - if (list_on_yp) { + if(!suppress_yp) { yp_remove(source); } @@ -502,7 +518,7 @@ done: if(fallback_source) { avl_delete(source->pending_tree, client, _remove_client); - // TODO: reset client local format data? + /* TODO: reset client local format data? */ avl_tree_wlock(fallback_source->pending_tree); avl_insert(fallback_source->pending_tree, (void *)client); avl_tree_unlock(fallback_source->pending_tree); @@ -520,7 +536,7 @@ done: if(fallback_source) { avl_delete(source->client_tree, client, _remove_client); - // TODO: reset client local format data? + /* TODO: reset client local format data? */ avl_tree_wlock(fallback_source->pending_tree); avl_insert(fallback_source->pending_tree, (void *)client); avl_tree_unlock(fallback_source->pending_tree); @@ -580,3 +596,4 @@ static int _free_client(void *key) return 1; } + diff --git a/src/source.h b/src/source.h index 53b18fde..72474711 100644 --- a/src/source.h +++ b/src/source.h @@ -16,6 +16,10 @@ typedef struct source_tag /* If this source drops, try to move all clients to this fallback */ char *fallback_mount; + /* set to zero to request the source to shutdown without causing a global + * shutdown */ + int running; + struct _format_plugin_tag *format; avl_tree *client_tree; diff --git a/src/stats.c b/src/stats.c index b4b61436..a3fe7d84 100644 --- a/src/stats.c +++ b/src/stats.c @@ -126,13 +126,13 @@ void stats_shutdown() stats_t *stats_get_stats() { - // lock global stats + /* lock global stats - // copy stats + copy stats - // unlock global stats + unlock global stats - // return copied stats + return copied stats */ return NULL; } diff --git a/src/yp.c b/src/yp.c index bcf20a64..0447a6be 100644 --- a/src/yp.c +++ b/src/yp.c @@ -1,5 +1,6 @@ #include #include +#include #include @@ -20,11 +21,13 @@ int yp_submit_url(int curl_con, char *yp_url, char *url, char *type) curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_URL, yp_url); curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_POSTFIELDS, url); - curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_TIMEOUT, config_get_config()->yp_url_timeout); + curl_easy_setopt(curl_get_handle(curl_con), CURLOPT_TIMEOUT, + config_get_config()->yp_url_timeout); /* get it! */ - memset(curl_get_result(curl_con), '\000', sizeof(struct curl_memory_struct)); - memset(curl_get_header_result(curl_con), '\000', sizeof(struct curl_memory_struct2)); + memset(curl_get_result(curl_con), 0, sizeof(struct curl_memory_struct)); + memset(curl_get_header_result(curl_con), 0, + sizeof(struct curl_memory_struct2)); curl_easy_perform(curl_get_handle(curl_con)); @@ -36,7 +39,8 @@ int yp_submit_url(int curl_con, char *yp_url, char *url, char *type) } else { if (strlen(curl_get_header_result(curl_con)->message) > 0) { - ERROR3("Got a NAK from %s(%s) (%s)", type,curl_get_header_result(curl_con)->message, yp_url); + ERROR3("Got a NAK from %s(%s) (%s)", type, + curl_get_header_result(curl_con)->message, yp_url); } else { ERROR2("Got a NAK from %s(Unknown) (%s)", type, yp_url); @@ -52,18 +56,16 @@ void *yp_touch_thread(void *arg) thread_exit(0); return NULL; } -int yp_remove(void *psource) + +int yp_remove(source_t *source) { char *url = NULL; int url_size = 0; int ret = 0; int curl_con = 0; - char *p1 = NULL; int i = 0; - int regen_sid = 0; long current_time = 0; - source_t *source = (source_t *)psource; current_time = time(¤t_time); @@ -81,17 +83,17 @@ int yp_remove(void *psource) url_size = strlen("action=remove&sid=") + 1; url_size += strlen(source->ypdata[i]->sid); url_size += 1024; - url = (char *)malloc(url_size); - memset(url, '\000', url_size); + url = malloc(url_size); sprintf(url, "action=remove&sid=%s", - source->ypdata[i]->sid); + source->ypdata[i]->sid); curl_con = curl_get_connection(); if (curl_con < 0) { ERROR0("Unable to get auth connection"); } else { - /* specify URL to get */ - ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, url, "yp_remove"); + /* specify URL to get */ + ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, + url, "yp_remove"); } if (url) { free(url); @@ -101,19 +103,17 @@ int yp_remove(void *psource) } return 1; } -int yp_touch(void *psource) +int yp_touch(source_t *source) { char *url = NULL; int url_size = 0; int ret = 0; int curl_con = 0; - char *p1 = NULL; int i = 0; int regen_sid = 0; long current_time = 0; - source_t *source = (source_t *)psource; - current_time = time(¤t_time); + current_time = time(NULL); for (i=0; inum_yp_directories; i++) { source->ypdata[i]->yp_last_touch = current_time; if (source->ypdata[i]->sid == 0) { @@ -136,32 +136,32 @@ int yp_touch(void *psource) } else { source->ypdata[i]->current_song = (char *)malloc(1); - memset(source->ypdata[i]->current_song, '\000', 1); + source->ypdata[i]->current_song[0] = 0; } if (source->ypdata[i]->sid) { url_size += strlen(source->ypdata[i]->sid); } else { source->ypdata[i]->sid = (char *)malloc(1); - memset(source->ypdata[i]->sid, '\000', 1); + source->ypdata[i]->sid[0] = 0; } url_size += 1024; - url = (char *)malloc(url_size); - memset(url, '\000', url_size); - sprintf(url, "action=touch&sid=%s&st=%s&listeners=%d", - source->ypdata[i]->sid, - source->ypdata[i]->current_song, - source->listeners); + url = malloc(url_size); + sprintf(url, "action=touch&sid=%s&st=%s&listeners=%ld", + source->ypdata[i]->sid, + source->ypdata[i]->current_song, + source->listeners); curl_con = curl_get_connection(); if (curl_con < 0) { ERROR0("Unable to get auth connection"); } else { - /* specify URL to get */ - ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, url, "yp_touch"); + /* specify URL to get */ + ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, + url, "yp_touch"); if (!ret) { - source->ypdata[i]->sid[0] = '\000'; + source->ypdata[i]->sid[0] = 0; } } if (url) { @@ -172,16 +172,14 @@ int yp_touch(void *psource) } return 1; } -int yp_add(void *psource, int which) +int yp_add(source_t *source, int which) { char *url = NULL; int url_size = 0; int ret = 0; int curl_con = 0; - char *p1 = NULL; int i = 0; int ok = 0; - source_t *source = (source_t *)psource; for (i=0; inum_yp_directories; i++) { if (which != -1) { @@ -198,82 +196,83 @@ int yp_add(void *psource, int which) if (ok) { if (source->ypdata[i]) { - url_size = strlen("action=add&sn=&genre=&cpswd=&desc=&url=&listenurl=&type=&b=") + 1; + url_size = strlen("action=add&sn=&genre=&cpswd=&desc=&url=" + "&listenurl=&type=&b=") + 1; if (source->ypdata[i]->server_name) { url_size += strlen(source->ypdata[i]->server_name); } else { source->ypdata[i]->server_name = (char *)malloc(1); - memset(source->ypdata[i]->server_name, '\000', 1); + source->ypdata[i]->server_name[0] = 0; } if (source->ypdata[i]->server_desc) { url_size += strlen(source->ypdata[i]->server_desc); } else { source->ypdata[i]->server_desc = (char *)malloc(1); - memset(source->ypdata[i]->server_desc, '\000', 1); + source->ypdata[i]->server_desc[0] = 0; } if (source->ypdata[i]->server_genre) { url_size += strlen(source->ypdata[i]->server_genre); } else { source->ypdata[i]->server_genre = (char *)malloc(1); - memset(source->ypdata[i]->server_genre, '\000', 1); + source->ypdata[i]->server_genre[0] = 0; } if (source->ypdata[i]->cluster_password) { url_size += strlen(source->ypdata[i]->cluster_password); } else { source->ypdata[i]->cluster_password = (char *)malloc(1); - memset(source->ypdata[i]->cluster_password, '\000', 1); + source->ypdata[i]->cluster_password[0] = 0; } if (source->ypdata[i]->server_url) { url_size += strlen(source->ypdata[i]->server_url); } else { source->ypdata[i]->server_url = (char *)malloc(1); - memset(source->ypdata[i]->server_url, '\000', 1); + source->ypdata[i]->server_url[0] = 0; } if (source->ypdata[i]->listen_url) { url_size += strlen(source->ypdata[i]->listen_url); } else { source->ypdata[i]->listen_url = (char *)malloc(1); - memset(source->ypdata[i]->listen_url, '\000', 1); + source->ypdata[i]->listen_url[0] = 0; } if (source->ypdata[i]->server_type) { url_size += strlen(source->ypdata[i]->server_type); } else { source->ypdata[i]->server_type = (char *)malloc(1); - memset(source->ypdata[i]->server_type, '\000', 1); + source->ypdata[i]->server_type[0] = 0; } if (source->ypdata[i]->bitrate) { url_size += strlen(source->ypdata[i]->bitrate); } else { source->ypdata[i]->bitrate = (char *)malloc(1); - memset(source->ypdata[i]->bitrate, '\000', 1); + source->ypdata[i]->bitrate[0] = 0; } if (source->ypdata[i]->current_song) { url_size += strlen(source->ypdata[i]->current_song); } else { source->ypdata[i]->current_song = (char *)malloc(1); - memset(source->ypdata[i]->current_song, '\000', 1); + source->ypdata[i]->current_song[0] = 0; } url_size += 1024; - url = (char *)malloc(url_size); - memset(url, '\000', url_size); - sprintf(url, "action=add&sn=%s&genre=%s&cpswd=%s&desc=%s&url=%s&listenurl=%s&type=%s&b=%s", - source->ypdata[i]->server_name, - source->ypdata[i]->server_genre, - source->ypdata[i]->cluster_password, - source->ypdata[i]->server_desc, - source->ypdata[i]->server_url, - source->ypdata[i]->listen_url, - source->ypdata[i]->server_type, - source->ypdata[i]->bitrate); + url = malloc(url_size); + sprintf(url, "action=add&sn=%s&genre=%s&cpswd=%s&desc=%s&url=%s" + "&listenurl=%s&type=%s&b=%s", + source->ypdata[i]->server_name, + source->ypdata[i]->server_genre, + source->ypdata[i]->cluster_password, + source->ypdata[i]->server_desc, + source->ypdata[i]->server_url, + source->ypdata[i]->listen_url, + source->ypdata[i]->server_type, + source->ypdata[i]->bitrate); curl_con = curl_get_connection(); if (curl_con < 0) { @@ -281,7 +280,8 @@ int yp_add(void *psource, int which) } else { /* specify URL to get */ - ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, url, "yp_add"); + ret = yp_submit_url(curl_con, source->ypdata[i]->yp_url, + url, "yp_add"); if (ret) { if (strlen(curl_get_header_result(curl_con)->sid) > 0) { @@ -290,10 +290,14 @@ int yp_add(void *psource, int which) free(source->ypdata[i]->sid); source->ypdata[i]->sid = NULL; } - source->ypdata[i]->sid = (char *)malloc(strlen(curl_get_header_result(curl_con)->sid) +1); - memset(source->ypdata[i]->sid, '\000', strlen(curl_get_header_result(curl_con)->sid) +1); - strcpy(source->ypdata[i]->sid, curl_get_header_result(curl_con)->sid); - source->ypdata[i]->yp_touch_freq = curl_get_header_result(curl_con)->touch_freq; + source->ypdata[i]->sid = (char *)malloc( + strlen(curl_get_header_result(curl_con)-> + sid) +1); + strcpy(source->ypdata[i]->sid, + curl_get_header_result(curl_con)->sid); + source->ypdata[i]->yp_touch_interval = + curl_get_header_result( + curl_con)->touch_interval; } } } @@ -310,12 +314,9 @@ int yp_add(void *psource, int which) ypdata_t *yp_create_ypdata() { - ypdata_t *tmp; - - tmp = (ypdata_t *)malloc(sizeof(ypdata_t)); - memset(tmp, '\000', sizeof(ypdata_t)); - return(tmp); + return calloc(1, sizeof(ypdata_t)); } + void yp_destroy_ypdata(ypdata_t *ypdata) { if (ypdata) { @@ -352,3 +353,4 @@ void yp_destroy_ypdata(ypdata_t *ypdata) free(ypdata); } } + diff --git a/src/yp.h b/src/yp.h index 4d2b151b..1e314eaa 100644 --- a/src/yp.h +++ b/src/yp.h @@ -2,29 +2,32 @@ #define __YP_H__ #include + +struct source_tag; + #define YP_ADD_ALL -1 typedef struct ypdata_tag { - char *sid; - char *server_name; - char *server_desc; - char *server_genre; - char *cluster_password; - char *server_url; - char *listen_url; - char *bitrate; - char *server_type; - char *current_song; - char *yp_url; + char *sid; + char *server_name; + char *server_desc; + char *server_genre; + char *cluster_password; + char *server_url; + char *listen_url; + char *bitrate; + char *server_type; + char *current_song; + char *yp_url; int yp_url_timeout; - long yp_last_touch; - int yp_touch_freq; + long yp_last_touch; + int yp_touch_interval; } ypdata_t; void *yp_touch_thread(void *arg); -int yp_add(void *psource, int which); -int yp_touch(void *psource); -int yp_remove(void *psource); +int yp_add(struct source_tag *source, int which); +int yp_touch(struct source_tag *source); +int yp_remove(struct source_tag *psource); ypdata_t *yp_create_ypdata(); void yp_destroy_ypdata(ypdata_t *ypdata);