1
0
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:
oddsock 2003-12-12 23:06:44 +00:00
parent bb96da291a
commit e8a61ce5d3
5 changed files with 104 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

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