1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-23 06:25:24 +00:00

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
<authentication>, (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
This commit is contained in:
Michael Smith 2003-02-06 13:10:48 +00:00
parent ffb1f3bc7e
commit 9e168dc870
16 changed files with 328 additions and 199 deletions

22
TODO
View File

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

View File

@ -11,12 +11,23 @@
<source-timeout>10</source-timeout>
</limits>
<source-password>hackme</source-password>
<relay-password>hackme</relay-password>
<authentication>
<!-- Sources log in with username 'source' -->
<source-password>hackme</source-password>
<!-- Relays log in username 'relay' -->
<relay-password>hackme</relay-password>
<directory>
<yp-url>http://www.oddsock.org/cgi-bin/yp-cgi</yp-url>
</directory>
<!-- Admin logs in with the username given below -->
<admin-user>admin</admin-user>
<admin-password>hackme</admin-password>
</authentication>
<!-- Uncomment this if you want directory listings -->
<!--
<directory>
<yp-url>http://www.oddsock.org/cgi-bin/yp-cgi</yp-url>
</directory>
-->
<hostname>localhost</hostname>
<port>8000</port>
@ -30,15 +41,15 @@
<fileserve>1</fileserve>
<paths>
<basedir>/usr/local/icecast2</basedir>
<logdir>/usr/local/icecast2/logs</logdir>
<webroot>/usr/local/icecast2/web</webroot>
<basedir>/usr/local/icecast</basedir>
<logdir>/usr/local/icecast/logs</logdir>
<webroot>/usr/local/icecast/web</webroot>
</paths>
<logging>
<accesslog>access.log</accesslog>
<errorlog>error.log</errorlog>
<loglevel>4</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
<loglevel>4</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
</logging>
<security>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <thread/thread.h>
@ -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<NUM_CONNECTIONS; i++) {
curl_connections[i].curl_handle = curl_easy_init();
curl_easy_setopt(curl_connections[i].curl_handle,
CURLOPT_WRITEFUNCTION, curl_write_memory_callback);
curl_easy_setopt(curl_connections[i].curl_handle,
CURLOPT_WRITEHEADER, (void *)&(curl_connections[i].header_result));
CURLOPT_WRITEHEADER,
(void *)&(curl_connections[i].header_result));
curl_easy_setopt(curl_connections[i].curl_handle,
CURLOPT_HEADERFUNCTION, curl_header_memory_callback);
curl_easy_setopt(curl_connections[i].curl_handle,
@ -114,7 +115,7 @@ void curl_shutdown()
int i = 0;
for (i=0; i<NUM_CONNECTIONS; i++) {
curl_easy_cleanup(curl_connections[i].curl_handle);
memset(&(curl_connections[i]), '\000', sizeof(curl_connections[i]));
memset(&(curl_connections[i]), 0, sizeof(curl_connections[i]));
}
}
int curl_get_connection()
@ -145,9 +146,9 @@ int curl_release_connection(int which)
{
thread_mutex_lock(&_curl_mutex);
curl_connections[which].in_use = 0;
memset(&(curl_connections[which].result), '\000',
memset(&(curl_connections[which].result), 0,
sizeof(curl_connections[which].result));
memset(&(curl_connections[which].header_result), '\000',
memset(&(curl_connections[which].header_result), 0,
sizeof(curl_connections[which].header_result));
thread_mutex_unlock(&_curl_mutex);
return 1;
@ -155,7 +156,7 @@ int curl_release_connection(int which)
void curl_print_header_result(struct curl_memory_struct2 *mem) {
DEBUG1("SID -> (%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);
}

View File

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

View File

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

View File

@ -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 */

View File

@ -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;i<config_get_config()->num_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;i<source->num_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;i<source->num_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(&currentTime);
for (i=0;i<source->num_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(&currentTime);
if (list_on_yp) {
current_time = time(NULL);
for (i=0;i<source->num_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;i<source->num_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;
}

View File

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

View File

@ -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;
}

126
src/yp.c
View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <thread/thread.h>
@ -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(&current_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(&current_time);
current_time = time(NULL);
for (i=0; i<source->num_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; i<source->num_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);
}
}

View File

@ -2,29 +2,32 @@
#define __YP_H__
#include <stdio.h>
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);