Commit e3bb942e authored by Michael Smith's avatar Michael Smith
Browse files

Rearrange some relaying code.

Add ability to configure individual relays as well (i.e. single stream, rather
than all the streams from a server).

svn path=/trunk/icecast/; revision=4327
parent 9e168dc8
......@@ -37,6 +37,13 @@
<!--<master-server-port>8001</master-server-port>-->
<!--<master-update-interval>120</master-update-interval>-->
<!--<master-password>hackme</master-password>-->
<!--
<relay>
<server>127.0.0.1</server>
<port>8001</port>
<mount>/example.ogg</mount>
</relay>
-->
<fileserve>1</fileserve>
......
......@@ -55,6 +55,7 @@ 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 _parse_relay(xmlDocPtr doc, xmlNodePtr node);
static void _add_server(xmlDocPtr doc, xmlNodePtr node);
void config_initialize(void)
......@@ -257,6 +258,8 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
_configuration.master_update_interval = atoi(tmp);
} else if (strcmp(node->name, "limits") == 0) {
_parse_limits(doc, node->xmlChildrenNode);
} else if (strcmp(node->name, "relay") == 0) {
_parse_relay(doc, node->xmlChildrenNode);
} else if (strcmp(node->name, "directory") == 0) {
_parse_directory(doc, node->xmlChildrenNode);
} else if (strcmp(node->name, "paths") == 0) {
......@@ -305,6 +308,43 @@ static void _parse_limits(xmlDocPtr doc, xmlNodePtr node)
} while ((node = node->next));
}
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node)
{
char *tmp;
relay_server *relay = calloc(1, sizeof(relay_server));
relay_server *current = _configuration.relay;
relay_server *last=NULL;
while(current) {
last = current;
current = current->next;
}
if(last)
last->next = relay;
else
_configuration.relay = relay;
do {
if (node == NULL) break;
if (xmlIsBlankNode(node)) continue;
if (strcmp(node->name, "server") == 0) {
relay->server = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
}
else if (strcmp(node->name, "port") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
relay->port = atoi(tmp);
if(tmp) xmlFree(tmp);
}
else if (strcmp(node->name, "mount") == 0) {
relay->mount = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
}
} while ((node = node->next));
}
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node)
{
do {
......
......@@ -15,6 +15,13 @@ typedef struct ice_config_dir_tag
struct ice_config_dir_tag *next;
} ice_config_dir_t;
typedef struct _relay_server {
char *server;
int port;
char *mount;
struct _relay_server *next;
} relay_server;
typedef struct ice_config_tag
{
char *location;
......@@ -45,6 +52,8 @@ typedef struct ice_config_tag
int master_update_interval;
char *master_password;
relay_server *relay;
char *base_dir;
char *log_dir;
char *webroot_dir;
......
......@@ -64,13 +64,53 @@ void slave_shutdown(void) {
thread_join(_slave_thread_id);
}
static void *_slave_thread(void *arg) {
sock_t mastersock, streamsock;
char buf[256];
static void create_relay_stream(char *server, int port, char *mount)
{
sock_t streamsock;
char header[4096];
connection_t *con;
http_parser_t *parser;
client_t *client;
DEBUG1("Adding source at mountpoint \"%s\"", mount);
streamsock = sock_connect_wto(server, port, 0);
if (streamsock == SOCK_ERROR) {
WARN0("Failed to relay stream from master server");
return;
}
con = create_connection(streamsock, NULL);
sock_write(streamsock, "GET %s HTTP/1.0\r\n\r\n", mount);
memset(header, 0, sizeof(header));
if (util_read_header(con->sock, header, 4096) == 0) {
connection_close(con);
return;
}
parser = httpp_create_parser();
httpp_initialize(parser, NULL);
if(!httpp_parse_response(parser, header, strlen(header), mount)) {
if(httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE)) {
ERROR1("Error parsing relay request: %s",
httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE));
}
else
ERROR0("Error parsing relay request");
connection_close(con);
httpp_destroy(parser);
return;
}
client = client_create(con, parser);
if (!connection_create_source(client, con, parser,
httpp_getvar(parser, HTTPP_VAR_URI))) {
client_destroy(client);
}
return;
}
static void *_slave_thread(void *arg) {
sock_t mastersock;
char buf[256];
int interval = config_get_config()->master_update_interval;
char *authheader, *data;
int len;
......@@ -117,45 +157,30 @@ static void *_slave_thread(void *arg) {
if (!source_find_mount(buf)) {
avl_tree_unlock(global.source_tree);
DEBUG1("Adding source at mountpoint \"%s\"", buf);
streamsock = sock_connect_wto(config_get_config()->master_server, config_get_config()->master_server_port, 0);
if (streamsock == SOCK_ERROR) {
WARN0("Failed to relay stream from master server");
continue;
}
con = create_connection(streamsock, NULL);
sock_write(streamsock, "GET %s HTTP/1.0\r\n\r\n", buf);
memset(header, 0, sizeof(header));
if (util_read_header(con->sock, header, 4096) == 0) {
connection_close(con);
continue;
}
parser = httpp_create_parser();
httpp_initialize(parser, NULL);
if(!httpp_parse_response(parser, header, strlen(header), buf)) {
if(httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE)) {
ERROR1("Error parsing relay request: %s",
httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE));
}
else
ERROR0("Error parsing relay request");
connection_close(con);
httpp_destroy(parser);
continue;
}
client = client_create(con, parser);
if (!connection_create_source(client, con, parser,
httpp_getvar(parser, HTTPP_VAR_URI))) {
client_destroy(client);
}
continue;
}
avl_tree_unlock(global.source_tree);
create_relay_stream(
config_get_config()->master_server,
config_get_config()->master_server_port,
buf);
}
else
avl_tree_unlock(global.source_tree);
}
sock_close(mastersock);
/* And now, we process the individual mounts... */
relay_server *relay = config_get_config()->relay;
while(relay) {
avl_tree_rlock(global.source_tree);
if(!source_find_mount(relay->mount)) {
avl_tree_unlock(global.source_tree);
create_relay_stream(relay->server, relay->port, relay->mount);
}
else
avl_tree_unlock(global.source_tree);
}
}
thread_exit(0);
return NULL;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment