1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00

Support listening on multiple sockets.

svn path=/trunk/icecast/; revision=4454
This commit is contained in:
Michael Smith 2003-03-09 11:27:06 +00:00
parent 5565b331da
commit eba22526aa
8 changed files with 192 additions and 31 deletions

3
News
View File

@ -1,4 +1,7 @@
2003-03-09 2003-03-09
Support listening on multiple sockets.
2003-03-08
Support for shoutcast source protocol added. Support for shoutcast source protocol added.
2003-03-08 2003-03-08

View File

@ -31,9 +31,22 @@
--> -->
<hostname>localhost</hostname> <hostname>localhost</hostname>
<port>8000</port>
<!-- You can use these two if you only want a single listener -->
<!--<port>8000</port> -->
<!--<bind-address>127.0.0.1</bind-address>--> <!--<bind-address>127.0.0.1</bind-address>-->
<!-- You may have multiple <listener> elements -->
<listen-socket>
<port>8000</port>
<!-- <bind-address>127.0.0.1</bind-address> -->
</listen-socket>
<!--
<listen-socket>
<port>8001</port>
</listen-socket>
-->
<!--<master-server>127.0.0.1</master-server>--> <!--<master-server>127.0.0.1</master-server>-->
<!--<master-server-port>8001</master-server-port>--> <!--<master-server-port>8001</master-server-port>-->
<!--<master-update-interval>120</master-update-interval>--> <!--<master-update-interval>120</master-update-interval>-->

View File

@ -26,7 +26,6 @@
#define CONFIG_DEFAULT_FILESERVE 1 #define CONFIG_DEFAULT_FILESERVE 1
#define CONFIG_DEFAULT_TOUCH_FREQ 5 #define CONFIG_DEFAULT_TOUCH_FREQ 5
#define CONFIG_DEFAULT_HOSTNAME "localhost" #define CONFIG_DEFAULT_HOSTNAME "localhost"
#define CONFIG_DEFAULT_PORT 8888
#define CONFIG_DEFAULT_ACCESS_LOG "access.log" #define CONFIG_DEFAULT_ACCESS_LOG "access.log"
#define CONFIG_DEFAULT_ERROR_LOG "error.log" #define CONFIG_DEFAULT_ERROR_LOG "error.log"
#define CONFIG_DEFAULT_LOG_LEVEL 4 #define CONFIG_DEFAULT_LOG_LEVEL 4
@ -61,6 +60,8 @@ static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *c); ice_config_t *c);
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c); static void _parse_relay(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c); static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *c);
static void _add_server(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c); static void _add_server(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void create_locks() { static void create_locks() {
@ -97,6 +98,7 @@ void config_clear(ice_config_t *c)
ice_config_dir_t *dirnode, *nextdirnode; ice_config_dir_t *dirnode, *nextdirnode;
relay_server *relay, *nextrelay; relay_server *relay, *nextrelay;
mount_proxy *mount, *nextmount; mount_proxy *mount, *nextmount;
int i;
if (c->config_filename) if (c->config_filename)
free(c->config_filename); free(c->config_filename);
@ -125,7 +127,9 @@ void config_clear(ice_config_t *c)
xmlFree(c->access_log); xmlFree(c->access_log);
if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG) if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG)
xmlFree(c->error_log); xmlFree(c->error_log);
if (c->bind_address) xmlFree(c->bind_address); for(i=0; i < MAX_LISTEN_SOCKETS; i++) {
if (c->listeners[i].bind_address) xmlFree(c->listeners[i].bind_address);
}
if (c->master_server) xmlFree(c->master_server); if (c->master_server) xmlFree(c->master_server);
if (c->master_password) xmlFree(c->master_password); if (c->master_password) xmlFree(c->master_password);
if (c->user) xmlFree(c->user); if (c->user) xmlFree(c->user);
@ -262,10 +266,11 @@ static void _set_defaults(ice_config_t *configuration)
configuration->touch_interval = CONFIG_DEFAULT_TOUCH_FREQ; configuration->touch_interval = CONFIG_DEFAULT_TOUCH_FREQ;
configuration->dir_list = NULL; configuration->dir_list = NULL;
configuration->hostname = CONFIG_DEFAULT_HOSTNAME; configuration->hostname = CONFIG_DEFAULT_HOSTNAME;
configuration->port = CONFIG_DEFAULT_PORT; configuration->port = 0;
configuration->bind_address = NULL; configuration->listeners[0].port = 0;
configuration->listeners[0].bind_address = NULL;
configuration->master_server = NULL; configuration->master_server = NULL;
configuration->master_server_port = CONFIG_DEFAULT_PORT; configuration->master_server_port = 0;
configuration->master_update_interval = CONFIG_MASTER_UPDATE_INTERVAL; configuration->master_update_interval = CONFIG_MASTER_UPDATE_INTERVAL;
configuration->master_password = NULL; configuration->master_password = NULL;
configuration->base_dir = CONFIG_DEFAULT_BASE_DIR; configuration->base_dir = CONFIG_DEFAULT_BASE_DIR;
@ -324,13 +329,17 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node,
} else if (strcmp(node->name, "hostname") == 0) { } else if (strcmp(node->name, "hostname") == 0) {
if (configuration->hostname && configuration->hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(configuration->hostname); if (configuration->hostname && configuration->hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(configuration->hostname);
configuration->hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); configuration->hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "port") == 0) { } else if (strcmp(node->name, "listen-socket") == 0) {
_parse_listen_socket(doc, node->xmlChildrenNode, configuration);
} else if (strcmp(node->name, "port") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
configuration->port = atoi(tmp); configuration->port = atoi(tmp);
configuration->listeners[0].port = atoi(tmp);
if (tmp) xmlFree(tmp); if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "bind-address") == 0) { } else if (strcmp(node->name, "bind-address") == 0) {
if (configuration->bind_address) xmlFree(configuration->bind_address); if (configuration->listeners[0].bind_address)
configuration->bind_address = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); xmlFree(configuration->listeners[0].bind_address);
configuration->listeners[0].bind_address = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (strcmp(node->name, "master-server") == 0) { } else if (strcmp(node->name, "master-server") == 0) {
if (configuration->master_server) xmlFree(configuration->master_server); if (configuration->master_server) xmlFree(configuration->master_server);
configuration->master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); configuration->master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
@ -501,6 +510,38 @@ static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
} while ((node = node->next)); } while ((node = node->next));
} }
static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
listener_t *listener = NULL;
int i;
char *tmp;
for(i=0; i < MAX_LISTEN_SOCKETS; i++) {
if(configuration->listeners[i].port <= 0) {
listener = &(configuration->listeners[i]);
break;
}
}
do {
if (node == NULL) break;
if (xmlIsBlankNode(node)) continue;
if (strcmp(node->name, "port") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if(configuration->port == 0)
configuration->port = atoi(tmp);
listener->port = atoi(tmp);
if(tmp) xmlFree(tmp);
}
else if (strcmp(node->name, "bind-address") == 0) {
listener->bind_address = (char *)xmlNodeListGetString(doc,
node->xmlChildrenNode, 1);
}
} while ((node = node->next));
}
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node, static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration) ice_config_t *configuration)
{ {

View File

@ -8,7 +8,10 @@
#define MAX_YP_DIRECTORIES 25 #define MAX_YP_DIRECTORIES 25
#include "thread/thread.h" #include "thread/thread.h"
#include "avl/avl.h"
#include "global.h"
typedef struct ice_config_dir_tag typedef struct ice_config_dir_tag
{ {
@ -40,6 +43,11 @@ typedef struct _mount_proxy {
struct _mount_proxy *next; struct _mount_proxy *next;
} mount_proxy; } mount_proxy;
typedef struct {
int port;
char *bind_address;
} listener_t;
typedef struct ice_config_tag typedef struct ice_config_tag
{ {
char *config_filename; char *config_filename;
@ -66,8 +74,10 @@ typedef struct ice_config_tag
ice_config_dir_t *dir_list; ice_config_dir_t *dir_list;
char *hostname; char *hostname;
int port; int port;
char *bind_address;
listener_t listeners[MAX_LISTEN_SOCKETS];
char *master_server; char *master_server;
int master_server_port; int master_server_port;
int master_update_interval; int master_update_interval;

View File

@ -4,6 +4,9 @@
#include <time.h> #include <time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <sys/time.h> #include <sys/time.h>
@ -121,20 +124,84 @@ connection_t *create_connection(sock_t sock, char *ip) {
return con; return con;
} }
static int wait_for_serversock(int timeout)
{
#ifdef HAVE_POLL
struct pollfd ufds[MAX_LISTEN_SOCKETS];
int i, ret;
for(i=0; i < global.server_sockets; i++) {
ufds[i].fd = global.serversock[i];
ufds[i].events = POLLIN;
ufds[i].revents = 0;
}
ret = poll(ufds, global.server_sockets, timeout);
if(ret < 0) {
return -2;
}
else if(ret == 0) {
return -1;
}
else {
for(i=0; i < global.server_sockets; i++) {
if(ufds[i].revents == POLLIN)
return ufds[i].fd;
}
return -1; /* Shouldn't happen */
}
#else
fd_set rfds;
struct timeval tv, *p=NULL;
int i, ret;
int max = -1;
FD_ZERO(&rfds);
for(i=0; i < global.server_sockets; i++) {
FD_SET(global.serversock[i], &rfds);
if(global.serversock[i] > max)
max = global.serversock[i];
}
if(timeout >= 0) {
tv.tv_sec = timeout/1000;
tv.tv_usec = (timeout % 1000)/1000;
p = &tv;
}
ret = select(max+1, &rfds, NULL, NULL, p);
if(ret < 0) {
return -2;
}
else if(ret == 0) {
return -1;
}
else {
for(i=0; i < global.server_sockets; i++) {
if(FD_ISSET(global.serversock[i], &rfds))
return global.serversock[i];
}
return -1; /* Should be impossible, stop compiler warnings */
}
#endif
}
static connection_t *_accept_connection(void) static connection_t *_accept_connection(void)
{ {
int sock; int sock;
connection_t *con; connection_t *con;
char *ip; char *ip;
int serversock;
if (util_timed_wait_for_fd(global.serversock, 100) <= 0) { serversock = wait_for_serversock(100);
return NULL; if(serversock < 0)
} return NULL;
/* malloc enough room for a full IP address (including ipv6) */ /* malloc enough room for a full IP address (including ipv6) */
ip = (char *)malloc(MAX_ADDR_LEN); ip = (char *)malloc(MAX_ADDR_LEN);
sock = sock_accept(global.serversock, ip, MAX_ADDR_LEN); sock = sock_accept(serversock, ip, MAX_ADDR_LEN);
if (sock >= 0) { if (sock >= 0) {
con = create_connection(sock, ip); con = create_connection(sock, ip);

View File

@ -1,3 +1,5 @@
#include <string.h>
#include "thread.h" #include "thread.h"
#include "avl.h" #include "avl.h"
@ -17,7 +19,8 @@ static mutex_t _global_mutex;
void global_initialize(void) void global_initialize(void)
{ {
global.serversock = -1; memset(global.serversock, 0, sizeof(int)*MAX_LISTEN_SOCKETS);
global.server_sockets = 0;
global.running = 0; global.running = 0;
global.clients = 0; global.clients = 0;
global.sources = 0; global.sources = 0;

View File

@ -8,11 +8,14 @@
#define ICECAST_VERSION_STRING "Icecast 2.0-alpha2/cvs" #define ICECAST_VERSION_STRING "Icecast 2.0-alpha2/cvs"
#define MAX_LISTEN_SOCKETS 10
#include "thread/thread.h" #include "thread/thread.h"
typedef struct ice_global_tag typedef struct ice_global_tag
{ {
int serversock; int serversock[MAX_LISTEN_SOCKETS];
int server_sockets;
int running; int running;

View File

@ -153,26 +153,47 @@ static int _start_logging(void)
return 0; return 0;
} }
static int _setup_socket(void) static int _setup_sockets(void)
{ {
ice_config_t *config; ice_config_t *config;
int i = 0;
int ret = 0;
int successful = 0;
config = config_get_config_unlocked(); config = config_get_config_unlocked();
global.serversock = sock_get_server_socket(config->port, config->bind_address); for(i = 0; i < MAX_LISTEN_SOCKETS; i++) {
if(config->listeners[i].port <= 0)
break;
if (global.serversock == SOCK_ERROR) global.serversock[i] = sock_get_server_socket(
return 0; config->listeners[i].port, config->listeners[i].bind_address);
if (global.serversock[i] == SOCK_ERROR) {
fprintf(stderr, "Could not create listener socket on port %d\n",
config->listeners[i].port);
return 0;
}
else {
ret = 1;
successful++;
}
}
global.server_sockets = successful;
return 1; return ret;
} }
static int _start_listening(void) static int _start_listening(void)
{ {
if (sock_listen(global.serversock, ICE_LISTEN_QUEUE) == SOCK_ERROR) int i;
return 0; for(i=0; i < global.server_sockets; i++) {
if (sock_listen(global.serversock[i], ICE_LISTEN_QUEUE) == SOCK_ERROR)
return 0;
sock_set_blocking(global.serversock, SOCK_NONBLOCK); sock_set_blocking(global.serversock[i], SOCK_NONBLOCK);
}
return 1; return 1;
} }
@ -180,11 +201,8 @@ static int _start_listening(void)
/* bind the socket and start listening */ /* bind the socket and start listening */
static int _server_proc_init(void) static int _server_proc_init(void)
{ {
if (!_setup_socket()) { if (!_setup_sockets())
fprintf(stderr, "Could not create listener socket on port %d\n",
config_get_config_unlocked()->port);
return 0; return 0;
}
if (!_start_listening()) { if (!_start_listening()) {
fprintf(stderr, "Failed trying to listen on server socket\n"); fprintf(stderr, "Failed trying to listen on server socket\n");
@ -197,9 +215,12 @@ static int _server_proc_init(void)
/* this is the heart of the beast */ /* this is the heart of the beast */
static void _server_proc(void) static void _server_proc(void)
{ {
int i;
connection_accept_loop(); connection_accept_loop();
sock_close(global.serversock); for(i=0; i < MAX_LISTEN_SOCKETS; i++)
sock_close(global.serversock[i]);
} }
/* chroot the process. Watch out - we need to do this before starting other /* chroot the process. Watch out - we need to do this before starting other