mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-06-30 22:18:19 -04:00
Cleanup codestyle
This commit cleanups codestyle a bit, yet there is still some work to be done
This commit is contained in:
parent
9d84ba2036
commit
0dfc7c5b6a
60
src/acl.c
60
src/acl.c
@ -46,21 +46,25 @@ struct acl_tag {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* some string util functions */
|
/* some string util functions */
|
||||||
static inline void __skip_spaces(const char **str) {
|
static inline void __skip_spaces(const char **str)
|
||||||
|
{
|
||||||
register const char * p;
|
register const char * p;
|
||||||
|
|
||||||
for (p = *str; *p == ' '; p++);
|
for (p = *str; *p == ' '; p++);
|
||||||
|
|
||||||
*str = p;
|
*str = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_set_ANY_str(acl_t * acl, acl_policy_t policy, const char * str, int (*callback)(acl_t *, acl_policy_t, const char *)) {
|
int acl_set_ANY_str(acl_t *acl,
|
||||||
const char * end;
|
acl_policy_t policy,
|
||||||
|
const char *str,
|
||||||
|
int (*callback)(acl_t *, acl_policy_t, const char *))
|
||||||
|
{
|
||||||
|
const char *end;
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!acl || !str || !callback || (policy != ACL_POLICY_ALLOW && policy != ACL_POLICY_DENY))
|
if ( !acl || !str || !callback || (policy != ACL_POLICY_ALLOW && policy != ACL_POLICY_DENY) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -88,7 +92,8 @@ int acl_set_ANY_str(acl_t * acl, acl_policy_t policy, const char * str, int (*ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* basic functions to work with ACLs */
|
/* basic functions to work with ACLs */
|
||||||
acl_t * acl_new(void) {
|
acl_t *acl_new(void)
|
||||||
|
{
|
||||||
acl_t * ret = calloc(1, sizeof(*ret));
|
acl_t * ret = calloc(1, sizeof(*ret));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -109,7 +114,8 @@ acl_t * acl_new(void) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
acl_t * acl_new_from_xml_node(xmlNodePtr node) {
|
acl_t *acl_new_from_xml_node(xmlNodePtr node)
|
||||||
|
{
|
||||||
acl_t * ret;
|
acl_t * ret;
|
||||||
char * tmp;
|
char * tmp;
|
||||||
xmlAttrPtr prop;
|
xmlAttrPtr prop;
|
||||||
@ -191,14 +197,16 @@ acl_t * acl_new_from_xml_node(xmlNodePtr node) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void acl_addref(acl_t * acl) {
|
void acl_addref(acl_t * acl)
|
||||||
|
{
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
acl->refcount++;
|
acl->refcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void acl_release(acl_t * acl) {
|
void acl_release(acl_t * acl)
|
||||||
|
{
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -210,7 +218,10 @@ void acl_release(acl_t * acl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* HTTP Method specific functions */
|
/* HTTP Method specific functions */
|
||||||
int acl_set_method_str__callback(acl_t * acl, acl_policy_t policy, const char * str) {
|
int acl_set_method_str__callback(acl_t *acl,
|
||||||
|
acl_policy_t policy,
|
||||||
|
const char *str)
|
||||||
|
{
|
||||||
httpp_request_type_e method;
|
httpp_request_type_e method;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -228,7 +239,8 @@ int acl_set_method_str__callback(acl_t * acl, acl_policy_t policy, const char *
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
acl_policy_t acl_test_method(acl_t * acl, httpp_request_type_e method) {
|
acl_policy_t acl_test_method(acl_t * acl, httpp_request_type_e method)
|
||||||
|
{
|
||||||
if (!acl || method < httpp_req_none || method > httpp_req_unknown)
|
if (!acl || method < httpp_req_none || method > httpp_req_unknown)
|
||||||
return ACL_POLICY_ERROR;
|
return ACL_POLICY_ERROR;
|
||||||
|
|
||||||
@ -236,7 +248,10 @@ acl_policy_t acl_test_method(acl_t * acl, httpp_request_type_e method) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* admin/ interface specific functions */
|
/* admin/ interface specific functions */
|
||||||
int acl_set_admin_str__callbck(acl_t * acl, acl_policy_t policy, const char * str) {
|
int acl_set_admin_str__callbck(acl_t *acl,
|
||||||
|
acl_policy_t policy,
|
||||||
|
const char *str)
|
||||||
|
{
|
||||||
size_t read_i, write_i;
|
size_t read_i, write_i;
|
||||||
int command = admin_get_command(str);
|
int command = admin_get_command(str);
|
||||||
|
|
||||||
@ -264,7 +279,8 @@ int acl_set_admin_str__callbck(acl_t * acl, acl_policy_t policy, const char * st
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
acl_policy_t acl_test_admin(acl_t * acl, int command) {
|
acl_policy_t acl_test_admin(acl_t *acl, int command)
|
||||||
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (!acl)
|
if (!acl)
|
||||||
@ -278,7 +294,8 @@ acl_policy_t acl_test_admin(acl_t * acl, int command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* web/ interface specific functions */
|
/* web/ interface specific functions */
|
||||||
int acl_set_web_policy(acl_t * acl, acl_policy_t policy) {
|
int acl_set_web_policy(acl_t *acl, acl_policy_t policy)
|
||||||
|
{
|
||||||
if (!acl || (policy != ACL_POLICY_ALLOW && policy != ACL_POLICY_DENY))
|
if (!acl || (policy != ACL_POLICY_ALLOW && policy != ACL_POLICY_DENY))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -287,7 +304,8 @@ int acl_set_web_policy(acl_t * acl, acl_policy_t policy) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
acl_policy_t acl_test_web(acl_t * acl) {
|
acl_policy_t acl_test_web(acl_t *acl)
|
||||||
|
{
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return ACL_POLICY_ERROR;
|
return ACL_POLICY_ERROR;
|
||||||
|
|
||||||
@ -295,7 +313,8 @@ acl_policy_t acl_test_web(acl_t * acl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mount specific functons */
|
/* mount specific functons */
|
||||||
int acl_set_max_connection_duration(acl_t * acl, time_t duration) {
|
int acl_set_max_connection_duration(acl_t *acl, time_t duration)
|
||||||
|
{
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -304,14 +323,16 @@ int acl_set_max_connection_duration(acl_t * acl, time_t duration) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t acl_get_max_connection_duration(acl_t * acl) {
|
time_t acl_get_max_connection_duration(acl_t *acl)
|
||||||
|
{
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return acl->max_connection_duration;
|
return acl->max_connection_duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_set_max_connections_per_user(acl_t * acl, size_t limit) {
|
int acl_set_max_connections_per_user(acl_t *acl, size_t limit)
|
||||||
|
{
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -320,7 +341,8 @@ int acl_set_max_connections_per_user(acl_t * acl, size_t limit) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t acl_get_max_connections_per_user(acl_t * acl) {
|
ssize_t acl_get_max_connections_per_user(acl_t *acl)
|
||||||
|
{
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
391
src/admin.c
391
src/admin.c
@ -89,36 +89,36 @@
|
|||||||
|
|
||||||
/* Private features (in branches not for merge with master) (block 901-999) */
|
/* Private features (in branches not for merge with master) (block 901-999) */
|
||||||
|
|
||||||
#define FALLBACK_RAW_REQUEST "fallbacks"
|
#define FALLBACK_RAW_REQUEST "fallbacks"
|
||||||
#define FALLBACK_TRANSFORMED_REQUEST "fallbacks.xsl"
|
#define FALLBACK_TRANSFORMED_REQUEST "fallbacks.xsl"
|
||||||
#define SHOUTCAST_METADATA_REQUEST "admin.cgi"
|
#define SHOUTCAST_METADATA_REQUEST "admin.cgi"
|
||||||
#define METADATA_RAW_REQUEST "metadata"
|
#define METADATA_RAW_REQUEST "metadata"
|
||||||
#define METADATA_TRANSFORMED_REQUEST "metadata.xsl"
|
#define METADATA_TRANSFORMED_REQUEST "metadata.xsl"
|
||||||
#define LISTCLIENTS_RAW_REQUEST "listclients"
|
#define LISTCLIENTS_RAW_REQUEST "listclients"
|
||||||
#define LISTCLIENTS_TRANSFORMED_REQUEST "listclients.xsl"
|
#define LISTCLIENTS_TRANSFORMED_REQUEST "listclients.xsl"
|
||||||
#define STATS_RAW_REQUEST "stats"
|
#define STATS_RAW_REQUEST "stats"
|
||||||
#define STATS_TRANSFORMED_REQUEST "stats.xsl"
|
#define STATS_TRANSFORMED_REQUEST "stats.xsl"
|
||||||
#define QUEUE_RELOAD_RAW_REQUEST "reloadconfig"
|
#define QUEUE_RELOAD_RAW_REQUEST "reloadconfig"
|
||||||
#define QUEUE_RELOAD_TRANSFORMED_REQUEST "reloadconfig.xsl"
|
#define QUEUE_RELOAD_TRANSFORMED_REQUEST "reloadconfig.xsl"
|
||||||
#define LISTMOUNTS_RAW_REQUEST "listmounts"
|
#define LISTMOUNTS_RAW_REQUEST "listmounts"
|
||||||
#define LISTMOUNTS_TRANSFORMED_REQUEST "listmounts.xsl"
|
#define LISTMOUNTS_TRANSFORMED_REQUEST "listmounts.xsl"
|
||||||
#define STREAMLIST_RAW_REQUEST "streamlist"
|
#define STREAMLIST_RAW_REQUEST "streamlist"
|
||||||
#define STREAMLIST_TRANSFORMED_REQUEST "streamlist.xsl"
|
#define STREAMLIST_TRANSFORMED_REQUEST "streamlist.xsl"
|
||||||
#define STREAMLIST_PLAINTEXT_REQUEST "streamlist.txt"
|
#define STREAMLIST_PLAINTEXT_REQUEST "streamlist.txt"
|
||||||
#define MOVECLIENTS_RAW_REQUEST "moveclients"
|
#define MOVECLIENTS_RAW_REQUEST "moveclients"
|
||||||
#define MOVECLIENTS_TRANSFORMED_REQUEST "moveclients.xsl"
|
#define MOVECLIENTS_TRANSFORMED_REQUEST "moveclients.xsl"
|
||||||
#define KILLCLIENT_RAW_REQUEST "killclient"
|
#define KILLCLIENT_RAW_REQUEST "killclient"
|
||||||
#define KILLCLIENT_TRANSFORMED_REQUEST "killclient.xsl"
|
#define KILLCLIENT_TRANSFORMED_REQUEST "killclient.xsl"
|
||||||
#define KILLSOURCE_RAW_REQUEST "killsource"
|
#define KILLSOURCE_RAW_REQUEST "killsource"
|
||||||
#define KILLSOURCE_TRANSFORMED_REQUEST "killsource.xsl"
|
#define KILLSOURCE_TRANSFORMED_REQUEST "killsource.xsl"
|
||||||
#define ADMIN_XSL_RESPONSE "response.xsl"
|
#define ADMIN_XSL_RESPONSE "response.xsl"
|
||||||
#define MANAGEAUTH_RAW_REQUEST "manageauth"
|
#define MANAGEAUTH_RAW_REQUEST "manageauth"
|
||||||
#define MANAGEAUTH_TRANSFORMED_REQUEST "manageauth.xsl"
|
#define MANAGEAUTH_TRANSFORMED_REQUEST "manageauth.xsl"
|
||||||
#define UPDATEMETADATA_RAW_REQUEST "updatemetadata"
|
#define UPDATEMETADATA_RAW_REQUEST "updatemetadata"
|
||||||
#define UPDATEMETADATA_TRANSFORMED_REQUEST "updatemetadata.xsl"
|
#define UPDATEMETADATA_TRANSFORMED_REQUEST "updatemetadata.xsl"
|
||||||
#define DEFAULT_RAW_REQUEST ""
|
#define DEFAULT_RAW_REQUEST ""
|
||||||
#define DEFAULT_TRANSFORMED_REQUEST ""
|
#define DEFAULT_TRANSFORMED_REQUEST ""
|
||||||
#define BUILDM3U_RAW_REQUEST "buildm3u"
|
#define BUILDM3U_RAW_REQUEST "buildm3u"
|
||||||
|
|
||||||
typedef struct admin_command_tag {
|
typedef struct admin_command_tag {
|
||||||
const int id;
|
const int id;
|
||||||
@ -166,7 +166,8 @@ static const admin_command_t commands[] = {
|
|||||||
{COMMAND_ANY, "*", ADMINTYPE_GENERAL, TRANSFORMED} /* for ACL framework */
|
{COMMAND_ANY, "*", ADMINTYPE_GENERAL, TRANSFORMED} /* for ACL framework */
|
||||||
};
|
};
|
||||||
|
|
||||||
int admin_get_command(const char *command) {
|
int admin_get_command(const char *command)
|
||||||
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < (sizeof(commands)/sizeof(*commands)); i++)
|
for (i = 0; i < (sizeof(commands)/sizeof(*commands)); i++)
|
||||||
@ -176,7 +177,8 @@ int admin_get_command(const char *command) {
|
|||||||
return COMMAND_ERROR;
|
return COMMAND_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int admin_get_command_type(int command) {
|
int admin_get_command_type(int command)
|
||||||
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (command == ADMIN_COMMAND_ERROR || command == COMMAND_ANY)
|
if (command == ADMIN_COMMAND_ERROR || command == COMMAND_ANY)
|
||||||
@ -213,7 +215,7 @@ static void admin_handle_general_request(client_t *client);
|
|||||||
/* build an XML doc containing information about currently running sources.
|
/* build an XML doc containing information about currently running sources.
|
||||||
* If a mountpoint is passed then that source will not be added to the XML
|
* If a mountpoint is passed then that source will not be added to the XML
|
||||||
* doc even if the source is running */
|
* doc even if the source is running */
|
||||||
xmlDocPtr admin_build_sourcelist (const char *mount)
|
xmlDocPtr admin_build_sourcelist(const char *mount)
|
||||||
{
|
{
|
||||||
avl_node *node;
|
avl_node *node;
|
||||||
source_t *source;
|
source_t *source;
|
||||||
@ -255,7 +257,7 @@ xmlDocPtr admin_build_sourcelist (const char *mount)
|
|||||||
xmlNewChild(srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf));
|
xmlNewChild(srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf));
|
||||||
|
|
||||||
config = config_get_config();
|
config = config_get_config();
|
||||||
mountinfo = config_find_mount (config, source->mount, MOUNT_TYPE_NORMAL);
|
mountinfo = config_find_mount(config, source->mount, MOUNT_TYPE_NORMAL);
|
||||||
if (mountinfo)
|
if (mountinfo)
|
||||||
acl = auth_stack_get_anonymous_acl(mountinfo->authstack, httpp_req_get);
|
acl = auth_stack_get_anonymous_acl(mountinfo->authstack, httpp_req_get);
|
||||||
if (!acl)
|
if (!acl)
|
||||||
@ -266,16 +268,14 @@ xmlDocPtr admin_build_sourcelist (const char *mount)
|
|||||||
acl_release(acl);
|
acl_release(acl);
|
||||||
config_release_config();
|
config_release_config();
|
||||||
|
|
||||||
if (source->running)
|
if (source->running) {
|
||||||
{
|
if (source->client) {
|
||||||
if (source->client)
|
snprintf(buf, sizeof(buf), "%lu",
|
||||||
{
|
(unsigned long)(now - source->con->con_time));
|
||||||
snprintf (buf, sizeof(buf), "%lu",
|
xmlNewChild(srcnode, NULL, XMLSTR("Connected"), XMLSTR(buf));
|
||||||
(unsigned long)(now - source->con->con_time));
|
|
||||||
xmlNewChild (srcnode, NULL, XMLSTR("Connected"), XMLSTR(buf));
|
|
||||||
}
|
}
|
||||||
xmlNewChild (srcnode, NULL, XMLSTR("content-type"),
|
xmlNewChild(srcnode, NULL, XMLSTR("content-type"),
|
||||||
XMLSTR(source->format->contenttype));
|
XMLSTR(source->format->contenttype));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node = avl_get_next(node);
|
node = avl_get_next(node);
|
||||||
@ -283,11 +283,12 @@ xmlDocPtr admin_build_sourcelist (const char *mount)
|
|||||||
return(doc);
|
return(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void admin_send_response (xmlDocPtr doc, client_t *client,
|
void admin_send_response(xmlDocPtr doc,
|
||||||
int response, const char *xslt_template)
|
client_t *client,
|
||||||
|
int response,
|
||||||
|
const char *xslt_template)
|
||||||
{
|
{
|
||||||
if (response == RAW)
|
if (response == RAW) {
|
||||||
{
|
|
||||||
xmlChar *buff = NULL;
|
xmlChar *buff = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
size_t buf_len;
|
size_t buf_len;
|
||||||
@ -345,8 +346,7 @@ void admin_send_response (xmlDocPtr doc, client_t *client,
|
|||||||
client->respcode = 200;
|
client->respcode = 200;
|
||||||
fserve_add_client (client, NULL);
|
fserve_add_client (client, NULL);
|
||||||
}
|
}
|
||||||
if (response == TRANSFORMED)
|
if (response == TRANSFORMED) {
|
||||||
{
|
|
||||||
char *fullpath_xslt_template;
|
char *fullpath_xslt_template;
|
||||||
int fullpath_xslt_template_len;
|
int fullpath_xslt_template_len;
|
||||||
ice_config_t *config = config_get_config();
|
ice_config_t *config = config_get_config();
|
||||||
@ -397,7 +397,8 @@ void admin_handle_request(client_t *client, const char *uri)
|
|||||||
if (client->admin_command == COMMAND_RAW_METADATA_UPDATE &&
|
if (client->admin_command == COMMAND_RAW_METADATA_UPDATE &&
|
||||||
(acl_test_method(client->acl, httpp_req_source) == ACL_POLICY_ALLOW ||
|
(acl_test_method(client->acl, httpp_req_source) == ACL_POLICY_ALLOW ||
|
||||||
acl_test_method(client->acl, httpp_req_put) == ACL_POLICY_ALLOW)) {
|
acl_test_method(client->acl, httpp_req_put) == ACL_POLICY_ALLOW)) {
|
||||||
ICECAST_LOG_DEBUG("Granted right to call COMMAND_RAW_METADATA_UPDATE to client because it is allowed to do SOURCE or PUT.");
|
ICECAST_LOG_DEBUG("Granted right to call COMMAND_RAW_METADATA_UPDATE to "
|
||||||
|
"client because it is allowed to do SOURCE or PUT.");
|
||||||
} else {
|
} else {
|
||||||
client_send_error(client, 401, 1, "You need to authenticate\r\n");
|
client_send_error(client, 401, 1, "You need to authenticate\r\n");
|
||||||
return;
|
return;
|
||||||
@ -419,27 +420,22 @@ void admin_handle_request(client_t *client, const char *uri)
|
|||||||
avl_tree_rlock(global.source_tree);
|
avl_tree_rlock(global.source_tree);
|
||||||
source = source_find_mount_raw(mount);
|
source = source_find_mount_raw(mount);
|
||||||
|
|
||||||
if (source == NULL)
|
if (source == NULL) {
|
||||||
{
|
|
||||||
ICECAST_LOG_WARN("Admin command %s on non-existent source %s",
|
ICECAST_LOG_WARN("Admin command %s on non-existent source %s",
|
||||||
command_string, mount);
|
command_string, mount);
|
||||||
avl_tree_unlock(global.source_tree);
|
avl_tree_unlock(global.source_tree);
|
||||||
client_send_error(client, 400, 0, "Source does not exist");
|
client_send_error(client, 400, 0, "Source does not exist");
|
||||||
}
|
} else {
|
||||||
else
|
if (source->running == 0 && source->on_demand == 0) {
|
||||||
{
|
avl_tree_unlock(global.source_tree);
|
||||||
if (source->running == 0 && source->on_demand == 0)
|
|
||||||
{
|
|
||||||
avl_tree_unlock (global.source_tree);
|
|
||||||
ICECAST_LOG_INFO("Received admin command %s on unavailable mount \"%s\"",
|
ICECAST_LOG_INFO("Received admin command %s on unavailable mount \"%s\"",
|
||||||
command_string, mount);
|
command_string, mount);
|
||||||
client_send_error(client, 400, 0, "Source is not available");
|
client_send_error(client, 400, 0, "Source is not available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (client->admin_command == COMMAND_SHOUTCAST_METADATA_UPDATE &&
|
if (client->admin_command == COMMAND_SHOUTCAST_METADATA_UPDATE &&
|
||||||
source->shoutcast_compat == 0)
|
source->shoutcast_compat == 0) {
|
||||||
{
|
avl_tree_unlock(global.source_tree);
|
||||||
avl_tree_unlock (global.source_tree);
|
|
||||||
ICECAST_LOG_ERROR("illegal change of metadata on non-shoutcast "
|
ICECAST_LOG_ERROR("illegal change of metadata on non-shoutcast "
|
||||||
"compatible stream");
|
"compatible stream");
|
||||||
client_send_error(client, 400, 0, "illegal metadata call");
|
client_send_error(client, 400, 0, "illegal metadata call");
|
||||||
@ -450,8 +446,7 @@ void admin_handle_request(client_t *client, const char *uri)
|
|||||||
admin_handle_mount_request(client, source);
|
admin_handle_mount_request(client, source);
|
||||||
avl_tree_unlock(global.source_tree);
|
avl_tree_unlock(global.source_tree);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
admin_handle_general_request(client);
|
admin_handle_general_request(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -461,115 +456,117 @@ static void admin_handle_general_request(client_t *client)
|
|||||||
switch(client->admin_command) {
|
switch(client->admin_command) {
|
||||||
case COMMAND_RAW_STATS:
|
case COMMAND_RAW_STATS:
|
||||||
command_stats(client, NULL, RAW);
|
command_stats(client, NULL, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_QUEUE_RELOAD:
|
case COMMAND_RAW_QUEUE_RELOAD:
|
||||||
command_queue_reload(client, RAW);
|
command_queue_reload(client, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_LIST_MOUNTS:
|
case COMMAND_RAW_LIST_MOUNTS:
|
||||||
command_list_mounts(client, RAW);
|
command_list_mounts(client, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_LISTSTREAM:
|
case COMMAND_RAW_LISTSTREAM:
|
||||||
command_list_mounts(client, RAW);
|
command_list_mounts(client, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_PLAINTEXT_LISTSTREAM:
|
case COMMAND_PLAINTEXT_LISTSTREAM:
|
||||||
command_list_mounts(client, PLAINTEXT);
|
command_list_mounts(client, PLAINTEXT);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_STATS:
|
case COMMAND_TRANSFORMED_STATS:
|
||||||
command_stats(client, NULL, TRANSFORMED);
|
command_stats(client, NULL, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_QUEUE_RELOAD:
|
case COMMAND_TRANSFORMED_QUEUE_RELOAD:
|
||||||
command_queue_reload(client, TRANSFORMED);
|
command_queue_reload(client, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_LIST_MOUNTS:
|
case COMMAND_TRANSFORMED_LIST_MOUNTS:
|
||||||
command_list_mounts(client, TRANSFORMED);
|
command_list_mounts(client, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_LISTSTREAM:
|
case COMMAND_TRANSFORMED_LISTSTREAM:
|
||||||
command_list_mounts(client, TRANSFORMED);
|
command_list_mounts(client, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_MOVE_CLIENTS:
|
case COMMAND_TRANSFORMED_MOVE_CLIENTS:
|
||||||
command_list_mounts(client, TRANSFORMED);
|
command_list_mounts(client, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_MANAGEAUTH:
|
case COMMAND_TRANSFORMED_MANAGEAUTH:
|
||||||
command_manageauth(client, TRANSFORMED);
|
command_manageauth(client, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_MANAGEAUTH:
|
case COMMAND_RAW_MANAGEAUTH:
|
||||||
command_manageauth(client, RAW);
|
command_manageauth(client, RAW);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ICECAST_LOG_WARN("General admin request not recognised");
|
ICECAST_LOG_WARN("General admin request not recognised");
|
||||||
client_send_error(client, 400, 0, "Unknown admin request");
|
client_send_error(client, 400, 0, "Unknown admin request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void admin_handle_mount_request(client_t *client, source_t *source) {
|
static void admin_handle_mount_request(client_t *client, source_t *source)
|
||||||
|
{
|
||||||
switch(client->admin_command) {
|
switch(client->admin_command) {
|
||||||
case COMMAND_RAW_STATS:
|
case COMMAND_RAW_STATS:
|
||||||
command_stats(client, source->mount, RAW);
|
command_stats(client, source->mount, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_FALLBACK:
|
case COMMAND_RAW_FALLBACK:
|
||||||
command_fallback(client, source, RAW);
|
command_fallback(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_METADATA_UPDATE:
|
case COMMAND_RAW_METADATA_UPDATE:
|
||||||
command_metadata(client, source, RAW);
|
command_metadata(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_METADATA_UPDATE:
|
case COMMAND_TRANSFORMED_METADATA_UPDATE:
|
||||||
command_metadata(client, source, TRANSFORMED);
|
command_metadata(client, source, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_SHOUTCAST_METADATA_UPDATE:
|
case COMMAND_SHOUTCAST_METADATA_UPDATE:
|
||||||
command_shoutcast_metadata(client, source);
|
command_shoutcast_metadata(client, source);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_SHOW_LISTENERS:
|
case COMMAND_RAW_SHOW_LISTENERS:
|
||||||
command_show_listeners(client, source, RAW);
|
command_show_listeners(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_MOVE_CLIENTS:
|
case COMMAND_RAW_MOVE_CLIENTS:
|
||||||
command_move_clients(client, source, RAW);
|
command_move_clients(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_KILL_CLIENT:
|
case COMMAND_RAW_KILL_CLIENT:
|
||||||
command_kill_client(client, source, RAW);
|
command_kill_client(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_KILL_SOURCE:
|
case COMMAND_RAW_KILL_SOURCE:
|
||||||
command_kill_source(client, source, RAW);
|
command_kill_source(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_STATS:
|
case COMMAND_TRANSFORMED_STATS:
|
||||||
command_stats(client, source->mount, TRANSFORMED);
|
command_stats(client, source->mount, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_FALLBACK:
|
case COMMAND_TRANSFORMED_FALLBACK:
|
||||||
command_fallback(client, source, RAW);
|
command_fallback(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_SHOW_LISTENERS:
|
case COMMAND_TRANSFORMED_SHOW_LISTENERS:
|
||||||
command_show_listeners(client, source, TRANSFORMED);
|
command_show_listeners(client, source, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_MOVE_CLIENTS:
|
case COMMAND_TRANSFORMED_MOVE_CLIENTS:
|
||||||
command_move_clients(client, source, TRANSFORMED);
|
command_move_clients(client, source, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_KILL_CLIENT:
|
case COMMAND_TRANSFORMED_KILL_CLIENT:
|
||||||
command_kill_client(client, source, TRANSFORMED);
|
command_kill_client(client, source, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_KILL_SOURCE:
|
case COMMAND_TRANSFORMED_KILL_SOURCE:
|
||||||
command_kill_source(client, source, TRANSFORMED);
|
command_kill_source(client, source, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_TRANSFORMED_UPDATEMETADATA:
|
case COMMAND_TRANSFORMED_UPDATEMETADATA:
|
||||||
command_updatemetadata(client, source, TRANSFORMED);
|
command_updatemetadata(client, source, TRANSFORMED);
|
||||||
break;
|
break;
|
||||||
case COMMAND_RAW_UPDATEMETADATA:
|
case COMMAND_RAW_UPDATEMETADATA:
|
||||||
command_updatemetadata(client, source, RAW);
|
command_updatemetadata(client, source, RAW);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ICECAST_LOG_WARN("Mount request not recognised");
|
ICECAST_LOG_WARN("Mount request not recognised");
|
||||||
client_send_error(client, 400, 0, "Mount request unknown");
|
client_send_error(client, 400, 0, "Mount request unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMMAND_REQUIRE(client,name,var) \
|
#define COMMAND_REQUIRE(client,name,var) \
|
||||||
do { \
|
do { \
|
||||||
(var) = httpp_get_query_param((client)->parser, (name)); \
|
(var) = httpp_get_query_param((client)->parser, (name)); \
|
||||||
if((var) == NULL) { \
|
if((var) == NULL) { \
|
||||||
client_send_error((client), 400, 0, "Missing parameter"); \
|
client_send_error((client), 400, 0, "Missing parameter"); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
#define COMMAND_OPTIONAL(client,name,var) \
|
#define COMMAND_OPTIONAL(client,name,var) \
|
||||||
(var) = httpp_get_query_param((client)->parser, (name))
|
(var) = httpp_get_query_param((client)->parser, (name))
|
||||||
|
|
||||||
@ -577,8 +574,8 @@ static void html_success(client_t *client, char *message)
|
|||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
|
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
|
||||||
0, 200, NULL,
|
0, 0, 200, NULL,
|
||||||
"text/html", "utf-8",
|
"text/html", "utf-8",
|
||||||
"", NULL);
|
"", NULL);
|
||||||
|
|
||||||
@ -593,13 +590,14 @@ static void html_success(client_t *client, char *message)
|
|||||||
"<body><p>%s</p></body></html>", message);
|
"<body><p>%s</p></body></html>", message);
|
||||||
|
|
||||||
client->respcode = 200;
|
client->respcode = 200;
|
||||||
client->refbuf->len = strlen (client->refbuf->data);
|
client->refbuf->len = strlen(client->refbuf->data);
|
||||||
fserve_add_client (client, NULL);
|
fserve_add_client(client, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void command_move_clients(client_t *client, source_t *source,
|
static void command_move_clients(client_t *client,
|
||||||
int response)
|
source_t *source,
|
||||||
|
int response)
|
||||||
{
|
{
|
||||||
const char *dest_source;
|
const char *dest_source;
|
||||||
source_t *dest;
|
source_t *dest;
|
||||||
@ -621,46 +619,46 @@ static void command_move_clients(client_t *client, source_t *source,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = source_find_mount (dest_source);
|
dest = source_find_mount(dest_source);
|
||||||
|
|
||||||
if (dest == NULL)
|
if (dest == NULL) {
|
||||||
{
|
|
||||||
client_send_error(client, 400, 0, "No such destination");
|
client_send_error(client, 400, 0, "No such destination");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp (dest->mount, source->mount) == 0)
|
if (strcmp(dest->mount, source->mount) == 0) {
|
||||||
{
|
|
||||||
client_send_error(client, 400, 0, "supplied mountpoints are identical");
|
client_send_error(client, 400, 0, "supplied mountpoints are identical");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest->running == 0 && dest->on_demand == 0)
|
if (dest->running == 0 && dest->on_demand == 0) {
|
||||||
{
|
|
||||||
client_send_error(client, 400, 0, "Destination not running");
|
client_send_error(client, 400, 0, "Destination not running");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICECAST_LOG_INFO("source is \"%s\", destination is \"%s\"", source->mount, dest->mount);
|
ICECAST_LOG_INFO("source is \"%s\", destination is \"%s\"", source->mount, dest->mount);
|
||||||
|
|
||||||
doc = xmlNewDoc (XMLSTR("1.0"));
|
doc = xmlNewDoc(XMLSTR("1.0"));
|
||||||
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
|
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
|
||||||
xmlDocSetRootElement(doc, node);
|
xmlDocSetRootElement(doc, node);
|
||||||
|
|
||||||
source_move_clients (source, dest);
|
source_move_clients(source, dest);
|
||||||
|
|
||||||
memset(buf, '\000', sizeof(buf));
|
memset(buf, '\000', sizeof(buf));
|
||||||
snprintf (buf, sizeof(buf), "Clients moved from %s to %s",
|
snprintf(buf, sizeof(buf), "Clients moved from %s to %s",
|
||||||
source->mount, dest_source);
|
source->mount, dest_source);
|
||||||
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(buf));
|
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(buf));
|
||||||
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
|
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
|
||||||
|
|
||||||
admin_send_response(doc, client, response,
|
admin_send_response(doc, client, response, ADMIN_XSL_RESPONSE);
|
||||||
ADMIN_XSL_RESPONSE);
|
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline xmlNodePtr __add_listener(client_t *client, xmlNodePtr parent, time_t now, operation_mode mode) {
|
static inline xmlNodePtr __add_listener(client_t *client,
|
||||||
|
xmlNodePtr parent,
|
||||||
|
time_t now,
|
||||||
|
operation_mode mode)
|
||||||
|
{
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
xmlNodePtr node;
|
xmlNodePtr node;
|
||||||
char buf[22];
|
char buf[22];
|
||||||
@ -703,7 +701,10 @@ static inline xmlNodePtr __add_listener(client_t *client, xmlNodePtr parent, tim
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void admin_add_listeners_to_mount(source_t *source, xmlNodePtr parent, operation_mode mode) {
|
void admin_add_listeners_to_mount(source_t *source,
|
||||||
|
xmlNodePtr parent,
|
||||||
|
operation_mode mode)
|
||||||
|
{
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
avl_node *client_node;
|
avl_node *client_node;
|
||||||
|
|
||||||
@ -716,8 +717,9 @@ void admin_add_listeners_to_mount(source_t *source, xmlNodePtr parent, operation
|
|||||||
avl_tree_unlock(source->client_tree);
|
avl_tree_unlock(source->client_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_show_listeners(client_t *client, source_t *source,
|
static void command_show_listeners(client_t *client,
|
||||||
int response)
|
source_t *source,
|
||||||
|
int response)
|
||||||
{
|
{
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlNodePtr node, srcnode;
|
xmlNodePtr node, srcnode;
|
||||||
@ -740,7 +742,7 @@ static void command_show_listeners(client_t *client, source_t *source,
|
|||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_buildm3u(client_t *client, const char *mount)
|
static void command_buildm3u(client_t *client, const char *mount)
|
||||||
{
|
{
|
||||||
const char *username = NULL;
|
const char *username = NULL;
|
||||||
const char *password = NULL;
|
const char *password = NULL;
|
||||||
@ -750,12 +752,13 @@ static void command_buildm3u(client_t *client, const char *mount)
|
|||||||
COMMAND_REQUIRE(client, "username", username);
|
COMMAND_REQUIRE(client, "username", username);
|
||||||
COMMAND_REQUIRE(client, "password", password);
|
COMMAND_REQUIRE(client, "password", password);
|
||||||
|
|
||||||
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
|
ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
|
||||||
0, 200, NULL,
|
0, 0, 200, NULL,
|
||||||
"audio/x-mpegurl", NULL,
|
"audio/x-mpegurl", NULL,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
if (ret == -1 || ret >= (PER_CLIENT_REFBUF_SIZE - 512)) { /* we want at least 512 Byte left for data */
|
if (ret == -1 || ret >= (PER_CLIENT_REFBUF_SIZE - 512)) {
|
||||||
|
/* we want at least 512 Byte left for data */
|
||||||
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
|
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
|
||||||
client_send_error(client, 500, 0, "Header generation failed.");
|
client_send_error(client, 500, 0, "Header generation failed.");
|
||||||
return;
|
return;
|
||||||
@ -779,7 +782,8 @@ static void command_buildm3u(client_t *client, const char *mount)
|
|||||||
fserve_add_client (client, NULL);
|
fserve_add_client (client, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent) {
|
xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent)
|
||||||
|
{
|
||||||
xmlNodePtr rolenode = xmlNewChild(parent, NULL, XMLSTR("role"), NULL);
|
xmlNodePtr rolenode = xmlNewChild(parent, NULL, XMLSTR("role"), NULL);
|
||||||
char idbuf[32];
|
char idbuf[32];
|
||||||
|
|
||||||
@ -800,7 +804,8 @@ xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent) {
|
|||||||
return rolenode;
|
return rolenode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_manageauth(client_t *client, int response) {
|
static void command_manageauth(client_t *client, int response)
|
||||||
|
{
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlNodePtr node, rolenode, usersnode, msgnode;
|
xmlNodePtr node, rolenode, usersnode, msgnode;
|
||||||
const char *action = NULL;
|
const char *action = NULL;
|
||||||
@ -814,8 +819,7 @@ static void command_manageauth(client_t *client, int response) {
|
|||||||
ice_config_t *config = config_get_config();
|
ice_config_t *config = config_get_config();
|
||||||
auth_t *auth;
|
auth_t *auth;
|
||||||
|
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
/* get id */
|
/* get id */
|
||||||
COMMAND_REQUIRE(client, "id", idstring);
|
COMMAND_REQUIRE(client, "id", idstring);
|
||||||
id = atol(idstring);
|
id = atol(idstring);
|
||||||
@ -848,8 +852,7 @@ static void command_manageauth(client_t *client, int response) {
|
|||||||
if (action == NULL)
|
if (action == NULL)
|
||||||
action = "list";
|
action = "list";
|
||||||
|
|
||||||
if (!strcmp(action, "add"))
|
if (!strcmp(action, "add")) {
|
||||||
{
|
|
||||||
const char *password = NULL;
|
const char *password = NULL;
|
||||||
COMMAND_OPTIONAL(client, "password", password);
|
COMMAND_OPTIONAL(client, "password", password);
|
||||||
|
|
||||||
@ -872,8 +875,7 @@ static void command_manageauth(client_t *client, int response) {
|
|||||||
message = strdup("User already exists - not added");
|
message = strdup("User already exists - not added");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!strcmp(action, "delete"))
|
if (!strcmp(action, "delete")) {
|
||||||
{
|
|
||||||
if (username == NULL) {
|
if (username == NULL) {
|
||||||
ICECAST_LOG_WARN("manage auth request delete for %lu but no username", id);
|
ICECAST_LOG_WARN("manage auth request delete for %lu but no username", id);
|
||||||
break;
|
break;
|
||||||
@ -913,8 +915,8 @@ static void command_manageauth(client_t *client, int response) {
|
|||||||
auth_release(auth);
|
auth_release(auth);
|
||||||
|
|
||||||
admin_send_response(doc, client, response,
|
admin_send_response(doc, client, response,
|
||||||
MANAGEAUTH_TRANSFORMED_REQUEST);
|
MANAGEAUTH_TRANSFORMED_REQUEST);
|
||||||
free (message);
|
free(message);
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
return;
|
return;
|
||||||
} while (0);
|
} while (0);
|
||||||
@ -924,8 +926,9 @@ static void command_manageauth(client_t *client, int response) {
|
|||||||
client_send_error(client, error_code, 0, error_message);
|
client_send_error(client, error_code, 0, error_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_kill_source(client_t *client, source_t *source,
|
static void command_kill_source(client_t *client,
|
||||||
int response)
|
source_t *source,
|
||||||
|
int response)
|
||||||
{
|
{
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlNodePtr node;
|
xmlNodePtr node;
|
||||||
@ -943,8 +946,9 @@ static void command_kill_source(client_t *client, source_t *source,
|
|||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_kill_client(client_t *client, source_t *source,
|
static void command_kill_client(client_t *client,
|
||||||
int response)
|
source_t *source,
|
||||||
|
int response)
|
||||||
{
|
{
|
||||||
const char *idtext;
|
const char *idtext;
|
||||||
int id;
|
int id;
|
||||||
@ -959,7 +963,7 @@ static void command_kill_client(client_t *client, source_t *source,
|
|||||||
|
|
||||||
listener = source_find_client(source, id);
|
listener = source_find_client(source, id);
|
||||||
|
|
||||||
doc = xmlNewDoc (XMLSTR("1.0"));
|
doc = xmlNewDoc(XMLSTR("1.0"));
|
||||||
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
|
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
|
||||||
xmlDocSetRootElement(doc, node);
|
xmlDocSetRootElement(doc, node);
|
||||||
ICECAST_LOG_DEBUG("Response is %d", response);
|
ICECAST_LOG_DEBUG("Response is %d", response);
|
||||||
@ -987,8 +991,9 @@ static void command_kill_client(client_t *client, source_t *source,
|
|||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_fallback(client_t *client, source_t *source,
|
static void command_fallback(client_t *client,
|
||||||
int response)
|
source_t *source,
|
||||||
|
int response)
|
||||||
{
|
{
|
||||||
const char *fallback;
|
const char *fallback;
|
||||||
char *old;
|
char *old;
|
||||||
@ -1004,8 +1009,9 @@ static void command_fallback(client_t *client, source_t *source,
|
|||||||
html_success(client, "Fallback configured");
|
html_success(client, "Fallback configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_metadata(client_t *client, source_t *source,
|
static void command_metadata(client_t *client,
|
||||||
int response)
|
source_t *source,
|
||||||
|
int response)
|
||||||
{
|
{
|
||||||
const char *action;
|
const char *action;
|
||||||
const char *song, *title, *artist, *charset;
|
const char *song, *title, *artist, *charset;
|
||||||
@ -1015,13 +1021,14 @@ static void command_metadata(client_t *client, source_t *source,
|
|||||||
int same_ip = 1;
|
int same_ip = 1;
|
||||||
|
|
||||||
doc = xmlNewDoc(XMLSTR("1.0"));
|
doc = xmlNewDoc(XMLSTR("1.0"));
|
||||||
node = xmlNewDocNode (doc, NULL, XMLSTR("iceresponse"), NULL);
|
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
|
||||||
xmlDocSetRootElement(doc, node);
|
xmlDocSetRootElement(doc, node);
|
||||||
|
|
||||||
ICECAST_LOG_DEBUG("Got metadata update request");
|
ICECAST_LOG_DEBUG("Got metadata update request");
|
||||||
|
|
||||||
if (source->parser->req_type == httpp_req_put) {
|
if (source->parser->req_type == httpp_req_put) {
|
||||||
ICECAST_LOG_ERROR("Got legacy SOURCE-style metadata update command on source connected with PUT at mountpoint %s", source->mount);
|
ICECAST_LOG_ERROR("Got legacy SOURCE-style metadata update command on "
|
||||||
|
"source connected with PUT at mountpoint %s", source->mount);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_REQUIRE(client, "mode", action);
|
COMMAND_REQUIRE(client, "mode", action);
|
||||||
@ -1030,43 +1037,34 @@ static void command_metadata(client_t *client, source_t *source,
|
|||||||
COMMAND_OPTIONAL(client, "artist", artist);
|
COMMAND_OPTIONAL(client, "artist", artist);
|
||||||
COMMAND_OPTIONAL(client, "charset", charset);
|
COMMAND_OPTIONAL(client, "charset", charset);
|
||||||
|
|
||||||
if (strcmp (action, "updinfo") != 0)
|
if (strcmp (action, "updinfo") != 0) {
|
||||||
{
|
|
||||||
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("No such action"));
|
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("No such action"));
|
||||||
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("0"));
|
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("0"));
|
||||||
admin_send_response(doc, client, response,
|
admin_send_response(doc, client, response, ADMIN_XSL_RESPONSE);
|
||||||
ADMIN_XSL_RESPONSE);
|
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin = source->format;
|
plugin = source->format;
|
||||||
if (source->client && strcmp (client->con->ip, source->client->con->ip) != 0)
|
if (source->client && strcmp(client->con->ip, source->client->con->ip) != 0)
|
||||||
if (response == RAW && acl_test_admin(client->acl, COMMAND_RAW_METADATA_UPDATE) != ACL_POLICY_ALLOW)
|
if (response == RAW && acl_test_admin(client->acl, COMMAND_RAW_METADATA_UPDATE) != ACL_POLICY_ALLOW)
|
||||||
same_ip = 0;
|
same_ip = 0;
|
||||||
|
|
||||||
if (same_ip && plugin && plugin->set_tag)
|
if (same_ip && plugin && plugin->set_tag) {
|
||||||
{
|
if (song) {
|
||||||
if (song)
|
|
||||||
{
|
|
||||||
plugin->set_tag (plugin, "song", song, charset);
|
plugin->set_tag (plugin, "song", song, charset);
|
||||||
ICECAST_LOG_INFO("Metadata on mountpoint %s changed to \"%s\"", source->mount, song);
|
ICECAST_LOG_INFO("Metadata on mountpoint %s changed to \"%s\"", source->mount, song);
|
||||||
}
|
} else {
|
||||||
else
|
if (artist && title) {
|
||||||
{
|
plugin->set_tag(plugin, "title", title, charset);
|
||||||
if (artist && title)
|
plugin->set_tag(plugin, "artist", artist, charset);
|
||||||
{
|
|
||||||
plugin->set_tag (plugin, "title", title, charset);
|
|
||||||
plugin->set_tag (plugin, "artist", artist, charset);
|
|
||||||
ICECAST_LOG_INFO("Metadata on mountpoint %s changed to \"%s - %s\"",
|
ICECAST_LOG_INFO("Metadata on mountpoint %s changed to \"%s - %s\"",
|
||||||
source->mount, artist, title);
|
source->mount, artist, title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* updates are now done, let them be pushed into the stream */
|
/* updates are now done, let them be pushed into the stream */
|
||||||
plugin->set_tag (plugin, NULL, NULL, NULL);
|
plugin->set_tag (plugin, NULL, NULL, NULL);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
xmlNewChild(node, NULL, XMLSTR("message"),
|
xmlNewChild(node, NULL, XMLSTR("message"),
|
||||||
XMLSTR("Mountpoint will not accept URL updates"));
|
XMLSTR("Mountpoint will not accept URL updates"));
|
||||||
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
|
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
|
||||||
@ -1078,8 +1076,7 @@ static void command_metadata(client_t *client, source_t *source,
|
|||||||
|
|
||||||
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful"));
|
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful"));
|
||||||
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
|
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
|
||||||
admin_send_response(doc, client, response,
|
admin_send_response(doc, client, response, ADMIN_XSL_RESPONSE);
|
||||||
ADMIN_XSL_RESPONSE);
|
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1092,14 +1089,14 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
|
|||||||
ICECAST_LOG_DEBUG("Got shoutcast metadata update request");
|
ICECAST_LOG_DEBUG("Got shoutcast metadata update request");
|
||||||
|
|
||||||
if (source->parser->req_type == httpp_req_put) {
|
if (source->parser->req_type == httpp_req_put) {
|
||||||
ICECAST_LOG_ERROR("Got legacy shoutcast-style metadata update command on source connected with PUT at mountpoint %s", source->mount);
|
ICECAST_LOG_ERROR("Got legacy shoutcast-style metadata update command "
|
||||||
|
"on source connected with PUT at mountpoint %s", source->mount);
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_REQUIRE(client, "mode", action);
|
COMMAND_REQUIRE(client, "mode", action);
|
||||||
COMMAND_REQUIRE(client, "song", value);
|
COMMAND_REQUIRE(client, "song", value);
|
||||||
|
|
||||||
if (strcmp (action, "updinfo") != 0)
|
if (strcmp (action, "updinfo") != 0) {
|
||||||
{
|
|
||||||
client_send_error(client, 400, 0, "No such action");
|
client_send_error(client, 400, 0, "No such action");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1107,22 +1104,20 @@ static void command_shoutcast_metadata(client_t *client, source_t *source)
|
|||||||
if (acl_test_admin(client->acl, COMMAND_RAW_METADATA_UPDATE) != ACL_POLICY_ALLOW)
|
if (acl_test_admin(client->acl, COMMAND_RAW_METADATA_UPDATE) != ACL_POLICY_ALLOW)
|
||||||
same_ip = 0;
|
same_ip = 0;
|
||||||
|
|
||||||
if (same_ip && source->format && source->format->set_tag)
|
if (same_ip && source->format && source->format->set_tag) {
|
||||||
{
|
|
||||||
source->format->set_tag (source->format, "title", value, NULL);
|
source->format->set_tag (source->format, "title", value, NULL);
|
||||||
source->format->set_tag (source->format, NULL, NULL, NULL);
|
source->format->set_tag (source->format, NULL, NULL, NULL);
|
||||||
|
|
||||||
ICECAST_LOG_DEBUG("Metadata on mountpoint %s changed to \"%s\"",
|
ICECAST_LOG_DEBUG("Metadata on mountpoint %s changed to \"%s\"",
|
||||||
source->mount, value);
|
source->mount, value);
|
||||||
html_success(client, "Metadata update successful");
|
html_success(client, "Metadata update successful");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
client_send_error(client, 400, 0, "mountpoint will not accept URL updates");
|
client_send_error(client, 400, 0, "mountpoint will not accept URL updates");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_stats(client_t *client, const char *mount, int response) {
|
static void command_stats(client_t *client, const char *mount, int response)
|
||||||
|
{
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
|
|
||||||
ICECAST_LOG_DEBUG("Stats request, sending xml stats");
|
ICECAST_LOG_DEBUG("Stats request, sending xml stats");
|
||||||
@ -1133,7 +1128,8 @@ static void command_stats(client_t *client, const char *mount, int response) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_queue_reload(client_t *client, int response) {
|
static void command_queue_reload(client_t *client, int response)
|
||||||
|
{
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlNodePtr node;
|
xmlNodePtr node;
|
||||||
|
|
||||||
@ -1156,12 +1152,12 @@ static void command_list_mounts(client_t *client, int response)
|
|||||||
{
|
{
|
||||||
ICECAST_LOG_DEBUG("List mounts request");
|
ICECAST_LOG_DEBUG("List mounts request");
|
||||||
|
|
||||||
if (response == PLAINTEXT)
|
if (response == PLAINTEXT) {
|
||||||
{
|
ssize_t ret = util_http_build_header(client->refbuf->data,
|
||||||
ssize_t ret = util_http_build_header(client->refbuf->data, PER_CLIENT_REFBUF_SIZE, 0,
|
PER_CLIENT_REFBUF_SIZE, 0,
|
||||||
0, 200, NULL,
|
0, 200, NULL,
|
||||||
"text/plain", "utf-8",
|
"text/plain", "utf-8",
|
||||||
"", NULL);
|
"", NULL);
|
||||||
|
|
||||||
if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) {
|
if (ret == -1 || ret >= PER_CLIENT_REFBUF_SIZE) {
|
||||||
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
|
ICECAST_LOG_ERROR("Dropping client as we can not build response headers.");
|
||||||
@ -1174,13 +1170,11 @@ static void command_list_mounts(client_t *client, int response)
|
|||||||
|
|
||||||
client->refbuf->next = stats_get_streams ();
|
client->refbuf->next = stats_get_streams ();
|
||||||
fserve_add_client (client, NULL);
|
fserve_add_client (client, NULL);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
avl_tree_rlock (global.source_tree);
|
avl_tree_rlock(global.source_tree);
|
||||||
doc = admin_build_sourcelist(NULL);
|
doc = admin_build_sourcelist(NULL);
|
||||||
avl_tree_unlock (global.source_tree);
|
avl_tree_unlock(global.source_tree);
|
||||||
|
|
||||||
admin_send_response(doc, client, response,
|
admin_send_response(doc, client, response,
|
||||||
LISTMOUNTS_TRANSFORMED_REQUEST);
|
LISTMOUNTS_TRANSFORMED_REQUEST);
|
||||||
@ -1188,16 +1182,17 @@ static void command_list_mounts(client_t *client, int response)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void command_updatemetadata(client_t *client, source_t *source,
|
static void command_updatemetadata(client_t *client,
|
||||||
int response)
|
source_t *source,
|
||||||
|
int response)
|
||||||
{
|
{
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
xmlNodePtr node, srcnode;
|
xmlNodePtr node, srcnode;
|
||||||
|
|
||||||
doc = xmlNewDoc (XMLSTR("1.0"));
|
doc = xmlNewDoc(XMLSTR("1.0"));
|
||||||
node = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
|
node = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL);
|
||||||
srcnode = xmlNewChild (node, NULL, XMLSTR("source"), NULL);
|
srcnode = xmlNewChild(node, NULL, XMLSTR("source"), NULL);
|
||||||
xmlSetProp (srcnode, XMLSTR("mount"), XMLSTR(source->mount));
|
xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount));
|
||||||
xmlDocSetRootElement(doc, node);
|
xmlDocSetRootElement(doc, node);
|
||||||
|
|
||||||
admin_send_response(doc, client, response,
|
admin_send_response(doc, client, response,
|
||||||
|
22
src/admin.h
22
src/admin.h
@ -28,19 +28,25 @@
|
|||||||
#define ADMINTYPE_HYBRID (ADMINTYPE_GENERAL|ADMINTYPE_MOUNT)
|
#define ADMINTYPE_HYBRID (ADMINTYPE_GENERAL|ADMINTYPE_MOUNT)
|
||||||
|
|
||||||
/* formats */
|
/* formats */
|
||||||
#define RAW 1
|
#define RAW 1
|
||||||
#define TRANSFORMED 2
|
#define TRANSFORMED 2
|
||||||
#define PLAINTEXT 3
|
#define PLAINTEXT 3
|
||||||
|
|
||||||
/* special commands */
|
/* special commands */
|
||||||
#define ADMIN_COMMAND_ERROR (-1)
|
#define ADMIN_COMMAND_ERROR (-1)
|
||||||
#define ADMIN_COMMAND_ANY 0 /* for ACL framework */
|
#define ADMIN_COMMAND_ANY 0 /* for ACL framework */
|
||||||
|
|
||||||
void admin_handle_request(client_t *client, const char *uri);
|
void admin_handle_request(client_t *client, const char *uri);
|
||||||
void admin_send_response(xmlDocPtr doc, client_t *client,
|
|
||||||
int response, const char *xslt_template);
|
|
||||||
|
|
||||||
void admin_add_listeners_to_mount(source_t *source, xmlNodePtr parent, operation_mode mode);
|
void admin_send_response(xmlDocPtr doc,
|
||||||
|
client_t *client,
|
||||||
|
int response,
|
||||||
|
const char *xslt_template);
|
||||||
|
|
||||||
|
void admin_add_listeners_to_mount(source_t *source,
|
||||||
|
xmlNodePtr parent,
|
||||||
|
operation_mode mode);
|
||||||
|
|
||||||
xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent);
|
xmlNodePtr admin_add_role_to_authentication(auth_t *auth, xmlNodePtr parent);
|
||||||
|
|
||||||
int admin_get_command(const char *command);
|
int admin_get_command(const char *command);
|
||||||
|
@ -46,7 +46,7 @@ struct auth_stack_tag {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* code */
|
/* code */
|
||||||
static void __handle_auth_client (auth_t *auth, auth_client *auth_user);
|
static void __handle_auth_client(auth_t *auth, auth_client *auth_user);
|
||||||
|
|
||||||
static mutex_t _auth_lock; /* protects _current_id */
|
static mutex_t _auth_lock; /* protects _current_id */
|
||||||
static volatile unsigned long _current_id = 0;
|
static volatile unsigned long _current_id = 0;
|
||||||
|
25
src/auth.h
25
src/auth.h
@ -118,22 +118,27 @@ typedef struct auth_tag
|
|||||||
typedef struct auth_stack_tag auth_stack_t;
|
typedef struct auth_stack_tag auth_stack_t;
|
||||||
|
|
||||||
/* prototypes for auths that do not need own header file */
|
/* prototypes for auths that do not need own header file */
|
||||||
int auth_get_anonymous_auth (auth_t *auth, config_options_t *options);
|
int auth_get_anonymous_auth(auth_t *auth, config_options_t *options);
|
||||||
int auth_get_static_auth (auth_t *auth, config_options_t *options);
|
int auth_get_static_auth(auth_t *auth, config_options_t *options);
|
||||||
int auth_get_url_auth (auth_t *authenticator, config_options_t *options);
|
int auth_get_url_auth(auth_t *authenticator, config_options_t *options);
|
||||||
int auth_get_htpasswd_auth(auth_t *auth, config_options_t *options);
|
int auth_get_htpasswd_auth(auth_t *auth, config_options_t *options);
|
||||||
|
|
||||||
/* prototypes for auth.c */
|
/* prototypes for auth.c */
|
||||||
void auth_initialise (void);
|
void auth_initialise(void);
|
||||||
void auth_shutdown (void);
|
void auth_shutdown(void);
|
||||||
|
|
||||||
auth_t *auth_get_authenticator (xmlNodePtr node);
|
auth_t *auth_get_authenticator(xmlNodePtr node);
|
||||||
void auth_release (auth_t *authenticator);
|
void auth_release(auth_t *authenticator);
|
||||||
void auth_addref (auth_t *authenticator);
|
void auth_addref(auth_t *authenticator);
|
||||||
|
|
||||||
int auth_release_client(client_t *client);
|
int auth_release_client(client_t *client);
|
||||||
|
|
||||||
void auth_stack_add_client(auth_stack_t *stack, client_t *client, void (*on_result)(client_t *client, void *userdata, auth_result result), void *userdata);
|
void auth_stack_add_client(auth_stack_t *stack,
|
||||||
|
client_t *client,
|
||||||
|
void (*on_result)(client_t *client,
|
||||||
|
void *userdata,
|
||||||
|
auth_result result),
|
||||||
|
void *userdata);
|
||||||
|
|
||||||
void auth_stack_release(auth_stack_t *stack);
|
void auth_stack_release(auth_stack_t *stack);
|
||||||
void auth_stack_addref(auth_stack_t *stack);
|
void auth_stack_addref(auth_stack_t *stack);
|
||||||
|
@ -20,11 +20,13 @@
|
|||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#define CATMODULE "auth_anonymous"
|
#define CATMODULE "auth_anonymous"
|
||||||
|
|
||||||
static auth_result anonymous_auth (auth_client *auth_user) {
|
static auth_result anonymous_auth(auth_client *auth_user)
|
||||||
|
{
|
||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int auth_get_anonymous_auth (auth_t *authenticator, config_options_t *options) {
|
int auth_get_anonymous_auth(auth_t *authenticator, config_options_t *options)
|
||||||
|
{
|
||||||
authenticator->authenticate_client = anonymous_auth;
|
authenticator->authenticate_client = anonymous_auth;
|
||||||
authenticator->immediate = 1;
|
authenticator->immediate = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -45,8 +45,7 @@ static auth_result htpasswd_deleteuser(auth_t *auth, const char *username);
|
|||||||
static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode);
|
static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode);
|
||||||
static int _free_user (void *key);
|
static int _free_user (void *key);
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
char *name;
|
char *name;
|
||||||
char *pass;
|
char *pass;
|
||||||
} htpasswd_user;
|
} htpasswd_user;
|
||||||
@ -58,7 +57,8 @@ typedef struct {
|
|||||||
time_t mtime;
|
time_t mtime;
|
||||||
} htpasswd_auth_state;
|
} htpasswd_auth_state;
|
||||||
|
|
||||||
static void htpasswd_clear(auth_t *self) {
|
static void htpasswd_clear(auth_t *self)
|
||||||
|
{
|
||||||
htpasswd_auth_state *state = self->state;
|
htpasswd_auth_state *state = self->state;
|
||||||
free(state->filename);
|
free(state->filename);
|
||||||
if (state->users)
|
if (state->users)
|
||||||
@ -84,7 +84,7 @@ static char *get_hash(const char *data, int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int compare_users (void *arg, void *a, void *b)
|
static int compare_users(void *arg, void *a, void *b)
|
||||||
{
|
{
|
||||||
htpasswd_user *user1 = (htpasswd_user *)a;
|
htpasswd_user *user1 = (htpasswd_user *)a;
|
||||||
htpasswd_user *user2 = (htpasswd_user *)b;
|
htpasswd_user *user2 = (htpasswd_user *)b;
|
||||||
@ -93,7 +93,7 @@ static int compare_users (void *arg, void *a, void *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _free_user (void *key)
|
static int _free_user(void *key)
|
||||||
{
|
{
|
||||||
htpasswd_user *user = (htpasswd_user *)key;
|
htpasswd_user *user = (htpasswd_user *)key;
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ static int _free_user (void *key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void htpasswd_recheckfile (htpasswd_auth_state *htpasswd)
|
static void htpasswd_recheckfile(htpasswd_auth_state *htpasswd)
|
||||||
{
|
{
|
||||||
FILE *passwdfile;
|
FILE *passwdfile;
|
||||||
avl_tree *new_users;
|
avl_tree *new_users;
|
||||||
@ -114,8 +114,7 @@ static void htpasswd_recheckfile (htpasswd_auth_state *htpasswd)
|
|||||||
|
|
||||||
if (htpasswd->filename == NULL)
|
if (htpasswd->filename == NULL)
|
||||||
return;
|
return;
|
||||||
if (stat (htpasswd->filename, &file_stat) < 0)
|
if (stat (htpasswd->filename, &file_stat) < 0) {
|
||||||
{
|
|
||||||
ICECAST_LOG_WARN("failed to check status of %s", htpasswd->filename);
|
ICECAST_LOG_WARN("failed to check status of %s", htpasswd->filename);
|
||||||
|
|
||||||
/* Create a dummy users tree for things to use later */
|
/* Create a dummy users tree for things to use later */
|
||||||
@ -127,15 +126,13 @@ static void htpasswd_recheckfile (htpasswd_auth_state *htpasswd)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_stat.st_mtime == htpasswd->mtime)
|
if (file_stat.st_mtime == htpasswd->mtime) {
|
||||||
{
|
|
||||||
/* common case, no update to file */
|
/* common case, no update to file */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ICECAST_LOG_INFO("re-reading htpasswd file \"%s\"", htpasswd->filename);
|
ICECAST_LOG_INFO("re-reading htpasswd file \"%s\"", htpasswd->filename);
|
||||||
passwdfile = fopen (htpasswd->filename, "rb");
|
passwdfile = fopen (htpasswd->filename, "rb");
|
||||||
if (passwdfile == NULL)
|
if (passwdfile == NULL) {
|
||||||
{
|
|
||||||
ICECAST_LOG_WARN("Failed to open authentication database \"%s\": %s",
|
ICECAST_LOG_WARN("Failed to open authentication database \"%s\": %s",
|
||||||
htpasswd->filename, strerror(errno));
|
htpasswd->filename, strerror(errno));
|
||||||
return;
|
return;
|
||||||
@ -144,8 +141,7 @@ static void htpasswd_recheckfile (htpasswd_auth_state *htpasswd)
|
|||||||
|
|
||||||
new_users = avl_tree_new (compare_users, NULL);
|
new_users = avl_tree_new (compare_users, NULL);
|
||||||
|
|
||||||
while (get_line(passwdfile, line, MAX_LINE_LEN))
|
while (get_line(passwdfile, line, MAX_LINE_LEN)) {
|
||||||
{
|
|
||||||
int len;
|
int len;
|
||||||
htpasswd_user *entry;
|
htpasswd_user *entry;
|
||||||
|
|
||||||
@ -154,8 +150,7 @@ static void htpasswd_recheckfile (htpasswd_auth_state *htpasswd)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
sep = strrchr (line, ':');
|
sep = strrchr (line, ':');
|
||||||
if (sep == NULL)
|
if (sep == NULL) {
|
||||||
{
|
|
||||||
ICECAST_LOG_WARN("No separator on line %d (%s)", num, htpasswd->filename);
|
ICECAST_LOG_WARN("No separator on line %d (%s)", num, htpasswd->filename);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -196,15 +191,13 @@ static auth_result htpasswd_auth (auth_client *auth_user)
|
|||||||
|
|
||||||
thread_rwlock_rlock (&htpasswd->file_rwlock);
|
thread_rwlock_rlock (&htpasswd->file_rwlock);
|
||||||
entry.name = client->username;
|
entry.name = client->username;
|
||||||
if (avl_get_by_key (htpasswd->users, &entry, &result) == 0)
|
if (avl_get_by_key (htpasswd->users, &entry, &result) == 0) {
|
||||||
{
|
|
||||||
htpasswd_user *found = result;
|
htpasswd_user *found = result;
|
||||||
char *hashed_pw;
|
char *hashed_pw;
|
||||||
|
|
||||||
thread_rwlock_unlock (&htpasswd->file_rwlock);
|
thread_rwlock_unlock (&htpasswd->file_rwlock);
|
||||||
hashed_pw = get_hash (client->password, strlen (client->password));
|
hashed_pw = get_hash (client->password, strlen (client->password));
|
||||||
if (strcmp (found->pass, hashed_pw) == 0)
|
if (strcmp (found->pass, hashed_pw) == 0) {
|
||||||
{
|
|
||||||
free (hashed_pw);
|
free (hashed_pw);
|
||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
}
|
}
|
||||||
@ -231,19 +224,19 @@ int auth_get_htpasswd_auth (auth_t *authenticator, config_options_t *options)
|
|||||||
state = calloc(1, sizeof(htpasswd_auth_state));
|
state = calloc(1, sizeof(htpasswd_auth_state));
|
||||||
|
|
||||||
while(options) {
|
while(options) {
|
||||||
if(!strcmp(options->name, "filename"))
|
if(!strcmp(options->name, "filename")) {
|
||||||
{
|
|
||||||
free (state->filename);
|
free (state->filename);
|
||||||
state->filename = strdup(options->value);
|
state->filename = strdup(options->value);
|
||||||
}
|
}
|
||||||
options = options->next;
|
options = options->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->filename)
|
if (state->filename) {
|
||||||
ICECAST_LOG_INFO("Configured htpasswd authentication using password file \"%s\"",
|
ICECAST_LOG_INFO("Configured htpasswd authentication using password file \"%s\"",
|
||||||
state->filename);
|
state->filename);
|
||||||
else
|
} else {
|
||||||
ICECAST_LOG_ERROR("No filename given in options for authenticator.");
|
ICECAST_LOG_ERROR("No filename given in options for authenticator.");
|
||||||
|
}
|
||||||
|
|
||||||
authenticator->state = state;
|
authenticator->state = state;
|
||||||
|
|
||||||
@ -267,16 +260,14 @@ static auth_result htpasswd_adduser (auth_t *auth, const char *username, const c
|
|||||||
thread_rwlock_wlock (&state->file_rwlock);
|
thread_rwlock_wlock (&state->file_rwlock);
|
||||||
|
|
||||||
entry.name = (char*)username;
|
entry.name = (char*)username;
|
||||||
if (avl_get_by_key (state->users, &entry, &result) == 0)
|
if (avl_get_by_key (state->users, &entry, &result) == 0) {
|
||||||
{
|
|
||||||
thread_rwlock_unlock (&state->file_rwlock);
|
thread_rwlock_unlock (&state->file_rwlock);
|
||||||
return AUTH_USEREXISTS;
|
return AUTH_USEREXISTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
passwdfile = fopen(state->filename, "ab");
|
passwdfile = fopen(state->filename, "ab");
|
||||||
|
|
||||||
if (passwdfile == NULL)
|
if (passwdfile == NULL) {
|
||||||
{
|
|
||||||
thread_rwlock_unlock (&state->file_rwlock);
|
thread_rwlock_unlock (&state->file_rwlock);
|
||||||
ICECAST_LOG_WARN("Failed to open authentication database \"%s\": %s",
|
ICECAST_LOG_WARN("Failed to open authentication database \"%s\": %s",
|
||||||
state->filename, strerror(errno));
|
state->filename, strerror(errno));
|
||||||
@ -320,8 +311,7 @@ static auth_result htpasswd_deleteuser(auth_t *auth, const char *username)
|
|||||||
tmpfile_len = strlen(state->filename) + 6;
|
tmpfile_len = strlen(state->filename) + 6;
|
||||||
tmpfile = calloc(1, tmpfile_len);
|
tmpfile = calloc(1, tmpfile_len);
|
||||||
snprintf (tmpfile, tmpfile_len, "%s.tmp", state->filename);
|
snprintf (tmpfile, tmpfile_len, "%s.tmp", state->filename);
|
||||||
if (stat (tmpfile, &file_info) == 0)
|
if (stat (tmpfile, &file_info) == 0) {
|
||||||
{
|
|
||||||
ICECAST_LOG_WARN("temp file \"%s\" exists, rejecting operation", tmpfile);
|
ICECAST_LOG_WARN("temp file \"%s\" exists, rejecting operation", tmpfile);
|
||||||
free (tmpfile);
|
free (tmpfile);
|
||||||
fclose (passwdfile);
|
fclose (passwdfile);
|
||||||
@ -369,8 +359,7 @@ static auth_result htpasswd_deleteuser(auth_t *auth, const char *username)
|
|||||||
if (remove(state->filename) != 0) {
|
if (remove(state->filename) != 0) {
|
||||||
ICECAST_LOG_ERROR("Problem moving temp authentication file to original \"%s\" - \"%s\": %s",
|
ICECAST_LOG_ERROR("Problem moving temp authentication file to original \"%s\" - \"%s\": %s",
|
||||||
tmpfile, state->filename, strerror(errno));
|
tmpfile, state->filename, strerror(errno));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (rename(tmpfile, state->filename) != 0) {
|
if (rename(tmpfile, state->filename) != 0) {
|
||||||
ICECAST_LOG_ERROR("Problem moving temp authentication file to original \"%s\" - \"%s\": %s",
|
ICECAST_LOG_ERROR("Problem moving temp authentication file to original \"%s\" - \"%s\": %s",
|
||||||
tmpfile, state->filename, strerror(errno));
|
tmpfile, state->filename, strerror(errno));
|
||||||
@ -392,19 +381,18 @@ static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode)
|
|||||||
|
|
||||||
state = auth->state;
|
state = auth->state;
|
||||||
|
|
||||||
htpasswd_recheckfile (state);
|
htpasswd_recheckfile(state);
|
||||||
|
|
||||||
thread_rwlock_rlock (&state->file_rwlock);
|
thread_rwlock_rlock(&state->file_rwlock);
|
||||||
node = avl_get_first (state->users);
|
node = avl_get_first(state->users);
|
||||||
while (node)
|
while (node) {
|
||||||
{
|
|
||||||
htpasswd_user *user = (htpasswd_user *)node->key;
|
htpasswd_user *user = (htpasswd_user *)node->key;
|
||||||
newnode = xmlNewChild (srcnode, NULL, XMLSTR("user"), NULL);
|
newnode = xmlNewChild(srcnode, NULL, XMLSTR("user"), NULL);
|
||||||
xmlNewChild(newnode, NULL, XMLSTR("username"), XMLSTR(user->name));
|
xmlNewChild(newnode, NULL, XMLSTR("username"), XMLSTR(user->name));
|
||||||
xmlNewChild(newnode, NULL, XMLSTR("password"), XMLSTR(user->pass));
|
xmlNewChild(newnode, NULL, XMLSTR("password"), XMLSTR(user->pass));
|
||||||
node = avl_get_next (node);
|
node = avl_get_next(node);
|
||||||
}
|
}
|
||||||
thread_rwlock_unlock (&state->file_rwlock);
|
thread_rwlock_unlock(&state->file_rwlock);
|
||||||
|
|
||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,11 @@ typedef struct auth_static {
|
|||||||
char *password;
|
char *password;
|
||||||
} auth_static_t;
|
} auth_static_t;
|
||||||
|
|
||||||
static auth_result static_auth (auth_client *auth_user) {
|
static auth_result static_auth(auth_client *auth_user)
|
||||||
client_t *client = auth_user->client;
|
{
|
||||||
auth_t *auth = client->auth;
|
client_t *client = auth_user->client;
|
||||||
auth_static_t *auth_info = auth->state;
|
auth_t *auth = client->auth;
|
||||||
|
auth_static_t *auth_info = auth->state;
|
||||||
|
|
||||||
if (auth_info->username) {
|
if (auth_info->username) {
|
||||||
if (!client->username)
|
if (!client->username)
|
||||||
@ -49,17 +50,21 @@ static auth_result static_auth (auth_client *auth_user) {
|
|||||||
return AUTH_FAILED;
|
return AUTH_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_auth (auth_t *auth) {
|
static void clear_auth (auth_t *auth)
|
||||||
|
{
|
||||||
auth_static_t *auth_info = auth->state;
|
auth_static_t *auth_info = auth->state;
|
||||||
if (auth_info->username) free(auth_info->username);
|
if (auth_info->username)
|
||||||
if (auth_info->password) free(auth_info->password);
|
free(auth_info->username);
|
||||||
|
if (auth_info->password)
|
||||||
|
free(auth_info->password);
|
||||||
free(auth_info);
|
free(auth_info);
|
||||||
auth->state = NULL;
|
auth->state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auth_result static_userlist(auth_t *auth, xmlNodePtr srcnode) {
|
static auth_result static_userlist(auth_t *auth, xmlNodePtr srcnode)
|
||||||
|
{
|
||||||
auth_static_t *auth_info = auth->state;
|
auth_static_t *auth_info = auth->state;
|
||||||
xmlNodePtr newnode;
|
xmlNodePtr newnode;
|
||||||
|
|
||||||
newnode = xmlNewChild(srcnode, NULL, XMLSTR("user"), NULL);
|
newnode = xmlNewChild(srcnode, NULL, XMLSTR("user"), NULL);
|
||||||
xmlNewChild(newnode, NULL, XMLSTR("username"), XMLSTR(auth_info->username));
|
xmlNewChild(newnode, NULL, XMLSTR("username"), XMLSTR(auth_info->username));
|
||||||
@ -68,9 +73,10 @@ static auth_result static_userlist(auth_t *auth, xmlNodePtr srcnode) {
|
|||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int auth_get_static_auth (auth_t *authenticator, config_options_t *options) {
|
int auth_get_static_auth (auth_t *authenticator, config_options_t *options)
|
||||||
|
{
|
||||||
auth_static_t *auth_info;
|
auth_static_t *auth_info;
|
||||||
int need_user;
|
int need_user;
|
||||||
|
|
||||||
if (strcmp(authenticator->type, AUTH_TYPE_STATIC) == 0) {
|
if (strcmp(authenticator->type, AUTH_TYPE_STATIC) == 0) {
|
||||||
need_user = 1;
|
need_user = 1;
|
||||||
@ -93,10 +99,12 @@ int auth_get_static_auth (auth_t *authenticator, config_options_t *options) {
|
|||||||
|
|
||||||
while (options) {
|
while (options) {
|
||||||
if (strcmp(options->name, "username") == 0) {
|
if (strcmp(options->name, "username") == 0) {
|
||||||
if (auth_info->username) free(auth_info->username);
|
if (auth_info->username)
|
||||||
|
free(auth_info->username);
|
||||||
auth_info->username = strdup(options->value);
|
auth_info->username = strdup(options->value);
|
||||||
} else if (strcmp(options->name, "password") == 0) {
|
} else if (strcmp(options->name, "password") == 0) {
|
||||||
if (auth_info->password) free(auth_info->password);
|
if (auth_info->password)
|
||||||
|
free(auth_info->password);
|
||||||
auth_info->password = strdup(options->value);
|
auth_info->password = strdup(options->value);
|
||||||
} else {
|
} else {
|
||||||
ICECAST_LOG_ERROR("Unknown option: %s", options->name);
|
ICECAST_LOG_ERROR("Unknown option: %s", options->name);
|
||||||
|
422
src/auth_url.c
422
src/auth_url.c
@ -79,21 +79,21 @@
|
|||||||
#define CATMODULE "auth_url"
|
#define CATMODULE "auth_url"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *pass_headers; // headers passed from client to addurl.
|
char *pass_headers; // headers passed from client to addurl.
|
||||||
char *prefix_headers; // prefix for passed headers.
|
char *prefix_headers; // prefix for passed headers.
|
||||||
char *addurl;
|
char *addurl;
|
||||||
char *removeurl;
|
char *removeurl;
|
||||||
char *addaction;
|
char *addaction;
|
||||||
char *removeaction;
|
char *removeaction;
|
||||||
char *username;
|
char *username;
|
||||||
char *password;
|
char *password;
|
||||||
char *auth_header;
|
char *auth_header;
|
||||||
int auth_header_len;
|
int auth_header_len;
|
||||||
char *timelimit_header;
|
char *timelimit_header;
|
||||||
int timelimit_header_len;
|
int timelimit_header_len;
|
||||||
char *userpwd;
|
char *userpwd;
|
||||||
CURL *handle;
|
CURL *handle;
|
||||||
char errormsg [CURL_ERROR_SIZE];
|
char errormsg[CURL_ERROR_SIZE];
|
||||||
auth_result result;
|
auth_result result;
|
||||||
} auth_url;
|
} auth_url;
|
||||||
|
|
||||||
@ -131,31 +131,32 @@ static int my_getpass(void *client, char *prompt, char *buffer, int buflen)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream)
|
static size_t handle_returned_header(void *ptr,
|
||||||
|
size_t size,
|
||||||
|
size_t nmemb,
|
||||||
|
void *stream)
|
||||||
{
|
{
|
||||||
auth_client *auth_user = stream;
|
auth_client *auth_user = stream;
|
||||||
unsigned bytes = size * nmemb;
|
unsigned bytes = size * nmemb;
|
||||||
client_t *client = auth_user->client;
|
client_t *client = auth_user->client;
|
||||||
|
|
||||||
if (client)
|
if (client) {
|
||||||
{
|
|
||||||
auth_t *auth = client->auth;
|
auth_t *auth = client->auth;
|
||||||
auth_url *url = auth->state;
|
auth_url *url = auth->state;
|
||||||
if (strncasecmp (ptr, url->auth_header, url->auth_header_len) == 0)
|
if (strncasecmp(ptr, url->auth_header, url->auth_header_len) == 0)
|
||||||
url->result = AUTH_OK;
|
url->result = AUTH_OK;
|
||||||
if (strncasecmp (ptr, url->timelimit_header, url->timelimit_header_len) == 0)
|
if (strncasecmp(ptr, url->timelimit_header,
|
||||||
{
|
url->timelimit_header_len) == 0) {
|
||||||
unsigned int limit = 0;
|
unsigned int limit = 0;
|
||||||
sscanf ((char *)ptr+url->timelimit_header_len, "%u\r\n", &limit);
|
sscanf ((char *)ptr+url->timelimit_header_len, "%u\r\n", &limit);
|
||||||
client->con->discon_time = time(NULL) + limit;
|
client->con->discon_time = time(NULL) + limit;
|
||||||
}
|
}
|
||||||
if (strncasecmp (ptr, "icecast-auth-message: ", 22) == 0)
|
if (strncasecmp (ptr, "icecast-auth-message: ", 22) == 0) {
|
||||||
{
|
|
||||||
char *eol;
|
char *eol;
|
||||||
snprintf (url->errormsg, sizeof (url->errormsg), "%s", (char*)ptr+22);
|
snprintf(url->errormsg, sizeof(url->errormsg), "%s", (char*)ptr+22);
|
||||||
eol = strchr (url->errormsg, '\r');
|
eol = strchr(url->errormsg, '\r');
|
||||||
if (eol == NULL)
|
if (eol == NULL)
|
||||||
eol = strchr (url->errormsg, '\n');
|
eol = strchr(url->errormsg, '\n');
|
||||||
if (eol)
|
if (eol)
|
||||||
*eol = '\0';
|
*eol = '\0';
|
||||||
}
|
}
|
||||||
@ -165,273 +166,291 @@ static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* capture returned data, but don't do anything with it */
|
/* capture returned data, but don't do anything with it */
|
||||||
static size_t handle_returned_data (void *ptr, size_t size, size_t nmemb, void *stream)
|
static size_t handle_returned_data(void *ptr,
|
||||||
|
size_t size,
|
||||||
|
size_t nmemb,
|
||||||
|
void *stream)
|
||||||
{
|
{
|
||||||
return (int)(size*nmemb);
|
return (int)(size*nmemb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static auth_result url_remove_client (auth_client *auth_user)
|
static auth_result url_remove_client(auth_client *auth_user)
|
||||||
{
|
{
|
||||||
client_t *client = auth_user->client;
|
client_t *client = auth_user->client;
|
||||||
auth_t *auth = client->auth;
|
auth_t *auth = client->auth;
|
||||||
auth_url *url = auth->state;
|
auth_url *url = auth->state;
|
||||||
time_t duration = time(NULL) - client->con->con_time;
|
time_t duration = time(NULL) - client->con->con_time;
|
||||||
char *username, *password, *mount, *server;
|
char *username,
|
||||||
const char *mountreq;
|
*password,
|
||||||
ice_config_t *config;
|
*mount,
|
||||||
int port;
|
*server;
|
||||||
char *userpwd = NULL, post [4096];
|
const char *mountreq;
|
||||||
const char *agent;
|
ice_config_t *config;
|
||||||
char *user_agent, *ipaddr;
|
int port;
|
||||||
|
char *userpwd = NULL,
|
||||||
|
post[4096];
|
||||||
|
const char *agent;
|
||||||
|
char *user_agent,
|
||||||
|
*ipaddr;
|
||||||
|
|
||||||
if (url->removeurl == NULL)
|
if (url->removeurl == NULL)
|
||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
|
|
||||||
config = config_get_config ();
|
config = config_get_config();
|
||||||
server = util_url_escape (config->hostname);
|
server = util_url_escape(config->hostname);
|
||||||
port = config->port;
|
port = config->port;
|
||||||
config_release_config ();
|
config_release_config();
|
||||||
|
|
||||||
agent = httpp_getvar (client->parser, "user-agent");
|
agent = httpp_getvar(client->parser, "user-agent");
|
||||||
if (agent)
|
if (agent) {
|
||||||
user_agent = util_url_escape (agent);
|
user_agent = util_url_escape(agent);
|
||||||
else
|
} else {
|
||||||
user_agent = strdup ("-");
|
user_agent = strdup("-");
|
||||||
|
}
|
||||||
|
|
||||||
if (client->username)
|
if (client->username) {
|
||||||
username = util_url_escape (client->username);
|
username = util_url_escape(client->username);
|
||||||
else
|
} else {
|
||||||
username = strdup ("");
|
username = strdup("");
|
||||||
|
}
|
||||||
|
|
||||||
if (client->password)
|
if (client->password) {
|
||||||
password = util_url_escape (client->password);
|
password = util_url_escape(client->password);
|
||||||
else
|
} else {
|
||||||
password = strdup ("");
|
password = strdup("");
|
||||||
|
}
|
||||||
|
|
||||||
/* get the full uri (with query params if available) */
|
/* get the full uri (with query params if available) */
|
||||||
mountreq = httpp_getvar (client->parser, HTTPP_VAR_RAWURI);
|
mountreq = httpp_getvar(client->parser, HTTPP_VAR_RAWURI);
|
||||||
if (mountreq == NULL)
|
if (mountreq == NULL)
|
||||||
mountreq = httpp_getvar (client->parser, HTTPP_VAR_URI);
|
mountreq = httpp_getvar(client->parser, HTTPP_VAR_URI);
|
||||||
mount = util_url_escape (mountreq);
|
mount = util_url_escape(mountreq);
|
||||||
ipaddr = util_url_escape (client->con->ip);
|
ipaddr = util_url_escape(client->con->ip);
|
||||||
|
|
||||||
snprintf (post, sizeof (post),
|
snprintf(post, sizeof (post),
|
||||||
"action=%s&server=%s&port=%d&client=%lu&mount=%s"
|
"action=%s&server=%s&port=%d&client=%lu&mount=%s"
|
||||||
"&user=%s&pass=%s&duration=%lu&ip=%s&agent=%s",
|
"&user=%s&pass=%s&duration=%lu&ip=%s&agent=%s",
|
||||||
url->removeaction, /* already escaped */
|
url->removeaction, /* already escaped */
|
||||||
server, port, client->con->id, mount, username,
|
server, port, client->con->id, mount, username,
|
||||||
password, (long unsigned)duration, ipaddr, user_agent);
|
password, (long unsigned)duration, ipaddr, user_agent);
|
||||||
free (server);
|
|
||||||
free (mount);
|
|
||||||
free (username);
|
|
||||||
free (password);
|
|
||||||
free (ipaddr);
|
|
||||||
free (user_agent);
|
|
||||||
|
|
||||||
if (strchr (url->removeurl, '@') == NULL)
|
free(server);
|
||||||
{
|
free(mount);
|
||||||
if (url->userpwd)
|
free(username);
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd);
|
free(password);
|
||||||
else
|
free(ipaddr);
|
||||||
{
|
free(user_agent);
|
||||||
|
|
||||||
|
if (strchr (url->removeurl, '@') == NULL) {
|
||||||
|
if (url->userpwd) {
|
||||||
|
curl_easy_setopt(url->handle, CURLOPT_USERPWD, url->userpwd);
|
||||||
|
} else {
|
||||||
/* auth'd requests may not have a user/pass, but may use query args */
|
/* auth'd requests may not have a user/pass, but may use query args */
|
||||||
if (client->username && client->password)
|
if (client->username && client->password) {
|
||||||
{
|
size_t len = strlen(client->username) +
|
||||||
size_t len = strlen (client->username) + strlen (client->password) + 2;
|
strlen(client->password) + 2;
|
||||||
userpwd = malloc (len);
|
userpwd = malloc(len);
|
||||||
snprintf (userpwd, len, "%s:%s", client->username, client->password);
|
snprintf(userpwd, len, "%s:%s",
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, userpwd);
|
client->username, client->password);
|
||||||
|
curl_easy_setopt(url->handle, CURLOPT_USERPWD, userpwd);
|
||||||
|
} else {
|
||||||
|
curl_easy_setopt(url->handle, CURLOPT_USERPWD, "");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* url has user/pass but libcurl may need to clear any existing settings */
|
/* url has user/pass but libcurl may need to clear any existing settings */
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
|
curl_easy_setopt(url->handle, CURLOPT_USERPWD, "");
|
||||||
}
|
}
|
||||||
curl_easy_setopt (url->handle, CURLOPT_URL, url->removeurl);
|
curl_easy_setopt(url->handle, CURLOPT_URL, url->removeurl);
|
||||||
curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
|
curl_easy_setopt(url->handle, CURLOPT_POSTFIELDS, post);
|
||||||
curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
|
curl_easy_setopt(url->handle, CURLOPT_WRITEHEADER, auth_user);
|
||||||
|
|
||||||
if (curl_easy_perform (url->handle))
|
if (curl_easy_perform (url->handle))
|
||||||
ICECAST_LOG_WARN("auth to server %s failed with %s", url->removeurl, url->errormsg);
|
ICECAST_LOG_WARN("auth to server %s failed with %s",
|
||||||
|
url->removeurl, url->errormsg);
|
||||||
|
|
||||||
free (userpwd);
|
free(userpwd);
|
||||||
|
|
||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static auth_result url_add_client (auth_client *auth_user)
|
static auth_result url_add_client(auth_client *auth_user)
|
||||||
{
|
{
|
||||||
client_t *client = auth_user->client;
|
client_t *client = auth_user->client;
|
||||||
auth_t *auth = client->auth;
|
auth_t *auth = client->auth;
|
||||||
auth_url *url = auth->state;
|
auth_url *url = auth->state;
|
||||||
int res = 0, port;
|
int res = 0,
|
||||||
const char *agent;
|
port;
|
||||||
char *user_agent, *username, *password;
|
const char *agent;
|
||||||
const char *mountreq;
|
char *user_agent,
|
||||||
char *mount, *ipaddr, *server;
|
*username,
|
||||||
ice_config_t *config;
|
*password;
|
||||||
char *userpwd = NULL, post [4096];
|
const char *mountreq;
|
||||||
ssize_t post_offset;
|
char *mount,
|
||||||
char *pass_headers, *cur_header, *next_header;
|
*ipaddr,
|
||||||
const char *header_val;
|
*server;
|
||||||
char *header_valesc;
|
ice_config_t *config;
|
||||||
|
char *userpwd = NULL, post [4096];
|
||||||
|
ssize_t post_offset;
|
||||||
|
char *pass_headers,
|
||||||
|
*cur_header,
|
||||||
|
*next_header;
|
||||||
|
const char *header_val;
|
||||||
|
char *header_valesc;
|
||||||
|
|
||||||
if (url->addurl == NULL)
|
if (url->addurl == NULL)
|
||||||
return AUTH_OK;
|
return AUTH_OK;
|
||||||
|
|
||||||
config = config_get_config ();
|
config = config_get_config();
|
||||||
server = util_url_escape (config->hostname);
|
server = util_url_escape(config->hostname);
|
||||||
port = config->port;
|
port = config->port;
|
||||||
config_release_config ();
|
config_release_config();
|
||||||
|
|
||||||
agent = httpp_getvar (client->parser, "user-agent");
|
agent = httpp_getvar(client->parser, "user-agent");
|
||||||
if (agent)
|
if (agent) {
|
||||||
user_agent = util_url_escape (agent);
|
user_agent = util_url_escape(agent);
|
||||||
else
|
} else {
|
||||||
user_agent = strdup ("-");
|
user_agent = strdup("-");
|
||||||
|
}
|
||||||
|
|
||||||
if (client->username)
|
if (client->username) {
|
||||||
username = util_url_escape (client->username);
|
username = util_url_escape(client->username);
|
||||||
else
|
} else {
|
||||||
username = strdup ("");
|
username = strdup("");
|
||||||
|
}
|
||||||
|
|
||||||
if (client->password)
|
if (client->password) {
|
||||||
password = util_url_escape (client->password);
|
password = util_url_escape(client->password);
|
||||||
else
|
} else {
|
||||||
password = strdup ("");
|
password = strdup("");
|
||||||
|
}
|
||||||
|
|
||||||
/* get the full uri (with query params if available) */
|
/* get the full uri (with query params if available) */
|
||||||
mountreq = httpp_getvar (client->parser, HTTPP_VAR_RAWURI);
|
mountreq = httpp_getvar(client->parser, HTTPP_VAR_RAWURI);
|
||||||
if (mountreq == NULL)
|
if (mountreq == NULL)
|
||||||
mountreq = httpp_getvar (client->parser, HTTPP_VAR_URI);
|
mountreq = httpp_getvar(client->parser, HTTPP_VAR_URI);
|
||||||
mount = util_url_escape (mountreq);
|
mount = util_url_escape(mountreq);
|
||||||
ipaddr = util_url_escape (client->con->ip);
|
ipaddr = util_url_escape(client->con->ip);
|
||||||
|
|
||||||
post_offset = snprintf (post, sizeof (post),
|
post_offset = snprintf(post, sizeof (post),
|
||||||
"action=%s&server=%s&port=%d&client=%lu&mount=%s"
|
"action=%s&server=%s&port=%d&client=%lu&mount=%s"
|
||||||
"&user=%s&pass=%s&ip=%s&agent=%s",
|
"&user=%s&pass=%s&ip=%s&agent=%s",
|
||||||
url->addaction, /* already escaped */
|
url->addaction, /* already escaped */
|
||||||
server, port, client->con->id, mount, username,
|
server, port, client->con->id, mount, username,
|
||||||
password, ipaddr, user_agent);
|
password, ipaddr, user_agent);
|
||||||
free (server);
|
|
||||||
free (mount);
|
free(server);
|
||||||
free (user_agent);
|
free(mount);
|
||||||
free (username);
|
free(user_agent);
|
||||||
free (password);
|
free(username);
|
||||||
free (ipaddr);
|
free(password);
|
||||||
|
free(ipaddr);
|
||||||
|
|
||||||
pass_headers = NULL;
|
pass_headers = NULL;
|
||||||
if (url->pass_headers)
|
if (url->pass_headers)
|
||||||
pass_headers = strdup (url->pass_headers);
|
pass_headers = strdup(url->pass_headers);
|
||||||
if (pass_headers)
|
if (pass_headers) {
|
||||||
{
|
|
||||||
cur_header = pass_headers;
|
cur_header = pass_headers;
|
||||||
while (cur_header)
|
while (cur_header) {
|
||||||
{
|
next_header = strstr(cur_header, ",");
|
||||||
next_header = strstr (cur_header, ",");
|
if (next_header) {
|
||||||
if (next_header)
|
|
||||||
{
|
|
||||||
*next_header=0;
|
*next_header=0;
|
||||||
next_header++;
|
next_header++;
|
||||||
}
|
}
|
||||||
|
|
||||||
header_val = httpp_getvar (client->parser, cur_header);
|
header_val = httpp_getvar (client->parser, cur_header);
|
||||||
if (header_val)
|
if (header_val) {
|
||||||
{
|
|
||||||
header_valesc = util_url_escape (header_val);
|
header_valesc = util_url_escape (header_val);
|
||||||
post_offset += snprintf (post+post_offset, sizeof (post)-post_offset, "&%s%s=%s",
|
post_offset += snprintf(post + post_offset,
|
||||||
url->prefix_headers ? url->prefix_headers : "",
|
sizeof(post) - post_offset,
|
||||||
cur_header, header_valesc);
|
"&%s%s=%s",
|
||||||
free (header_valesc);
|
url->prefix_headers ? url->prefix_headers : "",
|
||||||
|
cur_header, header_valesc);
|
||||||
|
free(header_valesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_header = next_header;
|
cur_header = next_header;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strchr (url->addurl, '@') == NULL)
|
if (strchr(url->addurl, '@') == NULL) {
|
||||||
{
|
if (url->userpwd) {
|
||||||
if (url->userpwd)
|
curl_easy_setopt(url->handle, CURLOPT_USERPWD, url->userpwd);
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd);
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* auth'd requests may not have a user/pass, but may use query args */
|
/* auth'd requests may not have a user/pass, but may use query args */
|
||||||
if (client->username && client->password)
|
if (client->username && client->password) {
|
||||||
{
|
size_t len = strlen(client->username) + strlen(client->password) + 2;
|
||||||
size_t len = strlen (client->username) + strlen (client->password) + 2;
|
|
||||||
userpwd = malloc (len);
|
userpwd = malloc (len);
|
||||||
snprintf (userpwd, len, "%s:%s", client->username, client->password);
|
snprintf(userpwd, len, "%s:%s",
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, userpwd);
|
client->username, client->password);
|
||||||
}
|
curl_easy_setopt(url->handle, CURLOPT_USERPWD, userpwd);
|
||||||
else
|
} else {
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
|
curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* url has user/pass but libcurl may need to clear any existing settings */
|
/* url has user/pass but libcurl may need to clear any existing settings */
|
||||||
curl_easy_setopt (url->handle, CURLOPT_USERPWD, "");
|
curl_easy_setopt(url->handle, CURLOPT_USERPWD, "");
|
||||||
}
|
}
|
||||||
curl_easy_setopt (url->handle, CURLOPT_URL, url->addurl);
|
curl_easy_setopt(url->handle, CURLOPT_URL, url->addurl);
|
||||||
curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post);
|
curl_easy_setopt(url->handle, CURLOPT_POSTFIELDS, post);
|
||||||
curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user);
|
curl_easy_setopt(url->handle, CURLOPT_WRITEHEADER, auth_user);
|
||||||
url->errormsg[0] = '\0';
|
url->errormsg[0] = '\0';
|
||||||
|
|
||||||
url->result = AUTH_FAILED;
|
url->result = AUTH_FAILED;
|
||||||
res = curl_easy_perform (url->handle);
|
res = curl_easy_perform(url->handle);
|
||||||
|
|
||||||
free (userpwd);
|
free(userpwd);
|
||||||
|
|
||||||
if (res)
|
if (res) {
|
||||||
{
|
ICECAST_LOG_WARN("auth to server %s failed with %s",
|
||||||
ICECAST_LOG_WARN("auth to server %s failed with %s", url->addurl, url->errormsg);
|
url->addurl, url->errormsg);
|
||||||
return AUTH_FAILED;
|
return AUTH_FAILED;
|
||||||
}
|
}
|
||||||
/* we received a response, lets see what it is */
|
/* we received a response, lets see what it is */
|
||||||
if (url->result == AUTH_FAILED) {
|
if (url->result == AUTH_FAILED) {
|
||||||
ICECAST_LOG_INFO("client auth (%s) failed with \"%s\"", url->addurl, url->errormsg);
|
ICECAST_LOG_INFO("client auth (%s) failed with \"%s\"",
|
||||||
|
url->addurl, url->errormsg);
|
||||||
}
|
}
|
||||||
return url->result;
|
return url->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auth_result auth_url_adduser(auth_t *auth, const char *username, const char *password)
|
static auth_result auth_url_adduser(auth_t *auth,
|
||||||
|
const char *username,
|
||||||
|
const char *password)
|
||||||
{
|
{
|
||||||
return AUTH_FAILED;
|
return AUTH_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auth_result auth_url_deleteuser (auth_t *auth, const char *username)
|
static auth_result auth_url_deleteuser(auth_t *auth, const char *username)
|
||||||
{
|
{
|
||||||
return AUTH_FAILED;
|
return AUTH_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auth_result auth_url_listuser (auth_t *auth, xmlNodePtr srcnode)
|
static auth_result auth_url_listuser(auth_t *auth, xmlNodePtr srcnode)
|
||||||
{
|
{
|
||||||
return AUTH_FAILED;
|
return AUTH_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int auth_get_url_auth(auth_t *authenticator, config_options_t *options)
|
int auth_get_url_auth(auth_t *authenticator, config_options_t *options)
|
||||||
{
|
{
|
||||||
auth_url *url_info;
|
auth_url *url_info;
|
||||||
const char * addaction = "listener_add";
|
const char *addaction = "listener_add";
|
||||||
const char * removeaction = "listener_remove";
|
const char *removeaction = "listener_remove";
|
||||||
|
|
||||||
authenticator->free = auth_url_clear;
|
authenticator->free = auth_url_clear;
|
||||||
authenticator->adduser = auth_url_adduser;
|
authenticator->adduser = auth_url_adduser;
|
||||||
authenticator->deleteuser = auth_url_deleteuser;
|
authenticator->deleteuser = auth_url_deleteuser;
|
||||||
authenticator->listuser = auth_url_listuser;
|
authenticator->listuser = auth_url_listuser;
|
||||||
|
|
||||||
url_info = calloc(1, sizeof(auth_url));
|
url_info = calloc(1, sizeof(auth_url));
|
||||||
authenticator->state = url_info;
|
authenticator->state = url_info;
|
||||||
|
|
||||||
/* default headers */
|
/* default headers */
|
||||||
url_info->auth_header = strdup("icecast-auth-user: 1\r\n");
|
url_info->auth_header = strdup("icecast-auth-user: 1\r\n");
|
||||||
url_info->timelimit_header = strdup("icecast-auth-timelimit:");
|
url_info->timelimit_header = strdup("icecast-auth-timelimit:");
|
||||||
|
|
||||||
/* force auth thread to call function. this makes sure the auth_t is attached to client */
|
/* force auth thread to call function. this makes sure the auth_t is attached to client */
|
||||||
authenticator->authenticate_client = url_add_client;
|
authenticator->authenticate_client = url_add_client;
|
||||||
@ -475,10 +494,9 @@ int auth_get_url_auth(auth_t *authenticator, config_options_t *options)
|
|||||||
url_info->addaction = util_url_escape(addaction);
|
url_info->addaction = util_url_escape(addaction);
|
||||||
url_info->removeaction = util_url_escape(removeaction);
|
url_info->removeaction = util_url_escape(removeaction);
|
||||||
|
|
||||||
url_info->handle = curl_easy_init ();
|
url_info->handle = curl_easy_init();
|
||||||
if (url_info->handle == NULL)
|
if (url_info->handle == NULL) {
|
||||||
{
|
auth_url_clear(authenticator);
|
||||||
auth_url_clear (authenticator);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,22 +505,22 @@ int auth_get_url_auth(auth_t *authenticator, config_options_t *options)
|
|||||||
if (url_info->timelimit_header)
|
if (url_info->timelimit_header)
|
||||||
url_info->timelimit_header_len = strlen (url_info->timelimit_header);
|
url_info->timelimit_header_len = strlen (url_info->timelimit_header);
|
||||||
|
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_USERAGENT, ICECAST_VERSION_STRING);
|
curl_easy_setopt(url_info->handle, CURLOPT_USERAGENT, ICECAST_VERSION_STRING);
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
|
curl_easy_setopt(url_info->handle, CURLOPT_HEADERFUNCTION, handle_returned_header);
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_WRITEFUNCTION, handle_returned_data);
|
curl_easy_setopt(url_info->handle, CURLOPT_WRITEFUNCTION, handle_returned_data);
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_WRITEDATA, url_info->handle);
|
curl_easy_setopt(url_info->handle, CURLOPT_WRITEDATA, url_info->handle);
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_NOSIGNAL, 1L);
|
curl_easy_setopt(url_info->handle, CURLOPT_NOSIGNAL, 1L);
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_TIMEOUT, 15L);
|
curl_easy_setopt(url_info->handle, CURLOPT_TIMEOUT, 15L);
|
||||||
#ifdef CURLOPT_PASSWDFUNCTION
|
#ifdef CURLOPT_PASSWDFUNCTION
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_PASSWDFUNCTION, my_getpass);
|
curl_easy_setopt(url_info->handle, CURLOPT_PASSWDFUNCTION, my_getpass);
|
||||||
#endif
|
#endif
|
||||||
curl_easy_setopt (url_info->handle, CURLOPT_ERRORBUFFER, &url_info->errormsg[0]);
|
curl_easy_setopt(url_info->handle, CURLOPT_ERRORBUFFER, &url_info->errormsg[0]);
|
||||||
|
|
||||||
if (url_info->username && url_info->password)
|
if (url_info->username && url_info->password) {
|
||||||
{
|
int len = strlen(url_info->username) + strlen(url_info->password) + 2;
|
||||||
int len = strlen (url_info->username) + strlen (url_info->password) + 2;
|
url_info->userpwd = malloc(len);
|
||||||
url_info->userpwd = malloc (len);
|
snprintf(url_info->userpwd, len, "%s:%s",
|
||||||
snprintf (url_info->userpwd, len, "%s:%s", url_info->username, url_info->password);
|
url_info->username, url_info->password);
|
||||||
}
|
}
|
||||||
|
|
||||||
ICECAST_LOG_INFO("URL based authentication setup");
|
ICECAST_LOG_INFO("URL based authentication setup");
|
||||||
|
1501
src/cfgfile.c
1501
src/cfgfile.c
File diff suppressed because it is too large
Load Diff
@ -77,32 +77,47 @@ typedef enum _mount_type {
|
|||||||
} mount_type;
|
} mount_type;
|
||||||
|
|
||||||
typedef struct _mount_proxy {
|
typedef struct _mount_proxy {
|
||||||
char *mountname; /* The mountpoint this proxy is used for */
|
/* The mountpoint this proxy is used for */
|
||||||
|
char *mountname;
|
||||||
mount_type mounttype; /* The type of the mount point */
|
/* The type of the mount point */
|
||||||
|
mount_type mounttype;
|
||||||
char *dumpfile; /* Filename to dump this stream to (will be appended). NULL
|
/* Filename to dump this stream to (will be appended).
|
||||||
to not dump. */
|
* NULL to not dump.
|
||||||
char *intro_filename; /* Send contents of file to client before the stream */
|
*/
|
||||||
int fallback_when_full; /* switch new listener to fallback source
|
char *dumpfile;
|
||||||
when max listeners reached */
|
/* Send contents of file to client before the stream */
|
||||||
int max_listeners; /* Max listeners for this mountpoint only. -1 to not
|
char *intro_filename;
|
||||||
limit here (i.e. only use the global limit) */
|
/* Switch new listener to fallback source when max listeners reached */
|
||||||
char *fallback_mount; /* Fallback mountname */
|
int fallback_when_full;
|
||||||
|
/* Max listeners for this mountpoint only.
|
||||||
int fallback_override; /* When this source arrives, do we steal back
|
* -1 to not limit here (i.e. only use the global limit)
|
||||||
clients from the fallback? */
|
*/
|
||||||
int no_mount; /* Do we permit direct requests of this mountpoint? (or only
|
int max_listeners;
|
||||||
indirect, through fallbacks) */
|
/* Fallback mountname */
|
||||||
int burst_size; /* amount to send to a new client if possible, -1 take
|
char *fallback_mount;
|
||||||
* from global setting */
|
/* When this source arrives, do we steal back
|
||||||
|
* clients from the fallback?
|
||||||
|
*/
|
||||||
|
int fallback_override;
|
||||||
|
/* Do we permit direct requests of this mountpoint?
|
||||||
|
* (or only indirect, through fallbacks)
|
||||||
|
*/
|
||||||
|
int no_mount;
|
||||||
|
/* amount to send to a new client if possible, -1 take
|
||||||
|
* from global setting
|
||||||
|
*/
|
||||||
|
int burst_size;
|
||||||
unsigned int queue_size_limit;
|
unsigned int queue_size_limit;
|
||||||
int hidden; /* Do we list this on the xsl pages */
|
/* Do we list this on the xsl pages */
|
||||||
unsigned int source_timeout; /* source timeout in seconds */
|
int hidden;
|
||||||
char *charset; /* character set if not utf8 */
|
/* source timeout in seconds */
|
||||||
int mp3_meta_interval; /* outgoing per-stream metadata interval */
|
unsigned int source_timeout;
|
||||||
|
/* character set if not utf8 */
|
||||||
ice_config_http_header_t *http_headers; /* additional HTTP headers */
|
char *charset;
|
||||||
|
/* outgoing per-stream metadata interval */
|
||||||
|
int mp3_meta_interval;
|
||||||
|
/* additional HTTP headers */
|
||||||
|
ice_config_http_header_t *http_headers;
|
||||||
|
|
||||||
struct event_registration_tag *event;
|
struct event_registration_tag *event;
|
||||||
|
|
||||||
@ -233,8 +248,8 @@ int config_parse_cmdline(int arg, char **argv);
|
|||||||
void config_set_config(ice_config_t *config);
|
void config_set_config(ice_config_t *config);
|
||||||
listener_t *config_clear_listener (listener_t *listener);
|
listener_t *config_clear_listener (listener_t *listener);
|
||||||
void config_clear(ice_config_t *config);
|
void config_clear(ice_config_t *config);
|
||||||
mount_proxy *config_find_mount (ice_config_t *config, const char *mount, mount_type type);
|
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_get_listen_sock(ice_config_t *config, connection_t *con);
|
||||||
|
|
||||||
config_options_t *config_parse_options(xmlNodePtr node);
|
config_options_t *config_parse_options(xmlNodePtr node);
|
||||||
void config_clear_options(config_options_t *options);
|
void config_clear_options(config_options_t *options);
|
||||||
|
24
src/client.c
24
src/client.c
@ -60,9 +60,9 @@ static inline void client_send_500(client_t *client, const char *message);
|
|||||||
*/
|
*/
|
||||||
int client_create(client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
int client_create(client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
||||||
{
|
{
|
||||||
ice_config_t *config;
|
ice_config_t *config;
|
||||||
client_t *client = (client_t *) calloc(1, sizeof(client_t));
|
client_t *client = (client_t *) calloc(1, sizeof(client_t));
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (client == NULL)
|
if (client == NULL)
|
||||||
abort();
|
abort();
|
||||||
@ -70,10 +70,11 @@ int client_create(client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
|||||||
config = config_get_config();
|
config = config_get_config();
|
||||||
|
|
||||||
global.clients++;
|
global.clients++;
|
||||||
if (config->client_limit < global.clients)
|
if (config->client_limit < global.clients) {
|
||||||
ICECAST_LOG_WARN("server client limit reached (%d/%d)", config->client_limit, global.clients);
|
ICECAST_LOG_WARN("server client limit reached (%d/%d)", config->client_limit, global.clients);
|
||||||
else
|
} else {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
config_release_config ();
|
config_release_config ();
|
||||||
|
|
||||||
@ -99,8 +100,7 @@ void client_destroy(client_t *client)
|
|||||||
|
|
||||||
/* release the buffer now, as the buffer could be on the source queue
|
/* release the buffer now, as the buffer could be on the source queue
|
||||||
* and may of disappeared after auth completes */
|
* and may of disappeared after auth completes */
|
||||||
if (client->refbuf)
|
if (client->refbuf) {
|
||||||
{
|
|
||||||
refbuf_release (client->refbuf);
|
refbuf_release (client->refbuf);
|
||||||
client->refbuf = NULL;
|
client->refbuf = NULL;
|
||||||
}
|
}
|
||||||
@ -113,7 +113,6 @@ void client_destroy(client_t *client)
|
|||||||
*/
|
*/
|
||||||
if (client->respcode && client->parser)
|
if (client->respcode && client->parser)
|
||||||
logging_access(client);
|
logging_access(client);
|
||||||
|
|
||||||
if (client->con)
|
if (client->con)
|
||||||
connection_close(client->con);
|
connection_close(client->con);
|
||||||
if (client->parser)
|
if (client->parser)
|
||||||
@ -141,14 +140,12 @@ int client_read_bytes(client_t *client, void *buf, unsigned len)
|
|||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
|
|
||||||
if (client->refbuf && client->refbuf->len)
|
if (client->refbuf && client->refbuf->len) {
|
||||||
{
|
|
||||||
/* we have data to read from a refbuf first */
|
/* we have data to read from a refbuf first */
|
||||||
if (client->refbuf->len < len)
|
if (client->refbuf->len < len)
|
||||||
len = client->refbuf->len;
|
len = client->refbuf->len;
|
||||||
memcpy (buf, client->refbuf->data, len);
|
memcpy (buf, client->refbuf->data, len);
|
||||||
if (len < client->refbuf->len)
|
if (len < client->refbuf->len) {
|
||||||
{
|
|
||||||
char *ptr = client->refbuf->data;
|
char *ptr = client->refbuf->data;
|
||||||
memmove (ptr, ptr+len, client->refbuf->len - len);
|
memmove (ptr, ptr+len, client->refbuf->len - len);
|
||||||
}
|
}
|
||||||
@ -200,7 +197,8 @@ void client_send_100(client_t *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* this function is designed to work even if client is in bad state */
|
/* this function is designed to work even if client is in bad state */
|
||||||
static inline void client_send_500(client_t *client, const char *message) {
|
static inline void client_send_500(client_t *client, const char *message)
|
||||||
|
{
|
||||||
const char header[] = "HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n"
|
const char header[] = "HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n"
|
||||||
"500 - Internal Server Error\n---------------------------\n";
|
"500 - Internal Server Error\n---------------------------\n";
|
||||||
const ssize_t header_len = sizeof(header) - 1;
|
const ssize_t header_len = sizeof(header) - 1;
|
||||||
|
557
src/connection.c
557
src/connection.c
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user