mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-02-02 15:07:36 -05:00
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.
This commit is contained in:
parent
33588fc9cf
commit
7742bf0a21
15
src/admin.c
15
src/admin.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;
|
||||
|
89
src/client.c
89
src/client.c
@ -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__ */
|
||||
|
28
src/fserve.c
28
src/fserve.c
@ -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);
|
||||
|
16
src/source.c
16
src/source.c
@ -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);
|
||||
|
18
src/stats.c
18
src/stats.c
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user