/* find/create handle and return it with the structure in a locked state */ static fh_node *open_fh (fbinfo *finfo) { fh_node *fh, *result; if (finfo->mount == NULL) finfo->mount = ""; fh = calloc (1, sizeof (fh_node)); memcpy (&fh->finfo, finfo, sizeof (fbinfo)); if (avl_get_by_key (fh_cache, fh, (void**)&result) == 0) { free (fh); thread_mutex_lock (&result->lock); avl_tree_unlock (fh_cache); if (finfo->flags & FS_FALLBACK) { if (result->finfo.type != finfo->type && finfo->type != FORMAT_TYPE_UNDEFINED) { WARN1 ("format mismatched for %s", finfo->mount); thread_mutex_unlock (&result->lock); return NULL; } result->expire = (time_t)-1; } return result; } // insert new one if (fh->finfo.mount[0]) { char *fullpath= util_get_path_from_normalised_uri (fh->finfo.mount, fh->finfo.flags&FS_USE_ADMIN); char *contenttype = fserve_content_type (fullpath); format_type_t type = format_get_type (contenttype); if (fh->finfo.type == FORMAT_TYPE_UNDEFINED) fh->finfo.type = type; if (finfo->flags & FS_FALLBACK) { if (fh->finfo.type != type && type != FORMAT_TYPE_UNDEFINED && fh->finfo.type != FORMAT_TYPE_UNDEFINED) { avl_tree_unlock (fh_cache); free (contenttype); free (fullpath); free (fh); WARN1 ("format mismatched for %s", finfo->mount); return NULL; } fh->expire = (time_t)-1; INFO2 ("lookup of fallback file \"%s\" (%d)", finfo->mount, finfo->limit); } else INFO1 ("lookup of \"%s\"", finfo->mount); if (file_open (&fh->f, fullpath) < 0) { INFO1 ("Failed to open \"%s\"", fullpath); avl_tree_unlock (fh_cache); free (contenttype); free (fullpath); free (fh); return NULL; } free (fullpath); fh->format = calloc (1, sizeof (format_plugin_t)); fh->format->type = fh->finfo.type; fh->format->contenttype = strdup (contenttype); free (contenttype); if (fh->finfo.type != FORMAT_TYPE_UNDEFINED) { fh->format->mount = strdup (fh->finfo.mount); if (format_get_plugin (fh->format) < 0) { avl_tree_unlock (fh_cache); file_close (&fh->f); free (fh->format); free (fh); return NULL; } } if (fh->finfo.limit) fh->out_bitrate = rate_setup (10000, 1000); } fh->clients = avl_tree_new (client_compare, NULL); thread_mutex_create (&fh->lock); thread_mutex_lock (&fh->lock); avl_insert (fh_cache, fh); avl_tree_unlock (fh_cache); fh->refcount = 0; fh->peak = 0; fh->finfo.mount = strdup (finfo->mount); fh->finfo.fallback = NULL; return fh; }
/* Called when activating a source. Verifies that the source count is not * exceeded and applies any initial parameters. */ int connection_complete_source (source_t *source, int response) { ice_config_t *config = config_get_config(); global_lock (); DEBUG1 ("sources count is %d", global.sources); if (global.sources < config->source_limit) { char *contenttype; mount_proxy *mountinfo; format_type_t format_type; /* setup format handler */ contenttype = httpp_getvar (source->parser, "content-type"); if (contenttype != NULL) { format_type = format_get_type (contenttype); if (format_type == FORMAT_ERROR) { global_unlock(); config_release_config(); if (response) { client_send_404 (source->client, "Content-type not supported"); source->client = NULL; } WARN1("Content-type \"%s\" not supported, dropping source", contenttype); return -1; } } else { WARN0("No content-type header, falling back to backwards compatibility mode " "for icecast 1.x relays. Assuming content is mp3."); format_type = FORMAT_TYPE_GENERIC; } if (format_get_plugin (format_type, source) < 0) { global_unlock(); config_release_config(); if (response) { client_send_404 (source->client, "internal format allocation problem"); source->client = NULL; } WARN1 ("plugin format failed for \"%s\"", source->mount); return -1; } global.sources++; stats_event_args (NULL, "sources", "%d", global.sources); global_unlock(); source->running = 1; mountinfo = config_find_mount (config, source->mount); if (mountinfo == NULL) source_update_settings (config, source, mountinfo); source_recheck_mounts (); config_release_config(); source->shutdown_rwlock = &_source_shutdown_rwlock; DEBUG0 ("source is ready to start"); return 0; } WARN1("Request to add source when maximum source limit " "reached %d", global.sources); global_unlock(); config_release_config(); if (response) { client_send_404 (source->client, "too many sources connected"); source->client = NULL; } return -1; }
/* Called when activating a source. Verifies that the source count is not * exceeded and applies any initial parameters. */ int connection_complete_source (source_t *source, int response) { ice_config_t *config; global_lock (); DEBUG1 ("sources count is %d", global.sources); config = config_get_config(); if (global.sources < config->source_limit) { const char *contenttype; const char *expectcontinue; mount_proxy *mountinfo; format_type_t format_type; /* setup format handler */ contenttype = httpp_getvar (source->parser, "content-type"); if (contenttype != NULL) { format_type = format_get_type (contenttype); if (format_type == FORMAT_ERROR) { config_release_config(); global_unlock(); if (response) { client_send_403 (source->client, "Content-type not supported"); source->client = NULL; } WARN1("Content-type \"%s\" not supported, dropping source", contenttype); return -1; } } else { WARN0("No content-type header, falling back to backwards compatibility mode " "for icecast 1.x relays. Assuming content is mp3."); format_type = FORMAT_TYPE_GENERIC; } if (format_get_plugin (format_type, source) < 0) { global_unlock(); config_release_config(); if (response) { client_send_403 (source->client, "internal format allocation problem"); source->client = NULL; } WARN1 ("plugin format failed for \"%s\"", source->mount); return -1; } /* For PUT support we check for 100-continue and send back a 100 to stay in spec */ expectcontinue = httpp_getvar (source->parser, "expect"); if (expectcontinue != NULL) { #ifdef HAVE_STRCASESTR if (strcasestr (expectcontinue, "100-continue") != NULL) #else WARN0("OS doesn't support case insenestive substring checks..."); if (strstr (expectcontinue, "100-continue") != NULL) #endif { client_send_100 (source->client); } } global.sources++; stats_event_args (NULL, "sources", "%d", global.sources); global_unlock(); source->running = 1; mountinfo = config_find_mount (config, source->mount, MOUNT_TYPE_NORMAL); source_update_settings (config, source, mountinfo); config_release_config(); slave_rebuild_mounts(); source->shutdown_rwlock = &_source_shutdown_rwlock; DEBUG0 ("source is ready to start"); return 0; } WARN1("Request to add source when maximum source limit " "reached %d", global.sources); global_unlock(); config_release_config(); if (response) { client_send_403 (source->client, "too many sources connected"); source->client = NULL; } return -1; }
/* Called when activating a source. Verifies that the source count is not * exceeded and applies any initial parameters. */ int connection_complete_source (source_t *source) { ice_config_t *config = config_get_config(); global_lock (); DEBUG1 ("sources count is %d", global.sources); if (global.sources < config->source_limit) { char *contenttype; mount_proxy *mountproxy = config->mounts; format_type_t format_type; /* setup format handler */ contenttype = httpp_getvar (source->parser, "content-type"); if (contenttype != NULL) { format_type = format_get_type (contenttype); if (format_type == FORMAT_ERROR) { global_unlock(); config_release_config(); if (source->client) client_send_404 (source->client, "Content-type not supported"); WARN1("Content-type \"%s\" not supported, dropping source", contenttype); return -1; } } else { WARN0("No content-type header, falling back to backwards compatibility mode " "for icecast 1.x relays. Assuming content is mp3."); format_type = FORMAT_TYPE_MP3; } if (format_get_plugin (format_type, source) < 0) { global_unlock(); config_release_config(); if (source->client) client_send_404 (source->client, "internal format allocation problem"); WARN1 ("plugin format failed for \"%s\"", source->mount); return -1; } global.sources++; global_unlock(); /* set global settings first */ source->queue_size_limit = config->queue_size_limit; source->timeout = config->source_timeout; source->burst_size = config->burst_size; /* for relays, we don't yet have a client, however we do require one * to retrieve the stream from. This is created here, quite late, * because we can't use this client to return an error code/message, * so we only do this once we know we're going to accept the source. */ if (source->client == NULL) source->client = client_create (source->con, source->parser); while (mountproxy) { if (strcmp (mountproxy->mountname, source->mount) == 0) { source_apply_mount (source, mountproxy); break; } mountproxy = mountproxy->next; } config_release_config(); source->shutdown_rwlock = &_source_shutdown_rwlock; DEBUG0 ("source is ready to start"); return 0; } WARN1("Request to add source when maximum source limit " "reached %d", global.sources); global_unlock(); config_release_config(); if (source->client) client_send_404 (source->client, "too many sources connected"); return -1; }