int xslt_transform (xmlDocPtr doc, const char *xslfilename, client_t *client) { int i, ret; xsl_req *x; thread_rwlock_rlock (&xslt_lock); i = xslt_cached (xslfilename, NULL, client->worker->current_time.tv_sec); i = xslt_req_sheet (client, doc, xslfilename, i); x = client->shared_data; switch (i) { case -1: thread_rwlock_unlock (&xslt_lock); xmlFreeDoc (doc); client->shared_data = NULL; ret = client_send_404 (client, "Could not parse XSLT file"); break; case CACHESIZE: // delayed thread_rwlock_unlock (&xslt_lock); return 0; default: // found it and ok to use ret = xslt_send_sheet (client, doc, i); break; } if (x) { free (x->cache.filename); free (x->cache.disposition); free (x); } return ret; }
static int directory_recheck (client_t *client) { int ret = -1; thread_rwlock_rlock (&yp_lock); do { if (ypclient.connection.error) break; if (active_yps || yp_update) { ret = 0; if (yp_update || active_yps->mounts) { if (yp_update || client->counter <= client->worker->current_time.tv_sec) { client->counter = (uint64_t)-1; client->flags &= ~CLIENT_ACTIVE; thread_create ("YP Thread", yp_update_thread, NULL, THREAD_DETACHED); break; } } } client->schedule_ms = client->worker->time_ms + 1000; } while (0); thread_rwlock_unlock (&yp_lock); return ret; }
static auth_result htpasswd_auth (auth_client *auth_user) { auth_t *auth = auth_user->client->auth; htpasswd_auth_state *htpasswd = auth->state; client_t *client = auth_user->client; htpasswd_user entry; void *result; if (client->username == NULL || client->password == NULL) return AUTH_FAILED; htpasswd_recheckfile (htpasswd); thread_rwlock_rlock (&htpasswd->file_rwlock); entry.name = client->username; if (avl_get_by_key (htpasswd->users, &entry, &result) == 0) { htpasswd_user *found = result; char *hashed_pw; thread_rwlock_unlock (&htpasswd->file_rwlock); hashed_pw = get_hash (client->password, strlen (client->password)); if (strcmp (found->pass, hashed_pw) == 0) { free (hashed_pw); return AUTH_OK; } free (hashed_pw); DEBUG0 ("incorrect password for client"); return AUTH_FAILED; } DEBUG1 ("no such username: %s", client->username); thread_rwlock_unlock (&htpasswd->file_rwlock); return AUTH_FAILED; }
/* Add YP entries to active servers */ void yp_add (const char *mount) { struct yp_server *server; /* make sure YP thread is not modifying the lists */ thread_rwlock_rlock (&yp_lock); /* make sure we don't race against another yp_add */ thread_mutex_lock (&yp_pending_lock); server = (struct yp_server *)active_yps; while (server) { ypdata_t *yp; /* add new ypdata to each servers pending yp */ if ((yp = create_yp_entry (mount)) != NULL) { DEBUG2 ("Adding %s to %s", mount, server->url); yp->server = server; yp->touch_interval = server->touch_interval; yp->next = server->pending_mounts; yp->next_update = time(NULL) + 5; server->pending_mounts = yp; yp_update = 1; } server = server->next; } thread_mutex_unlock (&yp_pending_lock); thread_rwlock_unlock (&yp_lock); }
/* Mark an existing entry in the YP list as to be marked for deletion */ void yp_remove (const char *mount) { struct yp_server *server = (struct yp_server *)active_yps; thread_rwlock_rlock (&yp_lock); while (server) { ypdata_t *list = server->mounts; while (1) { ypdata_t *yp = find_yp_mount (list, mount); if (yp == NULL) break; if (yp->release || yp->remove) { list = yp->next; continue; /* search again these are old entries */ } DEBUG2 ("release %s on YP %s", mount, server->url); yp->release = 1; yp->next_update = 0; yp_update = 1; } server = server->next; } thread_rwlock_unlock (&yp_lock); }
/* This is similar to yp_remove, but we force a touch * attempt */ void yp_touch (const char *mount) { struct yp_server *server = (struct yp_server *)active_yps; time_t trigger; ypdata_t *search_list = NULL; thread_rwlock_rlock (&yp_lock); /* do update in 3 secs, give stats chance to update */ trigger = time(NULL) + 3; if (server) search_list = server->mounts; while (server) { ypdata_t *yp = find_yp_mount (search_list, mount); if (yp) { /* we may of found old entries not purged yet, so skip them */ if (yp->release != 0 || yp->remove != 0) { search_list = yp->next; continue; } /* only force if touch */ if (yp->process == do_yp_touch) yp->next_update = trigger; } server = server->next; if (server) search_list = server->mounts; } thread_rwlock_unlock (&yp_lock); }
/* This is similar to yp_remove, but we force a touch * attempt */ void yp_touch (const char *mount) { struct yp_server *server = (struct yp_server *)active_yps; ypdata_t *search_list = NULL; thread_rwlock_rlock (&yp_lock); if (server) search_list = server->mounts; while (server) { ypdata_t *yp = find_yp_mount (search_list, mount); if (yp) { /* we may of found old entries not purged yet, so skip them */ if (yp->release != 0 || yp->remove != 0) { search_list = yp->next; continue; } /* don't update the directory if there is a touch scheduled soon */ if (yp->process == do_yp_touch && now + yp->touch_interval - yp->next_update > 60) yp_schedule (yp, 0); } server = server->next; if (server) search_list = server->mounts; } thread_rwlock_unlock (&yp_lock); }
void yp_recheck_config (ice_config_t *config) { int i; struct yp_server *server; DEBUG0("Updating YP configuration"); thread_rwlock_rlock (&yp_lock); server = (struct yp_server *)active_yps; while (server) { server->remove = 1; server = server->next; } /* for each yp url in config, check to see if one exists if not, then add it. */ for (i=0 ; i < config->num_yp_directories; i++) { server = find_yp_server (config->yp_url[i]); if (server == NULL) { server = calloc (1, sizeof (struct yp_server)); if (server == NULL) { destroy_yp_server (server); break; } server->url = strdup (config->yp_url[i]); server->url_timeout = config->yp_url_timeout[i]; server->touch_interval = config->yp_touch_interval[i]; server->curl = curl_easy_init(); if (server->curl == NULL) { destroy_yp_server (server); break; } if (server->touch_interval < 30) server->touch_interval = 30; curl_easy_setopt (server->curl, CURLOPT_URL, server->url); curl_easy_setopt (server->curl, CURLOPT_HEADERFUNCTION, handle_returned_header); curl_easy_setopt (server->curl, CURLOPT_WRITEFUNCTION, handle_returned_data); curl_easy_setopt (server->curl, CURLOPT_WRITEDATA, server->curl); curl_easy_setopt (server->curl, CURLOPT_TIMEOUT, server->url_timeout); curl_easy_setopt (server->curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt (server->curl, CURLOPT_ERRORBUFFER, &(server->curl_error[0])); server->next = (struct yp_server *)pending_yps; pending_yps = server; INFO3 ("Adding new YP server \"%s\" (timeout %ds, default interval %ds)", server->url, server->url_timeout, server->touch_interval); } else { server->remove = 0; } } thread_rwlock_unlock (&yp_lock); yp_update = 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 void *yp_update_thread(void *arg) { if (!kitsune_is_updating()) { /**DSU control */ INFO0("YP update thread started"); yp_running = 1; } while (yp_running) { kitsune_update("yp_update"); /**DSU updatepoint */ struct yp_server *server; thread_sleep (200000); /* do the YP communication */ thread_rwlock_rlock (&yp_lock); server = (struct yp_server *)active_yps; while (server) { /* DEBUG1 ("trying %s", server->url); */ yp_process_server (server); server = server->next; } thread_rwlock_unlock (&yp_lock); /* update the local YP structure */ if (yp_update) { thread_rwlock_wlock (&yp_lock); check_servers (); server = (struct yp_server *)active_yps; while (server) { /* DEBUG1 ("Checking yps %s", server->url); */ add_pending_yp (server); delete_marked_yp (server); server = server->next; } yp_update = 0; thread_rwlock_unlock (&yp_lock); } } thread_rwlock_destroy (&yp_lock); thread_mutex_destroy (&yp_pending_lock); /* free server and ypdata left */ while (active_yps) { struct yp_server *server = (struct yp_server *)active_yps; active_yps = server->next; destroy_yp_server (server); } return NULL; }
/* Not efficient; opens and scans the entire file for every request */ static auth_result htpasswd_auth(auth_t *auth, source_t *source, char *username, char *password) { htpasswd_auth_state *state = auth->state; FILE *passwdfile = NULL; char line[MAX_LINE_LEN]; char *sep; thread_rwlock_rlock(&state->file_rwlock); if (!state->allow_duplicate_users) { if (auth_is_listener_connected(source, username)) { thread_rwlock_unlock(&state->file_rwlock); return AUTH_FORBIDDEN; } } passwdfile = fopen(state->filename, "rb"); if(passwdfile == NULL) { WARN2("Failed to open authentication database \"%s\": %s", state->filename, strerror(errno)); thread_rwlock_unlock(&state->file_rwlock); return AUTH_FAILED; } while(get_line(passwdfile, line, MAX_LINE_LEN)) { if(!line[0] || line[0] == '#') continue; sep = strchr(line, ':'); if(sep == NULL) { DEBUG0("No seperator in line"); continue; } *sep = 0; if(!strcmp(username, line)) { /* Found our user, now: does the hash of password match hash? */ char *hash = sep+1; char *hashed_password = get_hash(password, strlen(password)); if(!strcmp(hash, hashed_password)) { fclose(passwdfile); free(hashed_password); thread_rwlock_unlock(&state->file_rwlock); return AUTH_OK; } free(hashed_password); /* We don't keep searching through the file */ break; } } fclose(passwdfile); thread_rwlock_unlock(&state->file_rwlock); return AUTH_FAILED; }
void client_add_incoming (client_t *client) { worker_t *handler; thread_rwlock_rlock (&workers_lock); handler = worker_incoming; thread_spin_lock (&handler->lock); thread_rwlock_unlock (&workers_lock); worker_add_client (handler, client); thread_spin_unlock (&handler->lock); worker_wakeup (handler); }
void client_add_worker (client_t *client) { worker_t *handler; thread_rwlock_rlock (&workers_lock); /* add client to the handler with the least number of clients */ handler = worker_selected(); thread_spin_lock (&handler->lock); thread_rwlock_unlock (&workers_lock); worker_add_client (handler, client); thread_spin_unlock (&handler->lock); worker_wakeup (handler); }
int auth_get_userlist(source_t *source, xmlNodePtr srcnode) { int ret = 0; htpasswd_auth_state *state; if (source->authenticator) { if (!strcmp(source->authenticator->type, "htpasswd")) { state = source->authenticator->state; thread_rwlock_rlock(&state->file_rwlock); ret = auth_get_htpasswd_userlist(source->authenticator, srcnode); thread_rwlock_unlock(&state->file_rwlock); } } return ret; }
/* Mark an existing entry in the YP list as to be marked for deletion */ void yp_remove (const char *mount) { struct yp_server *server = (struct yp_server *)active_yps; thread_rwlock_rlock (&yp_lock); while (server) { ypdata_t *yp = find_yp_mount (server->mounts, mount); if (yp) { DEBUG2 ("release %s on YP %s", mount, server->url); yp->release = 1; yp->next_update = 0; } server = server->next; } thread_rwlock_unlock (&yp_lock); }
static void *yp_update_thread(void *arg) { struct yp_server *server; yp_thread = thread_self(); /* DEBUG0("YP thread started"); */ /* do the YP communication */ thread_rwlock_rlock (&yp_lock); ypclient.counter = -1; server = (struct yp_server *)active_yps; while (server) { /* DEBUG1 ("trying %s", server->url); */ yp_process_server (server); server = server->next; } thread_rwlock_unlock (&yp_lock); /* update the local YP structure */ if (yp_update) { thread_rwlock_wlock (&yp_lock); check_servers (); server = (struct yp_server *)active_yps; while (server) { /* DEBUG1 ("Checking yps %s", server->url); */ add_pending_yp (server); delete_marked_yp (server); server = server->next; } yp_update = 0; thread_rwlock_unlock (&yp_lock); } yp_thread = NULL; /* DEBUG0("YP thread shutdown"); */ ypclient.flags |= CLIENT_ACTIVE; worker_wakeup (ypclient.worker); return NULL; }
/* The auth thread main loop. */ static void *auth_run_thread (void *arg) { auth_thread_t *handler = arg; auth_t *auth = handler->auth; DEBUG2 ("Authentication thread %d started for %s", handler->id, auth->mount); thread_rwlock_rlock (&auth_lock); while (1) { thread_mutex_lock (&auth->lock); if (auth->head) { auth_client *auth_user = auth->head; DEBUG2 ("%d client(s) pending on %s", auth->pending_count, auth->mount); auth->head = auth_user->next; if (auth->head == NULL) auth->tailp = &auth->head; auth->pending_count--; thread_mutex_unlock (&auth->lock); auth_user->next = NULL; /* associate per-thread data with auth_user here */ auth_user->thread_data = handler->data; auth_user->handler = handler->id; if (auth_user->process) auth_user->process (auth_user); auth_client_free (auth_user); continue; } handler->thread = NULL; break; } DEBUG1 ("Authenication thread %d shutting down", handler->id); auth_release (auth); thread_rwlock_unlock (&auth_lock); return NULL; }
// We pick a worker (consequetive) and set a max number of clients to move if needed void worker_balance_trigger (time_t now) { int log_counts = (now % 10) == 0 ? 1 : 0; if (worker_count == 1) return; // no balance required, leave quickly thread_rwlock_rlock (&workers_lock); // lets only search for this once a second, not many times worker_least_used = find_least_busy_handler (log_counts); if (worker_balance_to_check) { worker_balance_to_check->move_allocations = 50; worker_balance_to_check = worker_balance_to_check->next; } if (worker_balance_to_check == NULL) worker_balance_to_check = workers; thread_rwlock_unlock (&workers_lock); }
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_rwlock_rlock (&source->lock); avl_tree_unlock (global.source_tree); if (source->format->get_image (client, source->format) == 0) { thread_rwlock_unlock (&source->lock); return fserve_setup_client (client); } thread_rwlock_unlock (&source->lock); } else avl_tree_unlock (global.source_tree); return client_send_404 (client, "No image available"); }
// We pick a worker (consequetive) and set a max number of clients to move if needed void worker_balance_trigger (time_t now) { thread_rwlock_rlock (&workers_lock); if (worker_count > 1) { int log_counts = (now & 15) == 0 ? 1 : 0; worker_least_used = find_least_busy_handler (log_counts); if (worker_balance_to_check) { worker_balance_to_check->move_allocations = 50; worker_balance_to_check = worker_balance_to_check->next; } if (worker_balance_to_check == NULL) worker_balance_to_check = workers; } if (worker_incoming) worker_incoming->move_allocations = 2000000; // enforce a move away from this thread if possible thread_rwlock_unlock (&workers_lock); }
/* Add YP entries to active servers */ void yp_add (const char *mount) { struct yp_server *server; /* make sure YP thread is not modifying the lists */ thread_rwlock_rlock (&yp_lock); /* make sure we don't race against another yp_add */ thread_mutex_lock (&yp_pending_lock); server = (struct yp_server *)active_yps; while (server) { ypdata_t *yp; /* on-demand relays may already have a YP entry */ yp = find_yp_mount (server->mounts, mount); if (yp == NULL) { /* add new ypdata to each servers pending yp */ yp = create_yp_entry (mount); if (yp) { DEBUG2 ("Adding %s to %s", mount, server->url); yp->server = server; yp->touch_interval = server->touch_interval; yp->next = server->pending_mounts; yp->next_update = time(NULL) + 5; server->pending_mounts = yp; yp_update = 1; } } else DEBUG1 ("YP entry %s already exists", mount); server = server->next; } thread_mutex_unlock (&yp_pending_lock); thread_rwlock_unlock (&yp_lock); }
static int fserve_change_worker (client_t *client) { worker_t *this_worker = client->worker, *worker; int ret = 0; if (this_worker->move_allocations == 0 || worker_count < 2) return 0; thread_rwlock_rlock (&workers_lock); worker = worker_selected (); if (worker && worker != client->worker) { long diff = this_worker->count - worker->count; if (diff > 15) { this_worker->move_allocations--; ret = client_change_worker (client, worker); if (ret) DEBUG2 ("moving listener from %p to %p", this_worker, worker); } } thread_rwlock_unlock (&workers_lock); return ret; }
static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode) { htpasswd_auth_state *state; xmlNodePtr newnode; avl_node *node; state = auth->state; htpasswd_recheckfile (state); thread_rwlock_rlock (&state->file_rwlock); node = avl_get_first (state->users); while (node) { htpasswd_user *user = (htpasswd_user *)node->key; newnode = xmlNewChild (srcnode, NULL, "User", NULL); xmlNewChild(newnode, NULL, "username", user->name); xmlNewChild(newnode, NULL, "password", user->pass); node = avl_get_next (node); } thread_rwlock_unlock (&state->file_rwlock); return AUTH_OK; }
int xslt_transform (xmlDocPtr doc, const char *xslfilename, client_t *client) { xmlDocPtr res; xsltStylesheetPtr cur; int len, i; char **params = NULL; refbuf_t *content = NULL; client->shared_data = doc; thread_rwlock_rlock (&xslt_lock); i = xslt_cached (xslfilename, client); if (i < 0) { thread_rwlock_unlock (&xslt_lock); if (i == -2) { xmlFreeDoc (doc); client->shared_data = NULL; return client_send_404 (client, "Could not parse XSLT file"); } return 0; } cur = cache[i].stylesheet; client->shared_data = NULL; if (client->parser->queryvars) { // annoying but we need to surround the args with ' when passing them in int i, arg_count = client->parser->queryvars->length * 2; avl_node *node = avl_get_first (client->parser->queryvars); params = calloc (arg_count+1, sizeof (char *)); for (i = 0; node && i < arg_count; node = avl_get_next (node)) { http_var_t *param = (http_var_t *)node->key; char *tmp = util_url_escape (param->value); params[i++] = param->name; // use alloca for now, should really url esc into a supplied buffer params[i] = (char*)alloca (strlen (tmp) + 3); sprintf (params[i++], "\'%s\'", tmp); free (tmp); } params[i] = NULL; } res = xsltApplyStylesheet (cur, doc, (const char **)params); free (params); if (res == NULL || xslt_SaveResultToBuf (&content, &len, res, cur) < 0) { thread_rwlock_unlock (&xslt_lock); xmlFreeDoc (res); xmlFreeDoc (doc); WARN1 ("problem applying stylesheet \"%s\"", xslfilename); return client_send_404 (client, "XSLT problem"); } else { /* the 100 is to allow for the hardcoded headers */ refbuf_t *refbuf = refbuf_new (200); const char *mediatype = NULL; /* lets find out the content type to use */ if (cur->mediaType) mediatype = (char *)cur->mediaType; else { /* check method for the default, a missing method assumes xml */ if (cur->method && xmlStrcmp (cur->method, XMLSTR("html")) == 0) mediatype = "text/html"; else if (cur->method && xmlStrcmp (cur->method, XMLSTR("text")) == 0) mediatype = "text/plain"; else mediatype = "text/xml"; } snprintf (refbuf->data, 200, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n" "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" "Cache-Control: no-store, no-cache, must-revalidate\r\n" "Pragma: no-cache\r\n" "\r\n", mediatype, len); thread_rwlock_unlock (&xslt_lock); client->respcode = 200; client_set_queue (client, NULL); client->refbuf = refbuf; refbuf->len = strlen (refbuf->data); refbuf->next = content; } xmlFreeDoc(res); xmlFreeDoc(doc); return fserve_setup_client (client); }
ice_config_t *config_get_config(void) { thread_rwlock_rlock(&(_locks.config_lock)); return &_current_configuration; }
void avl_tree_rlock(avl_tree *tree) { thread_rwlock_rlock(&tree->rwlock); }
int redirect_client (const char *mountpoint, client_t *client) { int ret = 0, which; redirect_host *checking, **trail; thread_rwlock_rlock (&slaves_lock); /* select slave entry */ if (global.redirect_count == 0) { thread_rwlock_unlock (&slaves_lock); return 0; } which=(int) (((float)global.redirect_count)*rand()/(RAND_MAX+1.0)) + 1; checking = redirectors; trail = &redirectors; DEBUG2 ("random selection %d (out of %d)", which, global.redirect_count); while (checking) { DEBUG2 ("...%s:%d", checking->server, checking->port); if (checking->next_update && checking->next_update+10 < time(NULL)) { /* no streamist request, expire slave for now */ *trail = checking->next; global.redirect_count--; /* free slave details */ INFO2 ("dropping redirector for %s:%d", checking->server, checking->port); free (checking->server); free (checking); checking = *trail; if (which > 0) which--; /* we are 1 less now */ continue; } if (--which == 0) { char *location; /* add enough for "http://" the port ':' and nul */ int len = strlen (mountpoint) + strlen (checking->server) + 15; const char *user = client->username; const char *pass = client->password; const char *args = httpp_getvar (client->parser, HTTPP_VAR_QUERYARGS); const char *colon = ":", *at_sign = "@"; if (args) len += strlen (args); else args = ""; if (user && pass) len += strlen (user) + strlen (pass); else colon = at_sign = user = pass = ""; INFO2 ("redirecting listener to slave server at %s:%d", checking->server, checking->port); location = alloca (len); snprintf (location, len, "http://%s%s%s%s%s:%d%s%s", user, colon, pass, at_sign, checking->server, checking->port, mountpoint, args); client_send_302 (client, location); ret = 1; } trail = &checking->next; checking = checking->next; } thread_rwlock_unlock (&slaves_lock); return ret; }
void avl_node_rlock(avl_node *node) { thread_rwlock_rlock(&node->rwlock); }
/* 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 * doc even if the source is running */ xmlDocPtr admin_build_sourcelist (const char *mount, int show_listeners) { avl_node *node; source_t *source; xmlNodePtr xmlnode, srcnode; xmlDocPtr doc; char buf[22]; time_t now = time(NULL); doc = xmlNewDoc(XMLSTR("1.0")); xmlnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); xmlDocSetRootElement(doc, xmlnode); if (mount) { xmlNewChild(xmlnode, NULL, XMLSTR("current_source"), XMLSTR(mount)); } node = avl_get_first(global.source_tree); while(node) { source = (source_t *)node->key; if (mount && strcmp (mount, source->mount) == 0) { node = avl_get_next (node); continue; } thread_rwlock_rlock (&source->lock); if (source_available (source)) { ice_config_t *config; mount_proxy *mountinfo; srcnode = xmlNewChild (xmlnode, NULL, XMLSTR("source"), NULL); xmlSetProp (srcnode, XMLSTR("mount"), XMLSTR(source->mount)); snprintf (buf, sizeof(buf), "%lu", source->listeners); xmlNewChild (srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf)); config = config_get_config(); mountinfo = config_find_mount (config, source->mount); if (mountinfo) { if (mountinfo->auth) { xmlNewChild (srcnode, NULL, XMLSTR("authenticator"), XMLSTR(mountinfo->auth->type)); } if (mountinfo->fallback_mount) xmlNewChild (srcnode, NULL, XMLSTR("fallback"), XMLSTR(mountinfo->fallback_mount)); } config_release_config(); if (source_running (source)) { if (source->client) { snprintf (buf, sizeof(buf), "%lu", (unsigned long)(now - source->client->connection.con_time)); xmlNewChild (srcnode, NULL, XMLSTR("Connected"), XMLSTR(buf)); } xmlNewChild (srcnode, NULL, XMLSTR("content-type"), XMLSTR(source->format->contenttype)); if (show_listeners) admin_source_listeners (source, srcnode); } } thread_rwlock_unlock (&source->lock); node = avl_get_next(node); } return(doc); }
/* Perform any initialisation just before the stream data is processed, the header * info is processed by now and the format details are setup */ static void source_init (source_t *source) { ice_config_t *config = config_get_config(); char *listenurl; const char *str; int listen_url_size; mount_proxy *mountinfo; /* 6 for max size of port */ listen_url_size = strlen("http://") + strlen(config->hostname) + strlen(":") + 6 + strlen(source->mount) + 1; listenurl = malloc (listen_url_size); memset (listenurl, '\000', listen_url_size); snprintf (listenurl, listen_url_size, "http://%s%s", config->hostname, source->mount); config_release_config(); str = httpp_getvar(source->parser, "ice-audio-info"); source->audio_info = util_dict_new(); if (str) { _parse_audio_info (source, str); stats_event (source->mount, "audio_info", str); } stats_event (source->mount, "listenurl", listenurl); free(listenurl); if (source->dumpfilename != NULL) { source->dumpfile = fopen (source->dumpfilename, "ab"); if (source->dumpfile == NULL) { WARN2("Cannot open dump file \"%s\" for appending: %s, disabling.", source->dumpfilename, strerror(errno)); } } /* grab a read lock, to make sure we get a chance to cleanup */ thread_rwlock_rlock (source->shutdown_rwlock); /* start off the statistics */ source->listeners = 0; stats_event_inc (NULL, "source_total_connections"); stats_event (source->mount, "slow_listeners", "0"); stats_event_args (source->mount, "listeners", "%lu", source->listeners); stats_event_args (source->mount, "listener_peak", "%lu", source->peak_listeners); stats_event_time (source->mount, "stream_start"); DEBUG0("Source creation complete"); source->last_read = time (NULL); source->prev_listeners = -1; source->running = 1; mountinfo = config_find_mount (config_get_config(), source->mount); if (mountinfo) { if (mountinfo->on_connect) source_run_script (mountinfo->on_connect, source->mount); auth_stream_start (mountinfo, source->mount); } config_release_config(); /* ** Now, if we have a fallback source and override is on, we want ** to steal its clients, because it means we've come back online ** after a failure and they should be gotten back from the waiting ** loop or jingle track or whatever the fallback is used for */ if (source->fallback_override && source->fallback_mount) { source_t *fallback_source; avl_tree_rlock(global.source_tree); fallback_source = source_find_mount(source->fallback_mount); if (fallback_source) source_move_clients (fallback_source, source); avl_tree_unlock(global.source_tree); } }