static void *start_relay_stream (void *arg) { client_t *client = arg; relay_server *relay; source_t *src; int failed = 1, sources; global_lock(); sources = ++global.sources; stats_event_args (NULL, "sources", "%d", global.sources); global_unlock(); /* set the start time, because we want to decrease the sources on all failures */ client->connection.con_time = time (NULL); do { ice_config_t *config = config_get_config(); mount_proxy *mountinfo; relay = client->shared_data; src = relay->source; thread_rwlock_wlock (&src->lock); src->flags |= SOURCE_PAUSE_LISTENERS; if (sources > config->source_limit) { config_release_config(); WARN1 ("starting relayed mountpoint \"%s\" requires a higher sources limit", relay->localmount); break; } config_release_config(); INFO1("Starting relayed source at mountpoint \"%s\"", relay->localmount); if (open_relay (relay) < 0) break; if (connection_complete_source (src) < 0) { WARN1 ("Failed to complete initialisation on %s", relay->localmount); break; } stats_event_inc (NULL, "source_relay_connections"); source_init (src); config = config_get_config(); mountinfo = config_find_mount (config, src->mount); source_update_settings (config, src, mountinfo); INFO1 ("source %s is ready to start", src->mount); config_release_config(); failed = 0; } while (0); client->ops = &relay_client_ops; client->schedule_ms = timing_get_time(); if (failed) { /* failed to start any connection, better clean up and reset */ if (relay->on_demand == 0) { yp_remove (relay->localmount); src->yp_public = -1; } relay->in_use = NULL; INFO2 ("listener count remaining on %s is %d", src->mount, src->listeners); src->flags &= ~(SOURCE_PAUSE_LISTENERS|SOURCE_RUNNING); } thread_rwlock_unlock (&src->lock); thread_spin_lock (&relay_start_lock); relays_connecting--; thread_spin_unlock (&relay_start_lock); client->flags |= CLIENT_ACTIVE; worker_wakeup (client->worker); return NULL; }
static int xslt_req_sheet (client_t *client, xmlDocPtr doc, const char *fn, int i) { xsl_req *x = client->shared_data; worker_t *worker = client->worker; time_t now = worker->current_time.tv_sec; struct stat file; // DEBUG4 ("idx %d, fn %s, check %ld/%ld", i, i==CACHESIZE?"XXX":cache[i].filename, (long)cache[i].next_check, now); while (i < CACHESIZE && i >= 0 && cache[i].filename && cache[i].next_check >= now) { thread_spin_lock (&update_lock); if (now == cache[i].next_check) { cache[i].next_check = now + 20; thread_spin_unlock (&update_lock); break; // jump out of loop to do xsl load } thread_spin_unlock (&update_lock); return i; } if (stat (fn, &file)) { WARN2("Error checking for stylesheet file \"%s\": %s", fn, strerror(errno)); return -1; } if (i < CACHESIZE && i >= 0) { thread_spin_lock (&update_lock); cache[i].next_check = now + 20; if (file.st_mtime == cache[i].last_modified) { thread_spin_unlock (&update_lock); DEBUG1 ("file %s has same mtime, not modified", cache[i].filename); return i; } thread_spin_unlock (&update_lock); // DEBUG3 ("idx %d, time is %ld, %ld", i, (long)(cache[i].last_modified), (long)file.st_mtime); } if (x == NULL) { x = calloc (1, sizeof (xsl_req)); x->index = i; x->client = client; x->doc = doc; x->cache.filename = strdup (fn); x->cache.last_modified = file.st_mtime; x->cache.cache_age = now; x->cache.next_check = now + 20; client->shared_data = x; client->schedule_ms = worker->time_ms; client->ops = &xslt_ops; } thread_spin_lock (&update_lock); if (xsl_updating < 3) { xsl_updating++; thread_spin_unlock (&update_lock); client->flags &= ~CLIENT_ACTIVE; // DEBUG1 ("Starting update thread for %s", x->cache.filename); thread_create ("update xslt", xslt_update, x, THREAD_DETACHED); return CACHESIZE; } thread_spin_unlock (&update_lock); // DEBUG1 ("Delaying update thread for %s", x->cache.filename); client->schedule_ms += 10; if ((client->flags & CLIENT_ACTIVE) == 0) { client->flags |= CLIENT_ACTIVE; worker_wakeup (worker); } return CACHESIZE; }
int fserve_setup_client_fb (client_t *client, fbinfo *finfo) { fh_node *fh = &no_file; int ret = 0; if (finfo) { mount_proxy *minfo; if (finfo->flags & FS_FALLBACK && finfo->limit == 0) return -1; avl_tree_wlock (fh_cache); fh = find_fh (finfo); minfo = config_find_mount (config_get_config(), finfo->mount); if (fh) { thread_mutex_lock (&fh->lock); avl_tree_unlock (fh_cache); client->shared_data = NULL; if (minfo) { if (minfo->max_listeners >= 0 && fh->refcount > minfo->max_listeners) { thread_mutex_unlock (&fh->lock); config_release_config(); return client_send_403redirect (client, finfo->mount, "max listeners reached"); } if (check_duplicate_logins (finfo->mount, fh->clients, client, minfo->auth) == 0) { thread_mutex_unlock (&fh->lock); config_release_config(); return client_send_403 (client, "Account already in use"); } } config_release_config(); } else { if (minfo && minfo->max_listeners == 0) { avl_tree_unlock (fh_cache); config_release_config(); client->shared_data = NULL; return client_send_403redirect (client, finfo->mount, "max listeners reached"); } config_release_config(); fh = open_fh (finfo); if (fh == NULL) return client_send_404 (client, NULL); if (fh->finfo.limit) DEBUG2 ("request for throttled file %s (bitrate %d)", fh->finfo.mount, fh->finfo.limit*8); } if (fh->finfo.limit) { client->timer_start = client->worker->current_time.tv_sec; if (client->connection.sent_bytes == 0) client->timer_start -= 2; client->counter = 0; global_reduce_bitrate_sampling (global.out_bitrate); } } else { if (client->mount && (client->flags & CLIENT_AUTHENTICATED) && (client->respcode >= 300 || client->respcode < 200)) { fh = calloc (1, sizeof (no_file)); fh->finfo.mount = strdup (client->mount); fh->finfo.flags |= FS_DELETE; fh->refcount = 1; fh->f = SOCK_ERROR; thread_mutex_create (&fh->lock); } thread_mutex_lock (&fh->lock); } client->mount = fh->finfo.mount; if (fh->finfo.type == FORMAT_TYPE_UNDEFINED) { if (client->respcode == 0) { client->refbuf->len = 0; ret = format_general_headers (fh->format, client); } } else { if (fh->format->create_client_data && client->format_data == NULL) ret = fh->format->create_client_data (fh->format, client); if (fh->format->write_buf_to_client) client->check_buffer = fh->format->write_buf_to_client; } if (ret < 0) { thread_mutex_unlock (&fh->lock); return client_send_416 (client); } fh_add_client (fh, client); thread_mutex_unlock (&fh->lock); client->shared_data = fh; if (client->check_buffer == NULL) client->check_buffer = format_generic_write_to_client; client->ops = &buffer_content_ops; client->flags &= ~CLIENT_HAS_INTRO_CONTENT; client->flags |= CLIENT_IN_FSERVE; if (client->flags & CLIENT_ACTIVE) { client->schedule_ms = client->worker->time_ms; if (finfo && finfo->flags & FS_FALLBACK) return 0; // prevent a recursive loop return client->ops->process (client); } else { worker_t *worker = client->worker; ret = (fh->finfo.limit) ? 0 : -1; client->flags |= CLIENT_ACTIVE; worker_wakeup (worker); /* worker may of already processed client but make sure */ } return ret; }
static int command_manage_relay (client_t *client, int response) { const char *relay_mount, *enable; const char *msg; relay_server *relay; xmlDocPtr doc; xmlNodePtr node; COMMAND_OPTIONAL (client, "relay", relay_mount); COMMAND_OPTIONAL (client, "enable", enable); if (relay_mount == NULL || enable == NULL) { avl_node *relaynode; doc = xmlNewDoc (XMLSTR("1.0")); node = xmlNewDocNode (doc, NULL, XMLSTR("icerelaystats"), NULL); xmlDocSetRootElement(doc, node); avl_tree_rlock (global.relays); relaynode = avl_get_first (global.relays); while (relaynode) { relay_server *relay = (relay_server*)relaynode->key; add_relay_xmlnode (node, relay); relaynode = avl_get_next (relaynode); } avl_tree_unlock (global.relays); return admin_send_response (doc, client, response, "managerelays.xsl"); } avl_tree_rlock (global.relays); relay = slave_find_relay (relay_mount); msg = "no such relay"; if (relay) { source_t *source = relay->source; client_t *client; thread_rwlock_wlock (&source->lock); client = source->client; if (atoi (enable)) relay->flags |= RELAY_RUNNING; else relay->flags &= ~RELAY_RUNNING; if (client) { client->schedule_ms = 0; worker_wakeup (client->worker); } thread_rwlock_unlock (&source->lock); msg = "relay has been changed"; } avl_tree_unlock (global.relays); doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(msg)); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); }