Commit c26ee2fc authored by Philipp Schafft's avatar Philipp Schafft 🦁

Merge branch 'ph3-listen-sockets'

parents 1a426f7f d9e96a55
Pipeline #238 passed with stage
in 45 seconds
......@@ -32,6 +32,7 @@ noinst_HEADERS = \
refobject.h \
module.h \
reportxml.h \
listensocket.h \
event.h \
event_log.h \
event_exec.h \
......@@ -74,6 +75,7 @@ icecast_SOURCES = \
refobject.c \
module.c \
reportxml.c \
listensocket.c \
format.c \
format_ogg.c \
format_mp3.c \
......
......@@ -747,7 +747,6 @@ static void command_buildm3u(client_t *client, source_t *source, admin_format_t
const char *mount = source->mount;
const char *username = NULL;
const char *password = NULL;
ice_config_t *config;
ssize_t ret;
COMMAND_REQUIRE(client, "username", username);
......@@ -766,17 +765,7 @@ static void command_buildm3u(client_t *client, source_t *source, admin_format_t
}
config = config_get_config();
snprintf(client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret,
"Content-Disposition: attachment; filename=listen.m3u\r\n\r\n"
"http://%s:%s@%s:%d%s\r\n",
username,
password,
config->hostname,
config->port,
mount
);
config_release_config();
client_get_baseurl(client, NULL, client->refbuf->data + ret, PER_CLIENT_REFBUF_SIZE - ret, username, password, "Content-Disposition: attachment; filename=listen.m3u\r\n\r\n", mount, "\r\n");
client->respcode = 200;
client->refbuf->len = strlen (client->refbuf->data);
......@@ -1131,7 +1120,7 @@ static void command_stats(client_t *client, source_t *source, admin_format_t res
ICECAST_LOG_DEBUG("Stats request, sending xml stats");
doc = stats_get_xml(1, mount, client->mode);
doc = stats_get_xml(1, mount, client);
admin_send_response(doc, client, response, STATS_HTML_REQUEST);
xmlFreeDoc(doc);
return;
......
......@@ -10,7 +10,7 @@
* and others (see AUTHORS for details).
* Copyright 2011, Dave 'justdave' Miller <justdave@mozilla.com>.
* Copyright 2011-2014, Thomas B. "dm8tbr" Ruecker <thomas@ruecker.fi>,
* Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
* Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifdef HAVE_CONFIG_H
......@@ -172,6 +172,33 @@ 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;
}
}
char * config_href_to_id(const char *href)
{
if (!href || !*href)
return NULL;
if (*href != '#') {
ICECAST_LOG_ERROR("Can not convert string \"%H\" to ID.", href);
return NULL;
}
return strdup(href+1);
}
static void create_locks(void)
{
thread_mutex_create(&_locks.relay_lock);
......@@ -569,6 +596,7 @@ static void config_clear_resource(resource_t *resource)
xmlFree(resource->vhost);
xmlFree(resource->module);
xmlFree(resource->handler);
free(resource->listen_socket);
free(resource);
resource = nextresource;
}
......@@ -580,6 +608,8 @@ listener_t *config_clear_listener(listener_t *listener)
if (listener)
{
next = listener->next;
if (listener->id) xmlFree(listener->id);
if (listener->on_behalf_of) free(listener->on_behalf_of);
if (listener->bind_address) xmlFree(listener->bind_address);
if (listener->shoutcast_mount) xmlFree(listener->shoutcast_mount);
free (listener);
......@@ -999,7 +1029,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) {
......@@ -1744,6 +1774,20 @@ static void _parse_listen_socket(xmlDocPtr doc,
return;
listener->port = 8000;
listener->id = (char *)xmlGetProp(node, XMLSTR("id"));
tmp = (char*)xmlGetProp(node, XMLSTR("on-behalf-of"));
if (tmp) {
listener->on_behalf_of = config_href_to_id(tmp);
xmlFree(tmp);
}
tmp = (char *)xmlGetProp(node, XMLSTR("type"));
listener->type = config_str_to_listener_type(tmp);
xmlFree(tmp);
node = node->xmlChildrenNode;
do {
if (node == NULL)
break;
......@@ -1964,6 +2008,12 @@ static void _parse_resource(xmlDocPtr doc,
resource->bind_address = (char *)xmlGetProp(node, XMLSTR("bind-address"));
temp = (char *)xmlGetProp(node, XMLSTR("listen-socket"));
if (temp) {
resource->listen_socket = config_href_to_id(temp);
xmlFree(temp);
}
resource->vhost = (char *)xmlGetProp(node, XMLSTR("vhost"));
resource->module = (char *)xmlGetProp(node, XMLSTR("module"));
......@@ -2473,24 +2523,28 @@ mount_proxy *config_find_mount (ice_config_t *config,
return mountinfo;
}
/* Helper function to locate the configuration details of the listening
* socket
*/
listener_t *config_get_listen_sock(ice_config_t *config, connection_t *con)
{
listener_t *listener;
int i = 0;
listener_t *config_copy_listener_one(const listener_t *listener) {
listener_t *n;
listener = config->listen_sock;
while (listener) {
if (i >= global.server_sockets) {
listener = NULL;
} else {
if (global.serversock[i] == con->serversock)
break;
listener = listener->next;
i++;
}
if (listener == NULL)
return NULL;
n = calloc(1, sizeof(*n));
if (n == NULL)
return NULL;
n->next = NULL;
n->port = listener->port;
n->so_sndbuf = listener->so_sndbuf;
n->type = listener->type;
n->id = (char*)xmlStrdup(XMLSTR(listener->id));
if (listener->on_behalf_of) {
n->on_behalf_of = strdup(listener->on_behalf_of);
}
return listener;
n->bind_address = (char*)xmlStrdup(XMLSTR(listener->bind_address));
n->shoutcast_compat = listener->shoutcast_compat;
n->shoutcast_mount = (char*)xmlStrdup(XMLSTR(listener->shoutcast_mount));
n->tls = listener->tls;
return n;
}
......@@ -9,7 +9,7 @@
* Karl Heyes <karl@xiph.org>
* and others (see AUTHORS for details).
* Copyright 2011, Dave 'justdave' Miller <justdave@mozilla.com>.
* Copyright 2011-2014, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
* Copyright 2011-2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifndef __CFGFILE_H__
......@@ -139,6 +139,7 @@ typedef struct _resource {
char *destination;
int port;
char *bind_address;
char *listen_socket;
char *vhost;
char *module;
char *handler;
......@@ -147,8 +148,17 @@ typedef struct _resource {
struct _resource *next;
} resource_t;
typedef enum _listener_type_tag {
LISTENER_TYPE_ERROR,
LISTENER_TYPE_NORMAL,
LISTENER_TYPE_VIRTUAL
} listener_type_t;
typedef struct _listener_t {
struct _listener_t *next;
char *id;
char *on_behalf_of;
listener_type_t type;
int port;
int so_sndbuf;
char *bind_address;
......@@ -262,7 +272,8 @@ void config_set_config(ice_config_t *config);
listener_t *config_clear_listener (listener_t *listener);
void config_clear(ice_config_t *config);
mount_proxy *config_find_mount(ice_config_t *config, const char *mount, mount_type type);
listener_t *config_get_listen_sock(ice_config_t *config, connection_t *con);
listener_t *config_copy_listener_one(const listener_t *listener);
config_options_t *config_parse_options(xmlNodePtr node);
void config_clear_options(config_options_t *options);
......
......@@ -48,6 +48,7 @@
#include "util.h"
#include "acl.h"
#include "listensocket.h"
/* for ADMIN_COMMAND_ERROR */
#include "admin.h"
......@@ -110,7 +111,7 @@ static inline void client_reuseconnection(client_t *client) {
return;
con = client->con;
con = connection_create(con->sock, con->serversock, strdup(con->ip));
con = connection_create(con->sock, con->listensocket_real, con->listensocket_effective, strdup(con->ip));
reuse = client->reuse;
client->con->sock = -1; /* TODO: do not use magic */
......@@ -766,3 +767,91 @@ client_slurp_result_t client_body_skip(client_t *client)
break;
}
}
ssize_t client_get_baseurl(client_t *client, listensocket_t *listensocket, char *buf, size_t len, const char *user, const char *pw, const char *prefix, const char *suffix0, const char *suffix1)
{
const listener_t *listener = NULL;
const ice_config_t *config = NULL;
const char *host = NULL;
const char *proto = "http";
int port = 0;
ssize_t ret;
tlsmode_t tlsmode = ICECAST_TLSMODE_AUTO;
protocol_t protocol = ICECAST_PROTOCOL_HTTP;
if (!buf || !len)
return -1;
if (!prefix)
prefix = "";
if (!suffix0)
suffix0 = "";
if (!suffix1)
suffix1 = "";
if (client) {
host = httpp_getvar(client->parser, "host");
/* at least a couple of players (fb2k/winamp) are reported to send a
* host header but without the port number. So if we are missing the
* port then lets treat it as if no host line was sent */
if (host && strchr(host, ':') == NULL)
host = NULL;
listensocket = client->con->listensocket_effective;
tlsmode = client->con->tlsmode;
protocol = client->protocol;
}
if (!host && listensocket) {
listener = listensocket_get_listener(listensocket);
if (listener) {
host = listener->bind_address;
port = listener->port;
if (!client)
tlsmode = listener->tls;
}
}
if (!host) {
config = config_get_config();
host = config->hostname;
if (!port)
port = config->port;
}
switch (tlsmode) {
case ICECAST_TLSMODE_DISABLED:
case ICECAST_TLSMODE_AUTO:
switch (protocol) {
case ICECAST_PROTOCOL_HTTP: proto = "http"; break;
case ICECAST_PROTOCOL_SHOUTCAST: proto = "icy"; break;
}
break;
case ICECAST_TLSMODE_AUTO_NO_PLAIN:
case ICECAST_TLSMODE_RFC2817:
case ICECAST_TLSMODE_RFC2818:
switch (protocol) {
case ICECAST_PROTOCOL_HTTP: proto = "https"; break;
case ICECAST_PROTOCOL_SHOUTCAST: proto = "icys"; break;
}
break;
}
if (host && port) {
ret = snprintf(buf, len, "%s%s://%s%s%s%s%s:%i%s%s", prefix, proto, user ? user : "", pw ? ":" : "", pw ? pw : "", (user || pw) ? "@" : "", host, port, suffix0, suffix1);
} else if (host) {
ret = snprintf(buf, len, "%s%s://%s%s%s%s%s%s%s", prefix, proto, user ? user : "", pw ? ":" : "", pw ? pw : "", (user || pw) ? "@" : "", host, suffix0, suffix1);
} else {
ret = -1;
}
if (config)
config_release_config();
if (listener)
listensocket_release_listener(listensocket);
return ret;
}
......@@ -151,5 +151,6 @@ ssize_t client_body_read(client_t *client, void *buf, size_t len);
int client_body_eof(client_t *client);
client_slurp_result_t client_body_slurp(client_t *client, void *buf, size_t *len);
client_slurp_result_t client_body_skip(client_t *client);
ssize_t client_get_baseurl(client_t *client, listensocket_t *listensocket, char *buf, size_t len, const char *user, const char *pw, const char *prefix, const char *suffix0, const char *suffix1);
#endif /* __CLIENT_H__ */
This diff is collapsed.
......@@ -32,7 +32,8 @@ struct connection_tag {
uint64_t sent_bytes;
sock_t sock;
sock_t serversock;
listensocket_t *listensocket_real;
listensocket_t *listensocket_effective;
int error;
tlsmode_t tlsmode;
......@@ -50,9 +51,9 @@ void connection_initialize(void);
void connection_shutdown(void);
void connection_reread_config(ice_config_t *config);
void connection_accept_loop(void);
int connection_setup_sockets(ice_config_t *config);
void connection_setup_sockets(ice_config_t *config);
void connection_close(connection_t *con);
connection_t *connection_create(sock_t sock, sock_t serversock, char *ip);
connection_t *connection_create(sock_t sock, listensocket_t *listensocket_real, listensocket_t* listensocket_effective, char *ip);
int connection_complete_source(source_t *source, int response);
void connection_queue(connection_t *con);
void connection_uses_tls(connection_t *con);
......
......@@ -452,16 +452,9 @@ int fserve_client_create (client_t *httpclient, const char *path)
if (m3u_requested && m3u_file_available == 0)
{
const char *host = httpp_getvar (httpclient->parser, "host");
char *sourceuri = strdup (path);
char *dot = strrchr(sourceuri, '.');
/* at least a couple of players (fb2k/winamp) are reported to send a
* host header but without the port number. So if we are missing the
* port then lets treat it as if no host line was sent */
if (host && strchr (host, ':') == NULL)
host = NULL;
*dot = 0;
httpclient->respcode = 200;
ret = util_http_build_header (httpclient->refbuf->data, BUFSIZE, 0,
......@@ -473,24 +466,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
free(sourceuri);
return -1;
}
if (host == NULL)
{
config = config_get_config();
snprintf (httpclient->refbuf->data + ret, BUFSIZE - ret,
"http://%s:%d%s\r\n",
config->hostname, config->port,
sourceuri
);
config_release_config();
}
else
{
snprintf (httpclient->refbuf->data + ret, BUFSIZE - ret,
"http://%s%s\r\n",
host,
sourceuri
);
}
client_get_baseurl(httpclient, NULL, httpclient->refbuf->data + ret, BUFSIZE - ret, NULL, NULL, NULL, sourceuri, "\r\n");
httpclient->refbuf->len = strlen (httpclient->refbuf->data);
fserve_add_client (httpclient, NULL);
free (sourceuri);
......@@ -504,7 +480,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
char *eol = strrchr (reference, '.');
if (eol)
*eol = '\0';
doc = stats_get_xml (0, reference, httpclient->mode);
doc = stats_get_xml (0, reference, httpclient);
free (reference);
admin_send_response (doc, httpclient, ADMIN_FORMAT_HTML, xslt_playlist_requested);
xmlFreeDoc(doc);
......
......@@ -31,7 +31,7 @@ static mutex_t _global_mutex;
void global_initialize(void)
{
global.server_sockets = 0;
global.listensockets = NULL;
global.relays = NULL;
global.master_relays = NULL;
global.running = 0;
......
......@@ -22,13 +22,11 @@
#include "common/thread/thread.h"
#include "common/avl/avl.h"
#include "common/net/sock.h"
#include "icecasttypes.h"
typedef struct ice_global_tag
{
sock_t *serversock;
int server_sockets;
listensocket_container_t *listensockets;
int running;
......
......@@ -104,6 +104,11 @@ typedef struct reportxml_tag reportxml_t;
typedef struct reportxml_node_tag reportxml_node_t;
typedef struct reportxml_database_tag reportxml_database_t;
/* ---[ listensocket.[ch] ]--- */
typedef struct listensocket_container_tag listensocket_container_t;
typedef struct listensocket_tag listensocket_t;
/* ---[ refobject.[ch] ]--- */
typedef struct refobject_base_tag refobject_base_t;
......@@ -116,6 +121,8 @@ typedef union __attribute__ ((__transparent_union__)) {
reportxml_t *reportxml;
reportxml_node_t *reportxml_node;
reportxml_database_t *reportxml_database;
listensocket_container_t *listensocket_container;
listensocket_t *listensocket;
} refobject_t;
#else
typedef void * refobject_t;
......
This diff is collapsed.
/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifndef __LISTENSOCKET_H__
#define __LISTENSOCKET_H__
#include "icecasttypes.h"
#include "cfgfile.h"
listensocket_container_t * listensocket_container_new(void);
int listensocket_container_configure(listensocket_container_t *self, const ice_config_t *config);
int listensocket_container_configure_and_setup(listensocket_container_t *self, const ice_config_t *config);
int listensocket_container_setup(listensocket_container_t *self);
connection_t * listensocket_container_accept(listensocket_container_t *self, int timeout);
int listensocket_container_set_sockcount_cb(listensocket_container_t *self, void (*cb)(size_t count, void *userdata), void *userdata);
ssize_t listensocket_container_sockcount(listensocket_container_t *self);
int listensocket_refsock(listensocket_t *self);
int listensocket_unrefsock(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
......@@ -77,6 +77,7 @@
#include "yp.h"
#include "auth.h"
#include "event.h"
#include "listensocket.h"
#include <libxml/xmlmemory.h>
......@@ -318,20 +319,6 @@ static int _start_logging(void)
return 0;
}
static int _start_listening(void)
{
int i;
for(i=0; i < global.server_sockets; i++) {
if (sock_listen(global.serversock[i], ICECAST_LISTEN_QUEUE) == SOCK_ERROR)
return 0;
sock_set_blocking(global.serversock[i], 0);
}
return 1;
}
static void pidfile_update(ice_config_t *config, int always_try)
{
char *newpidfile = NULL;
......@@ -389,11 +376,10 @@ static int _server_proc_init(void)
{
ice_config_t *config = config_get_config_unlocked();
if (connection_setup_sockets (config) < 1)
return 0;
connection_setup_sockets(config);
if (!_start_listening()) {
_fatal_error("Failed trying to listen on server socket");
if (listensocket_container_sockcount(global.listensockets) < 1) {
ICECAST_LOG_ERROR("Can not listen on any sockets.");
return 0;
}
......
......@@ -200,7 +200,7 @@ static client_t *open_relay_connection (relay_server *relay)
ICECAST_LOG_WARN("Failed to connect to %s:%d", server, port);
break;
}
con = connection_create (streamsock, -1, strdup (server));
con = connection_create(streamsock, NULL, NULL, strdup(server));
/* At this point we may not know if we are relaying an mp3 or vorbis
* stream, but only send the icy-metadata header if the relay details
......
......@@ -616,19 +616,8 @@ static FILE * source_open_dumpfile(const char * filename) {
*/
static void source_init (source_t *source)
{
ice_config_t *config = config_get_config();
char *listenurl;
char listenurl[512];
const char *str;
int listen_url_size;
/* 6 for max size of port */
listen_url_size = strlen("http://") + strlen(config->hostname) +
strlen(":") + 6 + strlen(source->mount) + 1;
listenurl = malloc (listen_url_size);
snprintf (listenurl, listen_url_size, "http://%s:%d%s",
config->hostname, config->port, source->mount);
config_release_config();
str = httpp_getvar(source->parser, "ice-audio-info");
source->audio_info = util_dict_new();
......@@ -638,10 +627,9 @@ static void source_init (source_t *source)
stats_event (source->mount, "audio_info", str);
}
client_get_baseurl(NULL, NULL, listenurl, sizeof(listenurl), NULL, NULL, NULL, NULL, NULL);
stats_event (source->mount, "listenurl", listenurl);
free(listenurl);
if (source->dumpfilename != NULL)
{
source->dumpfile = source_open_dumpfile (source->dumpfilename);
......
......@@ -829,7 +829,7 @@ static inline void __add_authstack (auth_stack_t *stack, xmlNodePtr parent) {
auth_stack_next(&stack);
}
}
static xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, int hidden) {
static xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, int hidden, client_t *client) {
avl_node *avlnode;
xmlNodePtr ret = NULL;
ice_config_t *config;
......@@ -870,7 +870,13 @@ static xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, i
while (avlnode2)
{
stats_node_t *stat = avlnode2->key;
xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
if (client && strcmp(stat->name, "listenurl") == 0) {
char buf[512];
client_get_baseurl(client, NULL, buf, sizeof(buf), NULL, NULL, NULL, source->source, NULL);
xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(buf));
} else {
xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
}
avlnode2 = avl_get_next (avlnode2);
}
......@@ -1022,7 +1028,7 @@ void stats_transform_xslt(client_t *client, const char *uri)
char *xslpath = util_get_path_from_normalised_uri(uri);
const char *mount = httpp_get_param(client->parser, "mount");
doc = stats_get_xml(0, mount, client->mode);
doc = stats_get_xml(0, mount, client);
xslt_transform(doc, xslpath, client, 200);
......@@ -1053,7 +1059,7 @@ static void __add_metadata(xmlNodePtr node, const char *tag) {
free(name);
}
xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount, operation_mode mode)
xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount, client_t *client)
{
xmlDocPtr doc;
xmlNodePtr node;
......@@ -1063,12 +1069,12 @@ xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount, operation_mode
node = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
xmlDocSetRootElement(doc, node);
node = _dump_stats_to_doc (node, show_mount, show_hidden);
node = _dump_stats_to_doc(node, show_mount, show_hidden, client);
if (show_mount && node) {
avl_tree_rlock(global.source_tree);
source = source_find_mount_raw(show_mount);
admin_add_listeners_to_mount(source, node, mode);
admin_add_listeners_to_mount(source, node, client->mode);
avl_tree_unlock(global.source_tree);
}
......
......@@ -18,7 +18,6 @@
#include <libxml/tree.h>
#include "icecasttypes.h"
#include "cfgfile.h"
#include "refbuf.h"
typedef struct _stats_node_tag
......@@ -95,7 +94,7 @@ void stats_callback (client_t *client, void *notused);
void stats_transform_xslt(client_t *client, const char *uri);
void stats_sendxml(client_t *client);
xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount, operation_mode mode);
xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount, client_t *client);
char *stats_get_value(const char *source, const char *name);
#endif /* __STATS_H__ */
......
......@@ -53,6 +53,7 @@
#include "stats.h"
#include "fserve.h"
#include "util.h"
#include "cfgfile.h"
#define CATMODULE "xslt"
......
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