...
 
......@@ -167,6 +167,20 @@ operation_mode config_str_to_omode(const char *str)
}
}
static listener_type_t config_str_to_listener_type(const char *str)
{
if (!str || !*str) {
return LISTENER_TYPE_NORMAL;
} else if (strcasecmp(str, "normal") == 0) {
return LISTENER_TYPE_NORMAL;
} else if (strcasecmp(str, "virtual") == 0) {
return LISTENER_TYPE_VIRTUAL;
} else {
ICECAST_LOG_ERROR("Unknown listener type \"%s\", falling back to NORMAL.", str);
return LISTENER_TYPE_NORMAL;
}
}
static void create_locks(void)
{
thread_mutex_create(&_locks.relay_lock);
......@@ -557,6 +571,7 @@ listener_t *config_clear_listener(listener_t *listener)
if (listener)
{
next = listener->next;
if (listener->id) xmlFree(listener->id);
if (listener->bind_address) xmlFree(listener->bind_address);
if (listener->shoutcast_mount) xmlFree(listener->shoutcast_mount);
free (listener);
......@@ -979,7 +994,7 @@ static void _parse_root(xmlDocPtr doc,
xmlFree(configuration->mimetypes_fn);
configuration->mimetypes_fn = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (xmlStrcmp(node->name, XMLSTR("listen-socket")) == 0) {
_parse_listen_socket(doc, node->xmlChildrenNode, configuration);
_parse_listen_socket(doc, node, configuration);
} else if (xmlStrcmp(node->name, XMLSTR("port")) == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
if (tmp && *tmp) {
......@@ -1720,6 +1735,14 @@ static void _parse_listen_socket(xmlDocPtr doc,
return;
listener->port = 8000;
listener->id = (char *)xmlGetProp(node, XMLSTR("id"));
tmp = (char *)xmlGetProp(node, XMLSTR("type"));
listener->type = config_str_to_listener_type(tmp);
xmlFree(tmp);
node = node->xmlChildrenNode;
do {
if (node == NULL)
break;
......@@ -2411,6 +2434,8 @@ listener_t *config_copy_listener_one(const listener_t *listener) {
n->next = NULL;
n->port = listener->port;
n->so_sndbuf = listener->so_sndbuf;
n->type = listener->type;
n->id = (char*)xmlStrdup(XMLSTR(listener->id));
n->bind_address = (char*)xmlStrdup(XMLSTR(listener->bind_address));
n->shoutcast_compat = listener->shoutcast_compat;
n->shoutcast_mount = (char*)xmlStrdup(XMLSTR(listener->shoutcast_mount));
......
......@@ -25,6 +25,7 @@
struct _mount_proxy;
typedef struct ice_config_tag ice_config_t;
typedef struct _listener_t listener_t;
typedef enum _listener_type_tag listener_type_t;
#include <libxml/tree.h>
#include "common/thread/thread.h"
......@@ -167,8 +168,16 @@ typedef struct _aliases {
struct _aliases *next;
} aliases;
enum _listener_type_tag {
LISTENER_TYPE_ERROR,
LISTENER_TYPE_NORMAL,
LISTENER_TYPE_VIRTUAL
};
struct _listener_t {
struct _listener_t *next;
char *id;
listener_type_t type;
int port;
int so_sndbuf;
char *bind_address;
......
......@@ -305,13 +305,19 @@ int listensocket_container_setup(listensocket_container_
}
static int listensocket_container_setup__unlocked(listensocket_container_t *self)
{
listener_type_t type;
size_t i;
int ret = 0;
for (i = 0; i < self->sock_len; i++) {
if (self->sockref[i]) {
listensocket_apply_config(self->sock[i]);
} else {
listensocket_apply_config(self->sock[i]);
type = listensocket_get_type(self->sock[i]);
if (self->sockref[i] && type == LISTENER_TYPE_VIRTUAL) {
if (listensocket_unrefsock(self->sock[i]) == 0) {
self->sockref[i] = 0;
}
} else if (!self->sockref[i] && type != LISTENER_TYPE_VIRTUAL) {
if (listensocket_refsock(self->sock[i]) == 0) {
self->sockref[i] = 1;
} else {
......@@ -326,7 +332,7 @@ static int listensocket_container_setup__unlocked(listensocket_container_t *self
return ret;
}
static connection_t * listensocket_container_accept__inner(listensocket_container_t *self, int timeout)
static listensocket_t * listensocket_container_accept__inner(listensocket_container_t *self, int timeout)
{
#ifdef HAVE_POLL
struct pollfd ufds[self->sock_len];
......@@ -360,7 +366,7 @@ static connection_t * listensocket_container_accept__inner(listensocket_co
for (i = 0; i < found; i++) {
if (ufds[i].revents & POLLIN) {
return listensocket_accept(socks[i]);
return socks[i];
}
if (!(ufds[i].revents & (POLLHUP|POLLERR|POLLNVAL)))
......@@ -407,7 +413,7 @@ static connection_t * listensocket_container_accept__inner(listensocket_co
for (i = 0; i < self->sock_len; i++) {
if (self->sockref[i]) {
if (listensocket__select_isset(self->sock[i], &rfds)) {
return listensocket_accept(self->sock[i]);
return self->sock[i];
}
}
}
......@@ -417,14 +423,20 @@ static connection_t * listensocket_container_accept__inner(listensocket_co
}
connection_t * listensocket_container_accept(listensocket_container_t *self, int timeout)
{
listensocket_t *ls;
connection_t *ret;
if (!self)
return NULL;
thread_mutex_lock(&self->lock);
ret = listensocket_container_accept__inner(self, timeout);
ls = listensocket_container_accept__inner(self, timeout);
listensocket_ref(ls);
thread_mutex_unlock(&self->lock);
ret = listensocket_accept(ls, self);
listensocket_unref(ls);
return ret;
}
......@@ -574,10 +586,12 @@ static int listensocket_apply_config__unlocked(listensocket_t *self
listener = self->listener;
}
if (listener->so_sndbuf)
sock_set_send_buffer(self->sock, listener->so_sndbuf);
if (self->sock != SOCK_ERROR) {
if (listener->so_sndbuf)
sock_set_send_buffer(self->sock, listener->so_sndbuf);
sock_set_blocking(self->sock, 0);
sock_set_blocking(self->sock, 0);
}
if (self->listener_update) {
while ((self->listener = config_clear_listener(self->listener)));
......@@ -673,9 +687,10 @@ int listensocket_unrefsock(listensocket_t *self)
return 0;
}
connection_t * listensocket_accept(listensocket_t *self)
connection_t * listensocket_accept(listensocket_t *self, listensocket_container_t *container)
{
connection_t *con;
listensocket_t *effective = NULL;
sock_t sock;
char *ip;
......@@ -698,7 +713,15 @@ connection_t * listensocket_accept(listensocket_t *self)
memmove(ip, ip+7, strlen(ip+7)+1);
}
con = connection_create(sock, self, self, ip);
if (!effective) {
effective = self;
listensocket_ref(effective);
}
con = connection_create(sock, self, effective, ip);
listensocket_unref(effective);
if (con == NULL) {
sock_close(sock);
free(ip);
......@@ -740,6 +763,20 @@ int listensocket_release_listener(listensocket_t *self)
return 0;
}
listener_type_t listensocket_get_type(listensocket_t *self)
{
listener_type_t ret;
if (!self)
return LISTENER_TYPE_ERROR;
thread_mutex_lock(&self->lock);
ret = self->listener->type;
thread_mutex_unlock(&self->lock);
return ret;
}
#ifdef HAVE_POLL
static inline int listensocket__poll_fill(listensocket_t *self, struct pollfd *p)
{
......
......@@ -29,8 +29,9 @@ int listensocket_ref(listensocket_t *self);
int listensocket_unref(listensocket_t *self);
int listensocket_refsock(listensocket_t *self);
int listensocket_unrefsock(listensocket_t *self);
connection_t * listensocket_accept(listensocket_t *self);
connection_t * listensocket_accept(listensocket_t *self, listensocket_container_t *container);
const listener_t * listensocket_get_listener(listensocket_t *self);
int listensocket_release_listener(listensocket_t *self);
listener_type_t listensocket_get_type(listensocket_t *self);
#endif