Commit 7742bf0a authored by Philipp Schafft's avatar Philipp Schafft 🦁

Fix: Report correct listen URL to client.

The URL is constructed considering Protocol, TLS Mode, Host, and Port.

This considers:
 - The Host:-header as provided by the client,
 - The effective listensocket of the client,
 - Global configuration.

This works for:
 - Playlist generation,
 - Admin authed playlist generation,
 - Stats based XSLT.

It also unifies code:
 - Default stats values.

Not yet included:
 - YP requests.
parent 33588fc9
......@@ -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;
......
......@@ -48,6 +48,7 @@
#include "util.h"
#include "acl.h"
#include "listensocket.h"
/* for ADMIN_COMMAND_ERROR */
#include "admin.h"
......@@ -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__ */
......@@ -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);
......
......@@ -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