static char *_get_stats(const char *source, const char *name) { stats_node_t *stats = NULL; stats_source_t *src = NULL; char *value = NULL; if (source == NULL) { avl_tree_rlock (_stats.global_tree); stats = _find_node(_stats.global_tree, name); if (stats) value = (char *)strdup(stats->value); avl_tree_unlock (_stats.global_tree); } else { avl_tree_rlock (_stats.source_tree); src = _find_source(_stats.source_tree, source); if (src) { avl_tree_rlock (src->stats_tree); avl_tree_unlock (_stats.source_tree); stats = _find_node(src->stats_tree, name); if (stats) value = (char *)strdup(stats->value); avl_tree_unlock (src->stats_tree); } else avl_tree_unlock (_stats.source_tree); } return value; }
/* 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); }
void *my_calloc (const char *file, int line, size_t num, size_t size) { alloc_node match, *result; snprintf (match.name, sizeof (match.name), "%s:%d", file, line); avl_tree_wlock (global.alloc_tree); if (avl_get_by_key (global.alloc_tree, &match, (void**)&result) == 0) { allocheader *block = calloc (1, (num*size)+sizeof(allocheader)); result->count++; result->allocated += (num*size); block->info = result; block->len = num*size; avl_tree_unlock (global.alloc_tree); return block+1; } result = calloc (1, sizeof(alloc_node)); if (result) { allocheader *block = calloc (1, (num*size)+sizeof(allocheader)); snprintf (result->name, sizeof (result->name), "%s:%d", file, line); result->count = 1; result->allocated = (num * size); avl_insert (global.alloc_tree, result); block->info = result; block->len = num*size; avl_tree_unlock (global.alloc_tree); return block+1; } avl_tree_unlock (global.alloc_tree); return NULL; }
int fserve_kill_client (client_t *client, const char *mount, int response) { int loop = 2, id; fbinfo finfo; xmlDocPtr doc; xmlNodePtr node; const char *idtext, *v = "0"; char buf[50]; finfo.flags = 0; finfo.mount = (char*)mount; finfo.limit = 0; finfo.fallback = NULL; idtext = httpp_get_query_param (client->parser, "id"); if (idtext == NULL) return client_send_400 (client, "missing parameter id"); id = atoi(idtext); doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); snprintf (buf, sizeof(buf), "Client %d not found", id); avl_tree_rlock (fh_cache); while (1) { avl_node *node; fh_node *fh = find_fh (&finfo); if (fh) { thread_mutex_lock (&fh->lock); avl_tree_unlock (fh_cache); node = avl_get_first (fh->clients); while (node) { client_t *listener = (client_t *)node->key; if (listener->connection.id == id) { listener->connection.error = 1; snprintf (buf, sizeof(buf), "Client %d removed", id); v = "1"; loop = 0; break; } node = avl_get_next (node); } thread_mutex_unlock (&fh->lock); avl_tree_rlock (fh_cache); } if (loop == 0) break; loop--; if (loop == 1) finfo.flags = FS_FALLBACK; } avl_tree_unlock (fh_cache); xmlNewChild (node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewChild (node, NULL, XMLSTR("return"), XMLSTR(v)); return admin_send_response (doc, client, response, "response.xsl"); }
int fserve_list_clients_xml (xmlNodePtr parent, fbinfo *finfo) { int ret = 0; fh_node *fh; avl_node *anode; avl_tree_rlock (fh_cache); fh = find_fh (finfo); if (fh == NULL) { avl_tree_unlock (fh_cache); return 0; } thread_mutex_lock (&fh->lock); avl_tree_unlock (fh_cache); anode = avl_get_first (fh->clients); while (anode) { client_t *listener = (client_t *)anode->key; stats_listener_to_xml (listener, parent); ret++; anode = avl_get_next (anode); } thread_mutex_unlock (&fh->lock); return ret; }
/* Add listener to the pending lists of either the source or fserve thread. * This can be run from the connection or auth thread context */ static int add_authenticated_listener (const char *mount, mount_proxy *mountinfo, client_t *client) { int ret = 0; source_t *source = NULL; client->authenticated = 1; /* Here we are parsing the URI request to see if the extension is .xsl, if * so, then process this request as an XSLT request */ if (util_check_valid_extension (mount) == XSLT_CONTENT) { /* If the file exists, then transform it, otherwise, write a 404 */ ICECAST_LOG_DEBUG("Stats request, sending XSL transformed stats"); stats_transform_xslt (client, mount); return 0; } avl_tree_rlock (global.source_tree); source = source_find_mount (mount); if (source) { if (mountinfo) { if (check_duplicate_logins (source, client, mountinfo->auth) == 0) { avl_tree_unlock (global.source_tree); return -1; } /* set a per-mount disconnect time if auth hasn't set one already */ if (mountinfo->max_listener_duration && client->con->discon_time == 0) client->con->discon_time = time(NULL) + mountinfo->max_listener_duration; } ret = add_listener_to_source (source, client); avl_tree_unlock (global.source_tree); if (ret == 0) ICECAST_LOG_DEBUG("client authenticated, passed to source"); } else { avl_tree_unlock (global.source_tree); fserve_client_create (client, mount); } return ret; }
int command_list_mounts(client_t *client, int response) { DEBUG0("List mounts request"); client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); if (response == TEXT) { redirector_update (client); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); client->refbuf->len = strlen (client->refbuf->data); client->respcode = 200; if (strcmp (httpp_getvar (client->parser, HTTPP_VAR_URI), "/admin/streams") == 0) client->refbuf->next = stats_get_streams (1); else client->refbuf->next = stats_get_streams (0); return fserve_setup_client (client); } else { xmlDocPtr doc; avl_tree_rlock (global.source_tree); doc = admin_build_sourcelist(NULL); avl_tree_unlock (global.source_tree); return admin_send_response (doc, client, response, "listmounts.xsl"); } }
long stats_handle (const char *mount) { stats_source_t *src_stats; if (mount == NULL) return 0; avl_tree_wlock (_stats.source_tree); src_stats = _find_source(_stats.source_tree, mount); if (src_stats == NULL) { src_stats = (stats_source_t *)calloc (1, sizeof (stats_source_t)); if (src_stats == NULL) abort(); DEBUG1 ("new source stat %s", mount); src_stats->source = (char *)strdup (mount); src_stats->stats_tree = avl_tree_new (_compare_stats, NULL); src_stats->flags = STATS_SLAVE|STATS_GENERAL|STATS_HIDDEN; avl_insert (_stats.source_tree, (void *)src_stats); } avl_tree_wlock (src_stats->stats_tree); avl_tree_unlock (_stats.source_tree); return (long)src_stats; }
void stats_global_calc (void) { stats_event_t event; avl_node *anode; char buffer [VAL_BUFSIZE]; connection_stats (); avl_tree_rlock (_stats.global_tree); anode = avl_get_first(_stats.global_tree); while (anode) { stats_node_t *node = (stats_node_t *)anode->key; if (node->flags & STATS_REGULAR) stats_listener_send (node->flags, "EVENT global %s %s\n", node->name, node->value); anode = avl_get_next (anode); } avl_tree_unlock (_stats.global_tree); build_event (&event, NULL, "outgoing_kbitrate", buffer); event.flags = STATS_COUNTERS|STATS_HIDDEN; snprintf (buffer, sizeof(buffer), "%" PRIu64, (int64_t)global_getrate_avg (global.out_bitrate) * 8 / 1024); process_event (&event); }
static int command_alloc(client_t *client) { xmlDocPtr doc = xmlNewDoc (XMLSTR("1.0")); xmlNodePtr rootnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); avl_node *node; xmlDocSetRootElement(doc, rootnode); avl_tree_rlock (global.alloc_tree); node = avl_get_first (global.alloc_tree); while (node) { alloc_node *an = node->key; char value[25]; xmlNodePtr bnode = xmlNewChild (rootnode, NULL, XMLSTR("block"), NULL); xmlSetProp (bnode, XMLSTR("name"), XMLSTR(an->name)); snprintf (value, sizeof value, "%d", an->count); xmlNewChild (bnode, NULL, XMLSTR("count"), XMLSTR(value)); snprintf (value, sizeof value, "%d", an->allocated); xmlNewChild (bnode, NULL, XMLSTR("allocated"), XMLSTR(value)); node = avl_get_next (node); } avl_tree_unlock (global.alloc_tree); return admin_send_response (doc, client, RAW, "stats.xsl"); }
static void command_list_mounts(client_t *client, int response) { DEBUG0("List mounts request"); if (response == PLAINTEXT) { snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); client->refbuf->len = strlen (client->refbuf->data); client->respcode = 200; client->refbuf->next = stats_get_streams (); fserve_add_client (client, NULL); } else { xmlDocPtr doc; avl_tree_rlock (global.source_tree); doc = admin_build_sourcelist(NULL); avl_tree_unlock (global.source_tree); admin_send_response(doc, client, response, LISTMOUNTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); } }
int fserve_query_count (fbinfo *finfo) { int ret = -1; fh_node *fh; if (finfo->flags & FS_FALLBACK && finfo->limit) { avl_tree_wlock (fh_cache); fh = open_fh (finfo); if (fh) { ret = fh->refcount; thread_mutex_unlock (&fh->lock); } } else { avl_tree_rlock (fh_cache); fh = find_fh (finfo); if (fh) { thread_mutex_lock (&fh->lock); ret = fh->refcount; thread_mutex_unlock (&fh->lock); } avl_tree_unlock (fh_cache); } return ret; }
static xmlNodePtr _dump_stats_to_doc (xmlNodePtr root, const char *show_mount, int flags) { avl_node *avlnode; xmlNodePtr ret = NULL; /* general stats first */ avl_tree_rlock (_stats.global_tree); avlnode = avl_get_first(_stats.global_tree); while (avlnode) { stats_node_t *stat = avlnode->key; if (stat->flags & flags) xmlNewTextChild (root, NULL, XMLSTR(stat->name), XMLSTR(stat->value)); avlnode = avl_get_next (avlnode); } avl_tree_unlock (_stats.global_tree); /* now per mount stats */ avl_tree_rlock (_stats.source_tree); avlnode = avl_get_first(_stats.source_tree); while (avlnode) { stats_source_t *source = (stats_source_t *)avlnode->key; if (((flags&STATS_HIDDEN) || (source->flags&STATS_HIDDEN) == (flags&STATS_HIDDEN)) && (show_mount == NULL || strcmp (show_mount, source->source) == 0)) { avl_node *avlnode2; xmlNodePtr xmlnode = xmlNewTextChild (root, NULL, XMLSTR("source"), NULL); avl_tree_rlock (source->stats_tree); avlnode2 = avl_get_first (source->stats_tree); xmlSetProp (xmlnode, XMLSTR("mount"), XMLSTR(source->source)); if (ret == NULL) ret = xmlnode; while (avlnode2) { stats_node_t *stat = avlnode2->key; if ((flags&STATS_HIDDEN) || (stat->flags&STATS_HIDDEN) == (flags&STATS_HIDDEN)) xmlNewTextChild (xmlnode, NULL, XMLSTR(stat->name), XMLSTR(stat->value)); avlnode2 = avl_get_next (avlnode2); } avl_tree_unlock (source->stats_tree); } avlnode = avl_get_next (avlnode); } avl_tree_unlock (_stats.source_tree); return ret; }
int fserve_set_override (const char *mount, const char *dest, format_type_t type) { fh_node fh, *result; fh.finfo.flags = FS_FALLBACK; fh.finfo.mount = (char *)mount; fh.finfo.fallback = NULL; fh.finfo.type = type; avl_tree_wlock (fh_cache); result = find_fh (&fh.finfo); if (result) { thread_mutex_lock (&result->lock); if (result->refcount > 0) { fh_node *copy = calloc (1, sizeof (*copy)); avl_delete (fh_cache, result, NULL); copy->finfo = result->finfo; copy->finfo.mount = strdup (copy->finfo.mount); copy->prev_count = -1; // trigger stats update copy->expire = (time_t)-1; copy->stats = result->stats; copy->format = result->format; copy->f = result->f; thread_mutex_create (©->lock); copy->out_bitrate = rate_setup (10000, 1000); copy->clients = avl_tree_new (client_compare, NULL); avl_insert (fh_cache, copy); result->finfo.flags |= FS_DELETE; result->finfo.flags &= ~FS_FALLBACK; result->format = NULL; result->stats = 0; result->f = SOCK_ERROR; result->finfo.fallback = strdup (dest); result->finfo.type = type; } avl_tree_unlock (fh_cache); thread_mutex_unlock (&result->lock); INFO2 ("move clients from %s to %s", mount, dest); return 1; } avl_tree_unlock (fh_cache); return 0; }
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; } }
static void command_list_mounts(client_t *client, int response) { DEBUG0("List mounts request"); avl_tree_rlock (global.source_tree); if (response == PLAINTEXT) { char buffer [4096], *buf = buffer; unsigned int remaining = sizeof (buffer); int ret = snprintf (buffer, remaining, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); avl_node *node = avl_get_first(global.source_tree); while (node && ret > 0 && (unsigned)ret < remaining) { source_t *source = (source_t *)node->key; node = avl_get_next(node); if (source->hidden) continue; remaining -= ret; buf += ret; ret = snprintf (buf, remaining, "%s\n", source->mount); } avl_tree_unlock (global.source_tree); /* handle last line */ if (ret > 0 && (unsigned)ret < remaining) { remaining -= ret; buf += ret; } sock_write_bytes (client->con->sock, buffer, sizeof (buffer)-remaining); } else { xmlDocPtr doc = admin_build_sourcelist(NULL); avl_tree_unlock (global.source_tree); admin_send_response(doc, client, response, LISTMOUNTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); } client_destroy(client); return; }
client_t *source_find_client(source_t *source, int id) { client_t fakeclient; void *result; connection_t fakecon; fakeclient.con = &fakecon; fakeclient.con->id = id; avl_tree_rlock(source->client_tree); if(avl_get_by_key(source->client_tree, &fakeclient, &result) == 0) { avl_tree_unlock(source->client_tree); return result; } avl_tree_unlock(source->client_tree); return NULL; }
/* 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(); }
/* Check whether this client is currently on this mount, the client may be * on either the active or pending lists. * return 1 if ok to add or 0 to prevent */ static int check_duplicate_logins (source_t *source, client_t *client, auth_t *auth) { /* allow multiple authenticated relays */ if (client->username == NULL) return 1; if (auth && auth->allow_duplicate_users == 0) { avl_node *node; avl_tree_rlock (source->client_tree); node = avl_get_first (source->client_tree); while (node) { client_t *existing_client = (client_t *)node->key; if (existing_client->username && strcmp (existing_client->username, client->username) == 0) { avl_tree_unlock (source->client_tree); return 0; } node = avl_get_next (node); } avl_tree_unlock (source->client_tree); avl_tree_rlock (source->pending_tree); node = avl_get_first (source->pending_tree); while (node) { client_t *existing_client = (client_t *)node->key; if (existing_client->username && strcmp (existing_client->username, client->username) == 0) { avl_tree_unlock (source->pending_tree); return 0; } node = avl_get_next (node); } avl_tree_unlock (source->pending_tree); } return 1; }
/* Check for changes in the YP servers configured */ static void check_servers (void) { struct yp_server *server = (struct yp_server *)active_yps, **server_p = (struct yp_server **)&active_yps; while (server) { if (server->remove) { struct yp_server *to_go = server; DEBUG1 ("YP server \"%s\"removed", server->url); *server_p = server->next; server = server->next; destroy_yp_server (to_go); continue; } server_p = &server->next; server = server->next; } /* add new server entries */ while (pending_yps) { avl_node *node; server = (struct yp_server *)pending_yps; pending_yps = server->next; DEBUG1("Add pending yps %s", server->url); server->next = (struct yp_server *)active_yps; active_yps = server; /* new YP server configured, need to populate with existing sources */ avl_tree_rlock (global.source_tree); node = avl_get_first (global.source_tree); while (node) { ypdata_t *yp; source_t *source = node->key; thread_rwlock_rlock (&source->lock); if (source->yp_public && (yp = create_yp_entry (source->mount)) != NULL) { DEBUG1 ("Adding existing mount %s", source->mount); yp->server = server; yp->touch_interval = server->touch_interval; yp->next = server->mounts; server->mounts = yp; } thread_rwlock_unlock (&source->lock); node = avl_get_next (node); } avl_tree_unlock (global.source_tree); } }
static int _free_source_stats(void *key) { stats_source_t *node = (stats_source_t *)key; stats_listener_send (node->flags, "DELETE %s\n", node->source); DEBUG1 ("delete source node %s", node->source); avl_tree_unlock (node->stats_tree); avl_tree_free(node->stats_tree, _free_stats); free(node->source); free(node); return 1; }
static void command_show_listeners(client_t *client, source_t *source, int response) { xmlDocPtr doc; xmlNodePtr node, srcnode, listenernode; avl_node *client_node; client_t *current; char buf[22]; char *userAgent = NULL; time_t now = time(NULL); doc = xmlNewDoc("1.0"); node = xmlNewDocNode(doc, NULL, "icestats", NULL); srcnode = xmlNewChild(node, NULL, "source", NULL); xmlSetProp(srcnode, "mount", source->mount); xmlDocSetRootElement(doc, node); memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%ld", source->listeners); xmlNewChild(srcnode, NULL, "Listeners", buf); avl_tree_rlock(source->client_tree); client_node = avl_get_first(source->client_tree); while(client_node) { current = (client_t *)client_node->key; listenernode = xmlNewChild(srcnode, NULL, "listener", NULL); xmlNewChild(listenernode, NULL, "IP", current->con->ip); userAgent = httpp_getvar(current->parser, "user-agent"); if (userAgent) { xmlNewChild(listenernode, NULL, "UserAgent", userAgent); } else { xmlNewChild(listenernode, NULL, "UserAgent", "Unknown"); } memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%ld", now - current->con->con_time); xmlNewChild(listenernode, NULL, "Connected", buf); memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%lu", current->con->id); xmlNewChild(listenernode, NULL, "ID", buf); if (current->username) { xmlNewChild(listenernode, NULL, "username", current->username); } client_node = avl_get_next(client_node); } avl_tree_unlock(source->client_tree); admin_send_response(doc, client, response, LISTCLIENTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); client_destroy(client); }
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"); }
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; }
static void process_source_event (stats_event_t *event) { stats_source_t *snode; avl_tree_wlock (_stats.source_tree); snode = _find_source(_stats.source_tree, event->source); if (snode == NULL) { if (event->action == STATS_EVENT_REMOVE) { avl_tree_unlock (_stats.source_tree); return; } snode = (stats_source_t *)calloc(1,sizeof(stats_source_t)); if (snode == NULL) abort(); DEBUG1 ("new source stat %s", event->source); snode->source = (char *)strdup(event->source); snode->stats_tree = avl_tree_new(_compare_stats, NULL); snode->flags = STATS_SLAVE|STATS_GENERAL|STATS_HIDDEN; avl_insert(_stats.source_tree, (void *)snode); } if (event->action == STATS_EVENT_REMOVE && event->name == NULL) { int fallback_stream = 0; avl_tree_wlock (snode->stats_tree); fallback_stream = _find_node (snode->stats_tree, "fallback") == NULL ? 1 : 0; if (fallback_stream) avl_delete(_stats.source_tree, (void *)snode, _free_source_stats); else avl_tree_unlock (snode->stats_tree); avl_tree_unlock (_stats.source_tree); return; } avl_tree_wlock (snode->stats_tree); avl_tree_unlock (_stats.source_tree); process_source_stat (snode, event); avl_tree_unlock (snode->stats_tree); }
static void process_global_event (stats_event_t *event) { stats_node_t *node = NULL; avl_tree_wlock (_stats.global_tree); /* DEBUG3("global event %s %s %d", event->name, event->value, event->action); */ if (event->action == STATS_EVENT_REMOVE) { /* we're deleting */ node = _find_node(_stats.global_tree, event->name); if (node != NULL) { stats_listener_send (node->flags, "DELETE global %s\n", event->name); avl_delete(_stats.global_tree, (void *)node, _free_stats); } avl_tree_unlock (_stats.global_tree); return; } node = _find_node(_stats.global_tree, event->name); if (node) { modify_node_event (node, event); if ((node->flags & STATS_REGULAR) == 0) stats_listener_send (node->flags, "EVENT global %s %s\n", node->name, node->value); } else { /* add node */ node = (stats_node_t *)calloc(1, sizeof(stats_node_t)); node->name = (char *)strdup(event->name); node->value = (char *)strdup(event->value); node->flags = event->flags; avl_insert(_stats.global_tree, (void *)node); stats_listener_send (node->flags, "EVENT global %s %s\n", event->name, event->value); } avl_tree_unlock (_stats.global_tree); }
void my_free (void *freeblock) { allocheader *block; alloc_node *info; if (freeblock == NULL) return; block = (allocheader*)freeblock -1; info = block->info; avl_tree_wlock (global.alloc_tree); info->count--; info->allocated -= block->len; avl_tree_unlock (global.alloc_tree); free (block); }
/* if 0 is returned then the client should not be touched, however if -1 * is returned then the caller is responsible for handling the client */ static int add_listener_to_source (source_t *source, client_t *client) { int loop = 10; do { ICECAST_LOG_DEBUG("max on %s is %ld (cur %lu)", source->mount, source->max_listeners, source->listeners); if (source->max_listeners == -1) break; if (source->listeners < (unsigned long)source->max_listeners) break; if (loop && source->fallback_when_full && source->fallback_mount) { source_t *next = source_find_mount (source->fallback_mount); if (!next) { ICECAST_LOG_ERROR("Fallback '%s' for full source '%s' not found", source->mount, source->fallback_mount); return -1; } ICECAST_LOG_INFO("stream full trying %s", next->mount); source = next; loop--; continue; } /* now we fail the client */ return -1; } while (1); client->write_to_client = format_generic_write_to_client; client->check_buffer = format_check_http_buffer; client->refbuf->len = PER_CLIENT_REFBUF_SIZE; memset (client->refbuf->data, 0, PER_CLIENT_REFBUF_SIZE); /* lets add the client to the active list */ avl_tree_wlock (source->pending_tree); avl_insert (source->pending_tree, client); avl_tree_unlock (source->pending_tree); if (source->running == 0 && source->on_demand) { /* enable on-demand relay to start, wake up the slave thread */ ICECAST_LOG_DEBUG("kicking off on-demand relay"); source->on_demand_req = 1; } ICECAST_LOG_DEBUG("Added client to %s", source->mount); return 0; }
int auth_is_listener_connected(source_t *source, char *username) { client_t *client; avl_node *client_node; avl_tree_rlock(source->client_tree); client_node = avl_get_first(source->client_tree); while(client_node) { client = (client_t *)client_node->key; if (client->username) { if (!strcmp(client->username, username)) { avl_tree_unlock(source->client_tree); return 1; } } client_node = avl_get_next(client_node); } avl_tree_unlock(source->client_tree); return 0; }
/* Remove the provided source from the global tree and free it */ void source_free_source (source_t *source) { DEBUG1 ("freeing source \"%s\"", source->mount); avl_tree_wlock (global.source_tree); avl_delete (global.source_tree, source, NULL); avl_tree_unlock (global.source_tree); avl_tree_free(source->pending_tree, _free_client); avl_tree_free(source->client_tree, _free_client); free (source->mount); free (source); return; }