/* wrapper for starting the provided relay stream */ static void check_relay_stream (relay_server *relay) { if (relay->source == NULL) { if (relay->localmount[0] != '/') { WARN1 ("relay mountpoint \"%s\" does not start with /, skipping", relay->localmount); return; } /* new relay, reserve the name */ relay->source = source_reserve (relay->localmount); if (relay->source) DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount); else WARN1 ("new relay but source \"%s\" already exists", relay->localmount); } if (relay->source && !relay->running) { relay->thread = thread_create ("Relay Thread", start_relay_stream, relay, THREAD_ATTACHED); return; } /* the relay thread may of close down */ if (relay->cleanup && relay->thread) { DEBUG1 ("waiting for relay thread for \"%s\"", relay->localmount); thread_join (relay->thread); relay->thread = NULL; relay->cleanup = 0; relay->running = 0; } }
static void _handle_source_request (client_t *client, char *uri, int auth_style) { source_t *source; INFO1("Source logging in at mountpoint \"%s\"", uri); if (uri[0] != '/') { WARN0 ("source mountpoint not starting with /"); client_send_401 (client); return; } if (auth_style == ICECAST_SOURCE_AUTH) { if (connection_check_source_pass (client->parser, uri) == 0) { /* We commonly get this if the source client is using the wrong * protocol: attempt to diagnose this and return an error */ /* TODO: Do what the above comment says */ INFO1("Source (%s) attempted to login with invalid or missing password", uri); client_send_401(client); return; } } source = source_reserve (uri); if (source) { if (auth_style == SHOUTCAST_SOURCE_AUTH) { source->shoutcast_compat = 1; } source->client = client; source->parser = client->parser; source->con = client->con; if (connection_complete_source (source, 1) < 0) { source_clear_source (source); source_free_source (source); } else { refbuf_t *ok = refbuf_new (PER_CLIENT_REFBUF_SIZE); client->respcode = 200; snprintf (ok->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\n\r\n"); ok->len = strlen (ok->data); /* we may have unprocessed data read in, so don't overwrite it */ ok->associated = client->refbuf; client->refbuf = ok; fserve_add_client_callback (client, source_client_callback, source); } } else { client_send_404 (client, "Mountpoint in use"); WARN1 ("Mountpoint %s in use", uri); } }
static void _handle_source_request(connection_t *con, http_parser_t *parser, char *uri) { client_t *client; source_t *source; client = client_create(con, parser); INFO1("Source logging in at mountpoint \"%s\"", uri); if (uri[0] != '/') { WARN0 ("source mountpoint not starting with /"); client_send_401 (client); return; } if (!connection_check_source_pass(parser, uri)) { /* We commonly get this if the source client is using the wrong * protocol: attempt to diagnose this and return an error */ /* TODO: Do what the above comment says */ INFO1("Source (%s) attempted to login with invalid or missing password", uri); client_send_401(client); return; } source = source_reserve (uri); if (source) { source->client = client; source->parser = parser; source->con = con; if (connection_complete_source (source) < 0) { source->client = NULL; source_free_source (source); } else thread_create ("Source Thread", source_client_thread, source, THREAD_DETACHED); } else { client_send_404 (client, "Mountpoint in use"); WARN1 ("Mountpoint %s in use", uri); } }
void source_startup (client_t *client, const char *uri, int auth_style) { source_t *source; refbuf_t *ok; source = source_reserve (uri); if (!source) { client_send_403 (client, "Mountpoint in use"); WARN1 ("Mountpoint %s in use", uri); return; } source->client = client; source->parser = client->parser; source->con = client->con; if (connection_complete_source (source, 1) < 0) { source_clear_source (source); source_free_source (source); return; } client->respcode = 200; switch (auth_style) { case SHOUTCAST_SOURCE_AUTH: source->shoutcast_compat = 1; case NOAUTH_SOURCE_AUTH: break; case ICECAST_SOURCE_AUTH: ok = refbuf_new (PER_CLIENT_REFBUF_SIZE); client->respcode = 200; snprintf (ok->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\n\r\n"); ok->len = strlen (ok->data); /* we may have unprocessed data read in, so don't overwrite it */ ok->associated = client->refbuf; client->refbuf = ok; break; default: WARN1("Got unkown source auth type: %d", auth_style); return; } fserve_add_client_callback (client, source_client_callback, source); }
/* wrapper for starting the provided relay stream */ static void check_relay_stream (relay_server *relay) { if (relay->source == NULL) { if (relay->localmount[0] != '/') { ICECAST_LOG_WARN("relay mountpoint \"%s\" does not start with /, skipping", relay->localmount); return; } /* new relay, reserve the name */ relay->source = source_reserve (relay->localmount); if (relay->source) { ICECAST_LOG_DEBUG("Adding relay source at mountpoint \"%s\"", relay->localmount); if (relay->on_demand) { ice_config_t *config = config_get_config (); mount_proxy *mountinfo = config_find_mount (config, relay->localmount, MOUNT_TYPE_NORMAL); relay->source->on_demand = relay->on_demand; if (mountinfo == NULL) source_update_settings (config, relay->source, mountinfo); config_release_config (); stats_event (relay->localmount, "listeners", "0"); slave_update_all_mounts(); } } else { if (relay->start == 0) { ICECAST_LOG_WARN("new relay but source \"%s\" already exists", relay->localmount); relay->start = 1; } return; } } do { source_t *source = relay->source; /* skip relay if active, not configured or just not time yet */ if (relay->source == NULL || relay->running || relay->start > time(NULL)) break; /* check if an inactive on-demand relay has a fallback that has listeners */ if (relay->on_demand && source->on_demand_req == 0) { relay->source->on_demand = relay->on_demand; if (source->fallback_mount && source->fallback_override) { source_t *fallback; avl_tree_rlock (global.source_tree); fallback = source_find_mount (source->fallback_mount); if (fallback && fallback->running && fallback->listeners) { ICECAST_LOG_DEBUG("fallback running %d with %lu listeners", fallback->running, fallback->listeners); source->on_demand_req = 1; } avl_tree_unlock (global.source_tree); } if (source->on_demand_req == 0) break; } relay->start = time(NULL) + 5; relay->running = 1; relay->thread = thread_create ("Relay Thread", start_relay_stream, relay, THREAD_ATTACHED); return; } while (0); /* the relay thread may of shut down itself */ if (relay->cleanup) { if (relay->thread) { ICECAST_LOG_DEBUG("waiting for relay thread for \"%s\"", relay->localmount); thread_join (relay->thread); relay->thread = NULL; } relay->cleanup = 0; relay->running = 0; if (relay->on_demand && relay->source) { ice_config_t *config = config_get_config (); mount_proxy *mountinfo = config_find_mount (config, relay->localmount, MOUNT_TYPE_NORMAL); source_update_settings (config, relay->source, mountinfo); config_release_config (); stats_event (relay->localmount, "listeners", "0"); } } }
static void *source_fallback_file (void *arg) { char *mount = arg; char *type; char *path; unsigned int len; FILE *file = NULL; source_t *source = NULL; ice_config_t *config; http_parser_t *parser; do { if (mount == NULL || mount[0] != '/') break; config = config_get_config(); len = strlen (config->webroot_dir) + strlen (mount) + 1; path = malloc (len); if (path) snprintf (path, len, "%s%s", config->webroot_dir, mount); config_release_config (); if (path == NULL) break; file = fopen (path, "rb"); if (file == NULL) { WARN1 ("unable to open file \"%s\"", path); free (path); break; } free (path); source = source_reserve (mount); if (source == NULL) { WARN1 ("mountpoint \"%s\" already reserved", mount); break; } INFO1 ("mountpoint %s is reserved", mount); type = fserve_content_type (mount); parser = httpp_create_parser(); httpp_initialize (parser, NULL); httpp_setvar (parser, "content-type", type); free (type); source->hidden = 1; source->yp_public = 0; source->intro_file = file; source->parser = parser; file = NULL; if (connection_complete_source (source, 0) < 0) break; source_client_thread (source); httpp_destroy (parser); } while (0); if (file) fclose (file); free (mount); return NULL; }