mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
fixed master-slave relaying...
* slaves now ask for /admin/streamlist.txt which serves a plaintext version of the source list (this is what it was expecting to get) * /admin/streamlist still serves XML (which slave.c wasn't expecting) * fixed a few cases of pointer invalidation due to possible config re-reading. * slave relay now uses relay password to get the list of streams to relay svn path=/trunk/icecast/; revision=5695
This commit is contained in:
parent
bb96da291a
commit
e8a61ce5d3
58
src/admin.c
58
src/admin.c
@ -47,6 +47,7 @@
|
||||
#define COMMAND_RAW_LIST_MOUNTS 101
|
||||
#define COMMAND_RAW_STATS 102
|
||||
#define COMMAND_RAW_LISTSTREAM 103
|
||||
#define COMMAND_PLAINTEXT_LISTSTREAM 104
|
||||
#define COMMAND_TRANSFORMED_LIST_MOUNTS 201
|
||||
#define COMMAND_TRANSFORMED_STATS 202
|
||||
#define COMMAND_TRANSFORMED_LISTSTREAM 203
|
||||
@ -68,6 +69,7 @@
|
||||
#define LISTMOUNTS_TRANSFORMED_REQUEST "listmounts.xsl"
|
||||
#define STREAMLIST_RAW_REQUEST "streamlist"
|
||||
#define STREAMLIST_TRANSFORMED_REQUEST "streamlist.xsl"
|
||||
#define STREAMLIST_PLAINTEXT_REQUEST "streamlist.txt"
|
||||
#define MOVECLIENTS_RAW_REQUEST "moveclients"
|
||||
#define MOVECLIENTS_TRANSFORMED_REQUEST "moveclients.xsl"
|
||||
#define KILLCLIENT_RAW_REQUEST "killclient"
|
||||
@ -80,6 +82,7 @@
|
||||
|
||||
#define RAW 1
|
||||
#define TRANSFORMED 2
|
||||
#define PLAINTEXT 3
|
||||
int admin_get_command(char *command)
|
||||
{
|
||||
if(!strcmp(command, FALLBACK_RAW_REQUEST))
|
||||
@ -104,6 +107,8 @@ int admin_get_command(char *command)
|
||||
return COMMAND_TRANSFORMED_LIST_MOUNTS;
|
||||
else if(!strcmp(command, STREAMLIST_RAW_REQUEST))
|
||||
return COMMAND_RAW_LISTSTREAM;
|
||||
else if(!strcmp(command, STREAMLIST_PLAINTEXT_REQUEST))
|
||||
return COMMAND_PLAINTEXT_LISTSTREAM;
|
||||
else if(!strcmp(command, MOVECLIENTS_RAW_REQUEST))
|
||||
return COMMAND_RAW_MOVE_CLIENTS;
|
||||
else if(!strcmp(command, MOVECLIENTS_TRANSFORMED_REQUEST))
|
||||
@ -281,11 +286,24 @@ void admin_handle_request(client_t *client, char *uri)
|
||||
}
|
||||
else {
|
||||
|
||||
if(!connection_check_admin_pass(client->parser)) {
|
||||
INFO1("Bad or missing password on admin command "
|
||||
"request (command: %s)", command_string);
|
||||
client_send_401(client);
|
||||
return;
|
||||
if (command == COMMAND_PLAINTEXT_LISTSTREAM) {
|
||||
/* this request is used by a slave relay to retrieve
|
||||
mounts from the master, so handle this request
|
||||
validating against the relay password */
|
||||
if(!connection_check_relay_pass(client->parser)) {
|
||||
INFO1("Bad or missing password on admin command "
|
||||
"request (command: %s)", command_string);
|
||||
client_send_401(client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!connection_check_admin_pass(client->parser)) {
|
||||
INFO1("Bad or missing password on admin command "
|
||||
"request (command: %s)", command_string);
|
||||
client_send_401(client);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
admin_handle_general_request(client, command);
|
||||
@ -304,6 +322,9 @@ static void admin_handle_general_request(client_t *client, int command)
|
||||
case COMMAND_RAW_LISTSTREAM:
|
||||
command_list_mounts(client, RAW);
|
||||
break;
|
||||
case COMMAND_PLAINTEXT_LISTSTREAM:
|
||||
command_list_mounts(client, PLAINTEXT);
|
||||
break;
|
||||
case COMMAND_TRANSFORMED_STATS:
|
||||
command_stats(client, TRANSFORMED);
|
||||
break;
|
||||
@ -668,14 +689,35 @@ static void command_stats(client_t *client, int response) {
|
||||
|
||||
static void command_list_mounts(client_t *client, int response) {
|
||||
xmlDocPtr doc;
|
||||
avl_node *node;
|
||||
source_t *source;
|
||||
|
||||
DEBUG0("List mounts request");
|
||||
|
||||
doc = admin_build_sourcelist(NULL);
|
||||
|
||||
admin_send_response(doc, client, response, LISTMOUNTS_TRANSFORMED_REQUEST);
|
||||
xmlFreeDoc(doc);
|
||||
if (response == PLAINTEXT) {
|
||||
avl_tree_rlock(global.source_tree);
|
||||
|
||||
node = avl_get_first(global.source_tree);
|
||||
html_write(client,
|
||||
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
|
||||
while(node) {
|
||||
source = (source_t *)node->key;
|
||||
html_write(client, "%s\n", source->mount);
|
||||
node = avl_get_next(node);
|
||||
}
|
||||
avl_tree_unlock(global.source_tree);
|
||||
}
|
||||
else {
|
||||
|
||||
doc = admin_build_sourcelist(NULL);
|
||||
|
||||
admin_send_response(doc, client, response,
|
||||
LISTMOUNTS_TRANSFORMED_REQUEST);
|
||||
xmlFreeDoc(doc);
|
||||
}
|
||||
client_destroy(client);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -120,6 +120,10 @@ void config_clear(ice_config_t *c)
|
||||
xmlFree(c->admin_username);
|
||||
if (c->admin_password)
|
||||
xmlFree(c->admin_password);
|
||||
if (c->relay_username)
|
||||
xmlFree(c->relay_username);
|
||||
if (c->relay_password)
|
||||
xmlFree(c->relay_password);
|
||||
if (c->hostname && c->hostname != CONFIG_DEFAULT_HOSTNAME)
|
||||
xmlFree(c->hostname);
|
||||
if (c->base_dir && c->base_dir != CONFIG_DEFAULT_BASE_DIR)
|
||||
@ -302,6 +306,8 @@ static void _set_defaults(ice_config_t *configuration)
|
||||
configuration->user = CONFIG_DEFAULT_USER;
|
||||
configuration->group = CONFIG_DEFAULT_GROUP;
|
||||
configuration->num_yp_directories = 0;
|
||||
configuration->relay_username = NULL;
|
||||
configuration->relay_password = NULL;
|
||||
}
|
||||
|
||||
static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
||||
@ -593,6 +599,16 @@ static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
|
||||
xmlFree(configuration->admin_username);
|
||||
configuration->admin_username =
|
||||
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
} else if (strcmp(node->name, "relay-password") == 0) {
|
||||
if(configuration->relay_password)
|
||||
xmlFree(configuration->relay_password);
|
||||
configuration->relay_password =
|
||||
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
} else if (strcmp(node->name, "relay-user") == 0) {
|
||||
if(configuration->relay_username)
|
||||
xmlFree(configuration->relay_username);
|
||||
configuration->relay_username =
|
||||
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
||||
}
|
||||
} while ((node = node->next));
|
||||
}
|
||||
|
@ -76,6 +76,8 @@ typedef struct ice_config_tag
|
||||
char *source_password;
|
||||
char *admin_username;
|
||||
char *admin_password;
|
||||
char *relay_username;
|
||||
char *relay_password;
|
||||
|
||||
int touch_interval;
|
||||
ice_config_dir_t *dir_list;
|
||||
|
@ -557,15 +557,35 @@ static int _check_pass_ice(http_parser_t *parser, char *correctpass)
|
||||
|
||||
int connection_check_admin_pass(http_parser_t *parser)
|
||||
{
|
||||
int ret;
|
||||
ice_config_t *config = config_get_config();
|
||||
char *pass = config->admin_password;
|
||||
char *user = config->admin_username;
|
||||
config_release_config();
|
||||
|
||||
if(!pass || !user)
|
||||
if(!pass || !user) {
|
||||
config_release_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _check_pass_http(parser, user, pass);
|
||||
ret = _check_pass_http(parser, user, pass);
|
||||
config_release_config();
|
||||
return ret;
|
||||
}
|
||||
int connection_check_relay_pass(http_parser_t *parser)
|
||||
{
|
||||
int ret;
|
||||
ice_config_t *config = config_get_config();
|
||||
char *pass = config->relay_password;
|
||||
char *user = "relay";
|
||||
|
||||
if(!pass || !user) {
|
||||
config_release_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = _check_pass_http(parser, user, pass);
|
||||
config_release_config();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int connection_check_source_pass(http_parser_t *parser, char *mount)
|
||||
@ -579,7 +599,6 @@ int connection_check_source_pass(http_parser_t *parser, char *mount)
|
||||
|
||||
mount_proxy *mountinfo = config->mounts;
|
||||
thread_mutex_lock(&(config_locks()->mounts_lock));
|
||||
config_release_config();
|
||||
|
||||
while(mountinfo) {
|
||||
if(!strcmp(mountinfo->mountname, mount)) {
|
||||
@ -596,6 +615,7 @@ int connection_check_source_pass(http_parser_t *parser, char *mount)
|
||||
|
||||
if(!pass) {
|
||||
WARN0("No source password set, rejecting source");
|
||||
config_release_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -612,6 +632,7 @@ int connection_check_source_pass(http_parser_t *parser, char *mount)
|
||||
WARN0("Source is using deprecated icecast login");
|
||||
}
|
||||
}
|
||||
config_release_config();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
28
src/slave.c
28
src/slave.c
@ -95,22 +95,16 @@ static void create_relay_stream(char *server, int port,
|
||||
return;
|
||||
}
|
||||
con = create_connection(streamsock, -1, NULL);
|
||||
if(mp3) {
|
||||
/* Some mp3 servers are bitchy, send a user-agent string to make them
|
||||
* send the right response.
|
||||
*/
|
||||
sock_write(streamsock, "GET %s HTTP/1.0\r\n"
|
||||
"User-Agent: " ICECAST_VERSION_STRING "\r\n"
|
||||
"Icy-MetaData: 1\r\n"
|
||||
"\r\n",
|
||||
remotemount);
|
||||
}
|
||||
else {
|
||||
sock_write(streamsock, "GET %s HTTP/1.0\r\n"
|
||||
"User-Agent: " ICECAST_VERSION_STRING "\r\n"
|
||||
"\r\n",
|
||||
remotemount);
|
||||
}
|
||||
/* At this point we may not know if we are relaying a mp3 or vorbis stream,
|
||||
* so lets send in the icy-metadata header just in case, it's harmless in
|
||||
* the vorbis case. If we don't send in this header then relay will not
|
||||
* have mp3 metadata.
|
||||
*/
|
||||
sock_write(streamsock, "GET %s HTTP/1.0\r\n"
|
||||
"User-Agent: " ICECAST_VERSION_STRING "\r\n"
|
||||
"Icy-MetaData: 1\r\n"
|
||||
"\r\n",
|
||||
remotemount);
|
||||
memset(header, 0, sizeof(header));
|
||||
if (util_read_header(con->sock, header, 4096) == 0) {
|
||||
WARN0("Header read failed");
|
||||
@ -198,7 +192,7 @@ static void *_slave_thread(void *arg) {
|
||||
strcat(authheader, password);
|
||||
data = util_base64_encode(authheader);
|
||||
sock_write(mastersock,
|
||||
"GET /admin/streamlist HTTP/1.0\r\n"
|
||||
"GET /admin/streamlist.txt HTTP/1.0\r\n"
|
||||
"Authorization: Basic %s\r\n"
|
||||
"\r\n", data);
|
||||
free(authheader);
|
||||
|
Loading…
Reference in New Issue
Block a user