コード例 #1
0
ファイル: source.c プロジェクト: asepsutiawan/icecast
/* Search for mount, if the mount is there but not currently running then
 * check the fallback, and so on.  Must have a global source lock to call
 * this function.
 */
source_t *source_find_mount (const char *mount)
{
    source_t *source = NULL;
    ice_config_t *config;
    mount_proxy *mountinfo;
    int depth = 0;

    config = config_get_config();
    while (mount && depth < MAX_FALLBACK_DEPTH)
    {
        source = source_find_mount_raw(mount);

        if (source)
        {
            if (source->running || source->on_demand)
                break;
        }

        /* we either have a source which is not active (relay) or no source
         * at all. Check the mounts list for fallback settings
         */
        mountinfo = config_find_mount (config, mount);
        source = NULL;

        if (mountinfo == NULL)
            break;
        mount = mountinfo->fallback_mount;
        depth++;
    }

    config_release_config();
    return source;
}
コード例 #2
0
/* This removes any source stats from virtual mountpoints, ie mountpoints
 * where no source_t exists. This function requires the global sources lock
 * to be held before calling.
 */
void stats_clear_virtual_mounts (void)
{
    avl_node *snode;

    avl_tree_wlock (_stats.source_tree);
    snode = avl_get_first(_stats.source_tree);
    while (snode)
    {
        stats_source_t *src = (stats_source_t *)snode->key;
        source_t *source = source_find_mount_raw (src->source);

        if (source == NULL)
        {
            stats_node_t *node;
            avl_tree_wlock (src->stats_tree);
            node = _find_node (src->stats_tree, "fallback");
            if (node == NULL)
            {
                /* no source_t and no fallback file stat, so delete */
                snode = avl_get_next (snode);
                avl_delete (_stats.source_tree, src, _free_source_stats);
                continue;
            }
            avl_tree_unlock (src->stats_tree);
        }

        snode = avl_get_next (snode);
    }
    avl_tree_unlock (_stats.source_tree);
}
コード例 #3
0
ファイル: source.c プロジェクト: asepsutiawan/icecast
/* rescan the mount list, so that xsl files are updated to show
 * unconnected but active fallback mountpoints
 */
void source_recheck_mounts (int update_all)
{
    ice_config_t *config;
    mount_proxy *mount;

    avl_tree_rlock (global.source_tree);
    config = config_get_config();
    mount = config->mounts;

    if (update_all)
        stats_clear_virtual_mounts ();

    while (mount)
    {
        source_t *source = source_find_mount (mount->mountname);

        if (source)
        {
            source = source_find_mount_raw (mount->mountname);
            if (source)
            {
                mount_proxy *mountinfo = config_find_mount (config, source->mount);
                source_update_settings (config, source, mountinfo);
            }
            else if (update_all)
            {
                stats_event_hidden (mount->mountname, NULL, mount->hidden);
                stats_event_args (mount->mountname, "listenurl", "http://%s:%d%s",
                        config->hostname, config->port, mount->mountname);
                stats_event (mount->mountname, "listeners", "0");
                if (mount->max_listeners < 0)
                    stats_event (mount->mountname, "max_listeners", "unlimited");
                else
                    stats_event_args (mount->mountname, "max_listeners", "%d", mount->max_listeners);
            }
        }
        else
            stats_event (mount->mountname, NULL, NULL);

        /* check for fallback to file */
        if (global.running == ICE_RUNNING && mount->fallback_mount)
        {
            source_t *fallback = source_find_mount (mount->fallback_mount);
            if (fallback == NULL)
            {
                thread_create ("Fallback file thread", source_fallback_file,
                        strdup (mount->fallback_mount), THREAD_DETACHED);
            }
        }

        mount = mount->next;
    }
    avl_tree_unlock (global.source_tree);
    config_release_config();
}
コード例 #4
0
ファイル: admin.c プロジェクト: MechanisM/icecast-kh
int admin_mount_request (client_t *client, const char *uri)
{
    source_t *source;
    const char *mount = httpp_get_query_param (client->parser, "mount");

    struct admin_command *cmd = find_admin_command (admin_mount, uri);

    if (cmd == NULL)
        return command_stats (client, uri);

    if (cmd == NULL || cmd->handle.source == NULL)
    {
        INFO0("mount request not recognised");
        return client_send_400 (client, "unknown request");
    }

    avl_tree_rlock(global.source_tree);
    source = source_find_mount_raw(mount);

    if (source == NULL)
    {
        avl_tree_unlock(global.source_tree);
        if (strncmp (cmd->request, "stats", 5) == 0)
            return command_stats (client, uri);
        if (strncmp (cmd->request, "listclients", 11) == 0)
            return fserve_list_clients (client, mount, cmd->response, 1);
        if (strncmp (cmd->request, "killclient", 10) == 0)
            return fserve_kill_client (client, mount, cmd->response);
        WARN1("Admin command on non-existent source %s", mount);
        return client_send_400 (client, "Source does not exist");
    }
    else
    {
        int ret = 0;
        thread_mutex_lock (&source->lock);
        if (source_available (source) == 0)
        {
            thread_mutex_unlock (&source->lock);
            avl_tree_unlock (global.source_tree);
            INFO1("Received admin command on unavailable mount \"%s\"", mount);
            return client_send_400 (client, "Source is not available");
        }
        ret = cmd->handle.source (client, source, cmd->response);
        avl_tree_unlock(global.source_tree);
        return ret;
    }
}
コード例 #5
0
ファイル: source.c プロジェクト: miksago/icecast
/* Search for mount, if the mount is there but not currently running then
 * check the fallback, and so on.  Must have a global source lock to call
 * this function.
 */
source_t *source_find_mount (const char *mount)
{
    source_t *source = NULL;
    ice_config_t *config;
    mount_proxy *mountinfo;
    int depth = 0;

    config = config_get_config();
    while (mount != NULL)
    {
        /* limit the number of times through, maybe infinite */
        if (depth > MAX_FALLBACK_DEPTH)
        {
            source = NULL;
            break;
        }

        source = source_find_mount_raw(mount);

        if (source != NULL && source->running)
            break;

        /* source is not running, meaning that the fallback is not configured
           within the source, we need to check the mount list */
        mountinfo = config->mounts;
        source = NULL;
        while (mountinfo)
        {
            if (strcmp (mountinfo->mountname, mount) == 0)
                break;
            mountinfo = mountinfo->next;
        }
        if (mountinfo)
            mount = mountinfo->fallback_mount;
        else
            mount = NULL;
        depth++;
    }

    config_release_config();
    return source;
}
コード例 #6
0
ファイル: admin.c プロジェクト: MechanisM/icecast-kh
static int command_show_image (client_t *client, const char *mount)
{
    source_t *source;

    avl_tree_rlock (global.source_tree);
    source = source_find_mount_raw (mount);
    if (source && source->format && source->format->get_image)
    {
        thread_mutex_lock (&source->lock);
        avl_tree_unlock (global.source_tree);
        if (source->format->get_image (client, source->format) == 0)
        {
            thread_mutex_unlock (&source->lock);
            return fserve_setup_client (client);
        }
        thread_mutex_unlock (&source->lock);
    }
    else
        avl_tree_unlock (global.source_tree);
    return client_send_404 (client, "No image available");
}
コード例 #7
0
xmlDocPtr stats_get_xml(int show_hidden, const char *show_mount, operation_mode mode)
{
    xmlDocPtr doc;
    xmlNodePtr node;
    source_t * source;

    doc = xmlNewDoc (XMLSTR("1.0"));
    node = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
    xmlDocSetRootElement(doc, node);

    node = _dump_stats_to_doc (node, show_mount, show_hidden);

    if (show_mount && node) {
        avl_tree_rlock(global.source_tree);
        source = source_find_mount_raw(show_mount);
        admin_add_listeners_to_mount(source, node, mode);
        avl_tree_unlock(global.source_tree);
    }

    return doc;
}
コード例 #8
0
xmlDocPtr stats_get_xml (int flags, const char *show_mount)
{
    xmlDocPtr doc;
    xmlNodePtr node;

    doc = xmlNewDoc (XMLSTR("1.0"));
    node = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL);
    xmlDocSetRootElement(doc, node);

    node = _dump_stats_to_doc (node, show_mount, flags);

    if (show_mount && node)
    {
		source_t *source;
        /* show each listener */
        avl_tree_rlock (global.source_tree);
        source = source_find_mount_raw (show_mount);

        if (source)
        {
            thread_mutex_lock (&source->lock);
            admin_source_listeners (source, node);
            thread_mutex_unlock (&source->lock);
            avl_tree_unlock (global.source_tree);
        }
        else
        {
            fbinfo finfo;

            avl_tree_unlock (global.source_tree);
            finfo.flags = FS_FALLBACK;
            finfo.mount = (char*)show_mount;
            finfo.limit = 0;
            finfo.fallback = NULL;

            fserve_list_clients_xml (node, &finfo);
        }
    }
    return doc;
}
コード例 #9
0
/* This removes any source stats from virtual mountpoints, ie mountpoints
 * where no source_t exists. This function requires the global sources lock
 * to be held before calling.
 */
void stats_clear_virtual_mounts (void)
{
    avl_node *snode;

    thread_mutex_lock (&_stats_mutex);
    snode = avl_get_first(_stats.source_tree);
    while (snode)
    {
        stats_source_t *src = (stats_source_t *)snode->key;
        source_t *source = source_find_mount_raw (src->source);

        if (source == NULL)
        {
            /* no source_t is reserved so remove them now */
            snode = avl_get_next (snode);
            ICECAST_LOG_DEBUG("releasing %s stats", src->source);
            avl_delete (_stats.source_tree, src, _free_source_stats);
            continue;
        }

        snode = avl_get_next (snode);
    }
    thread_mutex_unlock (&_stats_mutex);
}
コード例 #10
0
ファイル: source.c プロジェクト: asepsutiawan/icecast
/* Allocate a new source with the stated mountpoint, if one already
 * exists with that mountpoint in the global source tree then return
 * NULL.
 */
source_t *source_reserve (const char *mount)
{
    source_t *src = NULL;

    if(mount[0] != '/')
        WARN1("Source at \"%s\" does not start with '/', clients will be "
                "unable to connect", mount);

    do
    {
        avl_tree_wlock (global.source_tree);
        src = source_find_mount_raw (mount);
        if (src)
        {
            src = NULL;
            break;
        }

        src = calloc (1, sizeof(source_t));
        if (src == NULL)
            break;

        src->client_tree = avl_tree_new(_compare_clients, NULL);
        src->pending_tree = avl_tree_new(_compare_clients, NULL);

        /* make duplicates for strings or similar */
        src->mount = strdup (mount);
        src->max_listeners = -1;

        avl_insert (global.source_tree, src);

    } while (0);

    avl_tree_unlock (global.source_tree);
    return src;
}
コード例 #11
0
ファイル: auth.c プロジェクト: balbinus/icecast-kh
int move_listener (client_t *client, struct _fbinfo *finfo)
{
    source_t *source;
    mount_proxy *minfo;
    int rate = finfo->limit, loop = 20, ret = -1;
    ice_config_t *config = config_get_config();
    struct _fbinfo where;
    unsigned int len = 4096;
    char buffer [len];

    memcpy (&where, finfo, sizeof (where));
    if (finfo->fallback)
        where.fallback = strdup (finfo->fallback);
    avl_tree_rlock (global.source_tree);
    do
    {
        len = sizeof buffer;
        util_expand_pattern (where.fallback, where.mount, buffer, &len);
        where.mount = buffer;

        minfo = config_find_mount (config, where.mount);

        if (rate == 0 && minfo && minfo->limit_rate)
            rate = minfo->limit_rate;
        source = source_find_mount_raw (where.mount);

        if (source == NULL && minfo == NULL)
            break;
        if (source)
        {
            thread_rwlock_wlock (&source->lock);
            if (source_available (source))
            {
                // an unused on-demand relay will still have an unitialised type
                if (source->format->type == finfo->type || source->format->type == FORMAT_TYPE_UNDEFINED)
                {
                    config_release_config();
                    avl_tree_unlock (global.source_tree);
                    source_setup_listener (source, client);
                    source->listeners++;
                    client->flags |= CLIENT_HAS_MOVED;
                    thread_rwlock_unlock (&source->lock);
                    free (where.fallback);
                    return 0;
                }
            }
            thread_rwlock_unlock (&source->lock);
        }
        if (minfo && minfo->fallback_mount)
        {
            free (where.fallback);
            where.fallback = strdup (where.mount);
            where.mount = minfo->fallback_mount;
        }
        else
            break;
    } while (loop--);

    avl_tree_unlock (global.source_tree);
    config_release_config();
    if (where.mount && ((client->flags & CLIENT_IS_SLAVE) == 0))
    {
        if (where.limit == 0)
        {
            if (rate == 0)
                if (sscanf (where.mount, "%*[^[][%d]", &rate) == 1)
                    rate = rate * 1000/8;
            where.limit = rate;
        }
        client->intro_offset = 0;
        ret = fserve_setup_client_fb (client, &where);
    }
    free (where.fallback);
    return ret;
}
コード例 #12
0
ファイル: admin.c プロジェクト: krattai/AEBL
void admin_handle_request(client_t *client, const char *uri)
{
    const char *mount, *command_string;
    int command;

    DEBUG1("Admin request (%s)", uri);
    if (!((strcmp(uri, "/admin.cgi") == 0) ||
         (strncmp("/admin/", uri, 7) == 0))) {
        ERROR0("Internal error: admin request isn't");
        client_send_401(client);
        return;
    }

    if (strcmp(uri, "/admin.cgi") == 0) {
        command_string = uri + 1;
    }
    else {
        command_string = uri + 7;
    }

    DEBUG1("Got command (%s)", command_string);
    command = admin_get_command(command_string);

    if(command < 0) {
        ERROR1("Error parsing command string or unrecognised command: %s",
                command_string);
        client_send_400(client, "Unrecognised command");
        return;
    }

    if (command == COMMAND_SHOUTCAST_METADATA_UPDATE) {

        ice_config_t *config;
        const char *sc_mount;
        const char *pass = httpp_get_query_param (client->parser, "pass");
        listener_t *listener;

        if (pass == NULL)
        {
            client_send_400 (client, "missing pass parameter");
            return;
        }
        config = config_get_config ();
        sc_mount = config->shoutcast_mount;
        listener = config_get_listen_sock (config, client->con);
        if (listener && listener->shoutcast_mount)
            sc_mount = listener->shoutcast_mount;

        httpp_set_query_param (client->parser, "mount", sc_mount);
        httpp_setvar (client->parser, HTTPP_VAR_PROTOCOL, "ICY");
        httpp_setvar (client->parser, HTTPP_VAR_ICYPASSWORD, pass);
        config_release_config ();
    }

    mount = httpp_get_query_param(client->parser, "mount");

    if(mount != NULL) {
        source_t *source;

        /* this request does not require auth but can apply to files on webroot */
        if (command == COMMAND_BUILDM3U)
        {
            command_buildm3u (client, mount);
            return;
        }
        /* This is a mount request, handle it as such */
        if (!connection_check_admin_pass(client->parser))
        {
            if (!connection_check_source_pass(client->parser, mount))
            {
                INFO1("Bad or missing password on mount modification admin "
                        "request (command: %s)", command_string);
                client_send_401(client);
                return;
            }
        }
        
        avl_tree_rlock(global.source_tree);
        source = source_find_mount_raw(mount);

        if (source == NULL)
        {
            WARN2("Admin command %s on non-existent source %s", 
                    command_string, mount);
            avl_tree_unlock(global.source_tree);
            client_send_400(client, "Source does not exist");
        }
        else
        {
            if (source->running == 0 && source->on_demand == 0)
            {
                avl_tree_unlock (global.source_tree);
                INFO2("Received admin command %s on unavailable mount \"%s\"",
                        command_string, mount);
                client_send_400 (client, "Source is not available");
                return;
            }
            if (command == COMMAND_SHOUTCAST_METADATA_UPDATE &&
                    source->shoutcast_compat == 0)
            {
                avl_tree_unlock (global.source_tree);
                ERROR0 ("illegal change of metadata on non-shoutcast "
                        "compatible stream");
                client_send_400 (client, "illegal metadata call");
                return;
            }
            INFO2("Received admin command %s on mount \"%s\"", 
                    command_string, mount);
            admin_handle_mount_request(client, source, command);
            avl_tree_unlock(global.source_tree);
        }
    }
    else {

        if (command == COMMAND_PLAINTEXT_LISTSTREAM) {
        /* this request is used by a slave relay to retrieve
           mounts from the master, so handle this request
           validating against the relay password */
            if(!connection_check_relay_pass(client->parser)) {
                INFO1("Bad or missing password on admin command "
                      "request (command: %s)", command_string);
                client_send_401(client);
                return;
            }
        }
        else {
            if(!connection_check_admin_pass(client->parser)) {
                INFO1("Bad or missing password on admin command "
                      "request (command: %s)", command_string);
                client_send_401(client);
                return;
            }
        }
        
        admin_handle_general_request(client, command);
    }
}
コード例 #13
0
static xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, int hidden) {
    avl_node *avlnode;
    xmlNodePtr ret = NULL;
    ice_config_t *config;

    thread_mutex_lock(&_stats_mutex);
    /* general stats first */
    avlnode = avl_get_first(_stats.global_tree);

    while (avlnode) {
        stats_node_t *stat = avlnode->key;
        if (stat->hidden <=  hidden)
            xmlNewTextChild (root, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
        avlnode = avl_get_next (avlnode);
    }
    /* now per mount stats */
    avlnode = avl_get_first(_stats.source_tree);
    config = config_get_config();
    __add_authstack(config->authstack, root);
    config_release_config();

    while (avlnode) {
        stats_source_t *source = (stats_source_t *)avlnode->key;

        if (source->hidden <= hidden &&
                (show_mount == NULL || strcmp (show_mount, source->source) == 0))
        {
            xmlNodePtr metadata, history;
            source_t *source_real;
            mount_proxy *mountproxy;
            int i;

            avl_node *avlnode2 = avl_get_first (source->stats_tree);
            xmlNodePtr xmlnode = xmlNewTextChild (root, NULL, XMLSTR("source"), NULL);

            xmlSetProp (xmlnode, XMLSTR("mount"), XMLSTR(source->source));
            if (ret == NULL)
                ret = xmlnode;
            while (avlnode2)
            {
                stats_node_t *stat = avlnode2->key;
                xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value));
                avlnode2 = avl_get_next (avlnode2);
            }


            avl_tree_rlock(global.source_tree);
            source_real = source_find_mount_raw(source->source);
            history = playlist_render_xspf(source_real->history);
            if (history)
                xmlAddChild(xmlnode, history);
            metadata = xmlNewTextChild(xmlnode, NULL, XMLSTR("metadata"), NULL);
            if (source_real->format) {
                for (i = 0; i < source_real->format->vc.comments; i++)
                    __add_metadata(metadata, source_real->format->vc.user_comments[i]);
            }
            avl_tree_unlock(global.source_tree);

            config = config_get_config();
            mountproxy = config_find_mount(config, source->source, MOUNT_TYPE_NORMAL);
            __add_authstack(mountproxy->authstack, xmlnode);
            config_release_config();
        }
        avlnode = avl_get_next (avlnode);
    }
    thread_mutex_unlock(&_stats_mutex);
    return ret;
}