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);