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_LIST_MOUNTS 101
|
||||||
#define COMMAND_RAW_STATS 102
|
#define COMMAND_RAW_STATS 102
|
||||||
#define COMMAND_RAW_LISTSTREAM 103
|
#define COMMAND_RAW_LISTSTREAM 103
|
||||||
|
#define COMMAND_PLAINTEXT_LISTSTREAM 104
|
||||||
#define COMMAND_TRANSFORMED_LIST_MOUNTS 201
|
#define COMMAND_TRANSFORMED_LIST_MOUNTS 201
|
||||||
#define COMMAND_TRANSFORMED_STATS 202
|
#define COMMAND_TRANSFORMED_STATS 202
|
||||||
#define COMMAND_TRANSFORMED_LISTSTREAM 203
|
#define COMMAND_TRANSFORMED_LISTSTREAM 203
|
||||||
@ -68,6 +69,7 @@
|
|||||||
#define LISTMOUNTS_TRANSFORMED_REQUEST "listmounts.xsl"
|
#define LISTMOUNTS_TRANSFORMED_REQUEST "listmounts.xsl"
|
||||||
#define STREAMLIST_RAW_REQUEST "streamlist"
|
#define STREAMLIST_RAW_REQUEST "streamlist"
|
||||||
#define STREAMLIST_TRANSFORMED_REQUEST "streamlist.xsl"
|
#define STREAMLIST_TRANSFORMED_REQUEST "streamlist.xsl"
|
||||||
|
#define STREAMLIST_PLAINTEXT_REQUEST "streamlist.txt"
|
||||||
#define MOVECLIENTS_RAW_REQUEST "moveclients"
|
#define MOVECLIENTS_RAW_REQUEST "moveclients"
|
||||||
#define MOVECLIENTS_TRANSFORMED_REQUEST "moveclients.xsl"
|
#define MOVECLIENTS_TRANSFORMED_REQUEST "moveclients.xsl"
|
||||||
#define KILLCLIENT_RAW_REQUEST "killclient"
|
#define KILLCLIENT_RAW_REQUEST "killclient"
|
||||||
@ -80,6 +82,7 @@
|
|||||||
|
|
||||||
#define RAW 1
|
#define RAW 1
|
||||||
#define TRANSFORMED 2
|
#define TRANSFORMED 2
|
||||||
|
#define PLAINTEXT 3
|
||||||
int admin_get_command(char *command)
|
int admin_get_command(char *command)
|
||||||
{
|
{
|
||||||
if(!strcmp(command, FALLBACK_RAW_REQUEST))
|
if(!strcmp(command, FALLBACK_RAW_REQUEST))
|
||||||
@ -104,6 +107,8 @@ int admin_get_command(char *command)
|
|||||||
return COMMAND_TRANSFORMED_LIST_MOUNTS;
|
return COMMAND_TRANSFORMED_LIST_MOUNTS;
|
||||||
else if(!strcmp(command, STREAMLIST_RAW_REQUEST))
|
else if(!strcmp(command, STREAMLIST_RAW_REQUEST))
|
||||||
return COMMAND_RAW_LISTSTREAM;
|
return COMMAND_RAW_LISTSTREAM;
|
||||||
|
else if(!strcmp(command, STREAMLIST_PLAINTEXT_REQUEST))
|
||||||
|
return COMMAND_PLAINTEXT_LISTSTREAM;
|
||||||
else if(!strcmp(command, MOVECLIENTS_RAW_REQUEST))
|
else if(!strcmp(command, MOVECLIENTS_RAW_REQUEST))
|
||||||
return COMMAND_RAW_MOVE_CLIENTS;
|
return COMMAND_RAW_MOVE_CLIENTS;
|
||||||
else if(!strcmp(command, MOVECLIENTS_TRANSFORMED_REQUEST))
|
else if(!strcmp(command, MOVECLIENTS_TRANSFORMED_REQUEST))
|
||||||
@ -281,11 +286,24 @@ void admin_handle_request(client_t *client, char *uri)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if(!connection_check_admin_pass(client->parser)) {
|
if (command == COMMAND_PLAINTEXT_LISTSTREAM) {
|
||||||
INFO1("Bad or missing password on admin command "
|
/* this request is used by a slave relay to retrieve
|
||||||
"request (command: %s)", command_string);
|
mounts from the master, so handle this request
|
||||||
client_send_401(client);
|
validating against the relay password */
|
||||||
return;
|
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);
|
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:
|
case COMMAND_RAW_LISTSTREAM:
|
||||||
command_list_mounts(client, RAW);
|
command_list_mounts(client, RAW);
|
||||||
break;
|
break;
|
||||||
|
case COMMAND_PLAINTEXT_LISTSTREAM:
|
||||||
|
command_list_mounts(client, PLAINTEXT);
|
||||||
|
break;
|
||||||
case COMMAND_TRANSFORMED_STATS:
|
case COMMAND_TRANSFORMED_STATS:
|
||||||
command_stats(client, TRANSFORMED);
|
command_stats(client, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
@ -668,14 +689,35 @@ static void command_stats(client_t *client, int response) {
|
|||||||
|
|
||||||
static void command_list_mounts(client_t *client, int response) {
|
static void command_list_mounts(client_t *client, int response) {
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
|
avl_node *node;
|
||||||
|
source_t *source;
|
||||||
|
|
||||||
DEBUG0("List mounts request");
|
DEBUG0("List mounts request");
|
||||||
|
|
||||||
doc = admin_build_sourcelist(NULL);
|
|
||||||
|
|
||||||
admin_send_response(doc, client, response, LISTMOUNTS_TRANSFORMED_REQUEST);
|
if (response == PLAINTEXT) {
|
||||||
xmlFreeDoc(doc);
|
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);
|
client_destroy(client);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +120,10 @@ void config_clear(ice_config_t *c)
|
|||||||
xmlFree(c->admin_username);
|
xmlFree(c->admin_username);
|
||||||
if (c->admin_password)
|
if (c->admin_password)
|
||||||
xmlFree(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)
|
if (c->hostname && c->hostname != CONFIG_DEFAULT_HOSTNAME)
|
||||||
xmlFree(c->hostname);
|
xmlFree(c->hostname);
|
||||||
if (c->base_dir && c->base_dir != CONFIG_DEFAULT_BASE_DIR)
|
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->user = CONFIG_DEFAULT_USER;
|
||||||
configuration->group = CONFIG_DEFAULT_GROUP;
|
configuration->group = CONFIG_DEFAULT_GROUP;
|
||||||
configuration->num_yp_directories = 0;
|
configuration->num_yp_directories = 0;
|
||||||
|
configuration->relay_username = NULL;
|
||||||
|
configuration->relay_password = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
|
||||||
@ -593,6 +599,16 @@ static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
|
|||||||
xmlFree(configuration->admin_username);
|
xmlFree(configuration->admin_username);
|
||||||
configuration->admin_username =
|
configuration->admin_username =
|
||||||
(char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
|
(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));
|
} while ((node = node->next));
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,8 @@ typedef struct ice_config_tag
|
|||||||
char *source_password;
|
char *source_password;
|
||||||
char *admin_username;
|
char *admin_username;
|
||||||
char *admin_password;
|
char *admin_password;
|
||||||
|
char *relay_username;
|
||||||
|
char *relay_password;
|
||||||
|
|
||||||
int touch_interval;
|
int touch_interval;
|
||||||
ice_config_dir_t *dir_list;
|
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 connection_check_admin_pass(http_parser_t *parser)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
ice_config_t *config = config_get_config();
|
ice_config_t *config = config_get_config();
|
||||||
char *pass = config->admin_password;
|
char *pass = config->admin_password;
|
||||||
char *user = config->admin_username;
|
char *user = config->admin_username;
|
||||||
config_release_config();
|
|
||||||
|
|
||||||
if(!pass || !user)
|
if(!pass || !user) {
|
||||||
|
config_release_config();
|
||||||
return 0;
|
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)
|
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;
|
mount_proxy *mountinfo = config->mounts;
|
||||||
thread_mutex_lock(&(config_locks()->mounts_lock));
|
thread_mutex_lock(&(config_locks()->mounts_lock));
|
||||||
config_release_config();
|
|
||||||
|
|
||||||
while(mountinfo) {
|
while(mountinfo) {
|
||||||
if(!strcmp(mountinfo->mountname, mount)) {
|
if(!strcmp(mountinfo->mountname, mount)) {
|
||||||
@ -596,6 +615,7 @@ int connection_check_source_pass(http_parser_t *parser, char *mount)
|
|||||||
|
|
||||||
if(!pass) {
|
if(!pass) {
|
||||||
WARN0("No source password set, rejecting source");
|
WARN0("No source password set, rejecting source");
|
||||||
|
config_release_config();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,6 +632,7 @@ int connection_check_source_pass(http_parser_t *parser, char *mount)
|
|||||||
WARN0("Source is using deprecated icecast login");
|
WARN0("Source is using deprecated icecast login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
config_release_config();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
src/slave.c
28
src/slave.c
@ -95,22 +95,16 @@ static void create_relay_stream(char *server, int port,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
con = create_connection(streamsock, -1, NULL);
|
con = create_connection(streamsock, -1, NULL);
|
||||||
if(mp3) {
|
/* At this point we may not know if we are relaying a mp3 or vorbis stream,
|
||||||
/* Some mp3 servers are bitchy, send a user-agent string to make them
|
* so lets send in the icy-metadata header just in case, it's harmless in
|
||||||
* send the right response.
|
* 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"
|
sock_write(streamsock, "GET %s HTTP/1.0\r\n"
|
||||||
"Icy-MetaData: 1\r\n"
|
"User-Agent: " ICECAST_VERSION_STRING "\r\n"
|
||||||
"\r\n",
|
"Icy-MetaData: 1\r\n"
|
||||||
remotemount);
|
"\r\n",
|
||||||
}
|
remotemount);
|
||||||
else {
|
|
||||||
sock_write(streamsock, "GET %s HTTP/1.0\r\n"
|
|
||||||
"User-Agent: " ICECAST_VERSION_STRING "\r\n"
|
|
||||||
"\r\n",
|
|
||||||
remotemount);
|
|
||||||
}
|
|
||||||
memset(header, 0, sizeof(header));
|
memset(header, 0, sizeof(header));
|
||||||
if (util_read_header(con->sock, header, 4096) == 0) {
|
if (util_read_header(con->sock, header, 4096) == 0) {
|
||||||
WARN0("Header read failed");
|
WARN0("Header read failed");
|
||||||
@ -198,7 +192,7 @@ static void *_slave_thread(void *arg) {
|
|||||||
strcat(authheader, password);
|
strcat(authheader, password);
|
||||||
data = util_base64_encode(authheader);
|
data = util_base64_encode(authheader);
|
||||||
sock_write(mastersock,
|
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"
|
"Authorization: Basic %s\r\n"
|
||||||
"\r\n", data);
|
"\r\n", data);
|
||||||
free(authheader);
|
free(authheader);
|
||||||
|
Loading…
Reference in New Issue
Block a user