static int command_list_log (client_t *client, int response) { refbuf_t *content; const char *logname = httpp_get_query_param (client->parser, "log"); int log = -1; ice_config_t *config; if (logname == NULL) return client_send_400 (client, "No log specified"); config = config_get_config (); if (strcmp (logname, "errorlog") == 0) log = config->error_log.logid; else if (strcmp (logname, "accesslog") == 0) log = config->access_log.logid; else if (strcmp (logname, "playlistlog") == 0) log = config->playlist_log.logid; if (log < 0) { config_release_config(); WARN1 ("request to show unknown log \"%s\"", logname); return client_send_400 (client, "unknown"); } content = refbuf_new (0); log_contents (log, &content->data, &content->len); config_release_config(); if (response == XSLT) { xmlNodePtr xmlnode; xmlDocPtr doc; doc = xmlNewDoc(XMLSTR("1.0")); xmlnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); xmlDocSetRootElement(doc, xmlnode); xmlNewTextChild (xmlnode, NULL, XMLSTR("log"), XMLSTR(content->data)); refbuf_release (content); return admin_send_response (doc, client, XSLT, "showlog.xsl"); } else { refbuf_t *http = refbuf_new (100); int len = snprintf (http->data, 100, "%s", "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n"); http->len = len; http->next = content; client->respcode = 200; client_set_queue (client, http); return fserve_setup_client (client); } }
static void url_stream_end (auth_client *auth_user) { char *mount, *server; ice_config_t *config = config_get_config (); mount_proxy *mountinfo = config_find_mount (config, auth_user->mount, MOUNT_TYPE_NORMAL); auth_t *auth = mountinfo->auth; auth_url *url = auth->state; char *stream_end_url; int port; char post [4096]; if (url->stream_end == NULL) { config_release_config (); return; } server = util_url_escape (config->hostname); port = config->port; stream_end_url = strdup (url->stream_end); /* we don't want this auth disappearing from under us while * the connection is in progress */ mountinfo->auth->refcount++; config_release_config (); mount = util_url_escape (auth_user->mount); snprintf (post, sizeof (post), "action=mount_remove&mount=%s&server=%s&port=%d", mount, server, port); free (server); free (mount); if (strchr (url->stream_end, '@') == NULL) { if (url->userpwd) curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd); else curl_easy_setopt (url->handle, CURLOPT_USERPWD, ""); } else curl_easy_setopt (url->handle, CURLOPT_USERPWD, ""); curl_easy_setopt (url->handle, CURLOPT_URL, url->stream_end); curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post); curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user); if (curl_easy_perform (url->handle)) ICECAST_LOG_WARN("auth to server %s failed with %s", stream_end_url, url->errormsg); auth_release (auth); free (stream_end_url); return; }
static void command_buildm3u(client_t *client, source_t *source, int response) { char *username = NULL; char *password = NULL; char *host = NULL; int port = 0; ice_config_t *config; COMMAND_REQUIRE(client, "username", username); COMMAND_REQUIRE(client, "password", password); config = config_get_config(); host = strdup(config->hostname); port = config->port; config_release_config(); client->respcode = 200; sock_write(client->con->sock, "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n" "Content-Disposition = attachment; filename=listen.m3u\r\n\r\n" "http://%s:%s@%s:%d%s\r\n", username, password, host, port, source->mount ); free(host); client_destroy(client); }
/* create a client_t with the provided connection and parser details. Return * 0 on success, -1 if server limit has been reached. In either case a * client_t is returned just in case a message needs to be returned. Should * be called with global lock held. */ int client_create (client_t **c_ptr, connection_t *con, http_parser_t *parser) { ice_config_t *config; client_t *client = (client_t *)calloc(1, sizeof(client_t)); int ret = -1; if (client == NULL) abort(); config = config_get_config (); global.clients++; if (config->client_limit < global.clients) WARN2 ("server client limit reached (%d/%d)", config->client_limit, global.clients); else ret = 0; config_release_config (); stats_event_args (NULL, "clients", "%d", global.clients); client->con = con; client->parser = parser; client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); client->refbuf->len = 0; /* force reader code to ignore buffer contents */ client->pos = 0; client->write_to_client = format_generic_write_to_client; *c_ptr = client; return ret; }
static void command_buildm3u(client_t *client, const char *mount) { const char *username = NULL; const char *password = NULL; ice_config_t *config; COMMAND_REQUIRE(client, "username", username); COMMAND_REQUIRE(client, "password", password); client->respcode = 200; config = config_get_config(); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n" "Content-Disposition = attachment; filename=listen.m3u\r\n\r\n" "http://%s:%s@%s:%d%s\r\n", username, password, config->hostname, config->port, mount ); config_release_config(); client->refbuf->len = strlen (client->refbuf->data); fserve_add_client (client, NULL); }
static void file_release (client_t *client) { fh_node *fh = client->shared_data; int ret = -1; if (fh->finfo.flags & FS_FALLBACK) stats_event_dec (NULL, "listeners"); remove_from_fh (fh, client); client_set_queue (client, NULL); if (client->flags & CLIENT_AUTHENTICATED && client->parser->req_type == httpp_req_get) { const char *mount = httpp_getvar (client->parser, HTTPP_VAR_URI); ice_config_t *config = config_get_config (); mount_proxy *mountinfo = config_find_mount (config, mount); if (mountinfo && mountinfo->access_log.name) logging_access_id (&mountinfo->access_log, client); ret = auth_release_listener (client, mount, mountinfo); config_release_config(); } if (ret < 0) { client->flags &= ~CLIENT_AUTHENTICATED; client_destroy (client); } global_reduce_bitrate_sampling (global.out_bitrate); }
static int auth_postprocess_listener (auth_client *auth_user) { int ret; client_t *client = auth_user->client; auth_t *auth = auth_user->auth; ice_config_t *config; mount_proxy *mountinfo; const char *mount = auth_user->mount; if (client == NULL) return 0; if ((client->flags & CLIENT_AUTHENTICATED) == 0) { /* auth failed so do we place the listener elsewhere */ auth_user->client = NULL; if (auth->rejected_mount) mount = auth->rejected_mount; else { client_send_401 (client, auth_user->auth->realm); return -1; } } config = config_get_config(); mountinfo = config_find_mount (config, mount); ret = add_authenticated_listener (mount, mountinfo, client); config_release_config(); auth_user->client = NULL; return ret; }
void fserve_initialize(void) { if (fserve_running) return; ice_config_t *config = config_get_config(); mimetypes = NULL; thread_spin_create (&pending_lock); #ifndef HAVE_PREAD thread_mutex_create (&seekread_lock); #endif fh_cache = avl_tree_new (_compare_fh, NULL); fserve_recheck_mime_types (config); config_release_config(); stats_event_flags (NULL, "file_connections", "0", STATS_COUNTERS); fserve_running = 1; memset (&no_file, 0, sizeof (no_file)); thread_mutex_create (&no_file.lock); no_file.clients = avl_tree_new (client_compare, NULL); no_file.refcount = 1; no_file.expire = (time_t)-1; no_file.f = -1; avl_insert (fh_cache, &no_file); INFO0("file serving started"); }
/* return -1 for failed, 0 for authenticated, 1 for pending */ int client_check_source_auth (client_t *client, const char *mount) { ice_config_t *config = config_get_config(); char *pass = config->source_password; char *user = "******"; int ret = -1; mount_proxy *mountinfo = config_find_mount (config, mount, MOUNT_TYPE_NORMAL); do { if (mountinfo) { ret = 1; if (auth_stream_authenticate (client, mount, mountinfo) > 0) break; ret = -1; if (mountinfo->password) pass = mountinfo->password; if (mountinfo->username) user = mountinfo->username; } if (connection_check_pass (client->parser, user, pass) > 0) ret = 0; } while (0); config_release_config(); return ret; }
/* Search for mount, if the mount is there but not currently running then * check the fallback, and so on. Must have a global source lock to call * this function. */ source_t *source_find_mount (const char *mount) { source_t *source = NULL; ice_config_t *config; mount_proxy *mountinfo; int depth = 0; config = config_get_config(); while (mount && depth < MAX_FALLBACK_DEPTH) { source = source_find_mount_raw(mount); if (source) { if (source->running || source->on_demand) break; } /* we either have a source which is not active (relay) or no source * at all. Check the mounts list for fallback settings */ mountinfo = config_find_mount (config, mount); source = NULL; if (mountinfo == NULL) break; mount = mountinfo->fallback_mount; depth++; } config_release_config(); return source; }
int connection_check_relay_pass(http_parser_t *parser) { int ret; ice_config_t *config = config_get_config(); char *pass = config->relay_password; char *user = config->relay_username; if(!pass || !user) { config_release_config(); return 0; } ret = _check_pass_http(parser, user, pass); config_release_config(); return ret; }
int connection_check_source_pass(http_parser_t *parser, char *mount) { ice_config_t *config = config_get_config(); char *pass = config->source_password; char *user = "******"; int ret; int ice_login = config->ice_login; char *protocol; mount_proxy *mountinfo = config->mounts; thread_mutex_lock(&(config_locks()->mounts_lock)); while(mountinfo) { if(!strcmp(mountinfo->mountname, mount)) { if(mountinfo->password) pass = mountinfo->password; if(mountinfo->username) user = mountinfo->username; break; } mountinfo = mountinfo->next; } thread_mutex_unlock(&(config_locks()->mounts_lock)); if(!pass) { WARN0("No source password set, rejecting source"); config_release_config(); return 0; } protocol = httpp_getvar(parser, HTTPP_VAR_PROTOCOL); if(protocol != NULL && !strcmp(protocol, "ICY")) { ret = _check_pass_icy(parser, pass); } else { ret = _check_pass_http(parser, user, pass); if(!ret && ice_login) { ret = _check_pass_ice(parser, pass); if(ret) WARN0("Source is using deprecated icecast login"); } } config_release_config(); return ret; }
void json_stats_stop(const char *mount) { ice_config_t *config = config_get_config(); if (config->json_stats_dir) { unlink(json_filename(config->json_stats_dir, mount)); } config_release_config(); }
static ypdata_t *create_yp_entry (const char *mount) { ypdata_t *yp; char *s; yp = calloc (1, sizeof (ypdata_t)); do { unsigned len = 512; int ret; char *url; mount_proxy *mountproxy = NULL; ice_config_t *config; if (yp == NULL) break; yp->mount = strdup (mount); yp->server_name = strdup (""); yp->server_desc = strdup (""); yp->server_genre = strdup (""); yp->bitrate = strdup (""); yp->server_type = strdup (""); yp->cluster_password = strdup (""); yp->url = strdup (""); yp->current_song = strdup (""); yp->audio_info = strdup (""); yp->subtype = strdup (""); yp->process = do_yp_add; url = malloc (len); if (url == NULL) break; config = config_get_config(); ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, mount); if (ret >= (signed)len) { s = realloc (url, ++ret); if (s) url = s; snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, mount); } mountproxy = config_find_mount (config, mount); if (mountproxy && mountproxy->cluster_password) add_yp_info (yp, mountproxy->cluster_password, YP_CLUSTER_PASSWORD); config_release_config(); yp->listen_url = util_url_escape (url); free (url); if (yp->listen_url == NULL) break; yp_schedule (yp, 0); return yp; } while (0); yp_destroy_ypdata (yp); return NULL; }
void yp_initialize() { ice_config_t *config = config_get_config(); thread_rwlock_create (&yp_lock); thread_mutex_create (&yp_pending_lock); yp_recheck_config (config); config_release_config (); yp_thread = thread_create("YP Touch Thread", yp_update_thread, (void *)NULL, THREAD_ATTACHED); }
/* 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(); }
static void url_stream_auth (auth_client *auth_user) { ice_config_t *config; int port; client_t *client = auth_user->client; auth_url *url = client->auth->state; char *mount, *host, *user, *pass, *ipaddr, *admin=""; char post [4096]; if (strchr (url->stream_auth, '@') == NULL) { if (url->userpwd) curl_easy_setopt (url->handle, CURLOPT_USERPWD, url->userpwd); else curl_easy_setopt (url->handle, CURLOPT_USERPWD, ""); } else curl_easy_setopt (url->handle, CURLOPT_USERPWD, ""); curl_easy_setopt (url->handle, CURLOPT_URL, url->stream_auth); curl_easy_setopt (url->handle, CURLOPT_POSTFIELDS, post); curl_easy_setopt (url->handle, CURLOPT_WRITEHEADER, auth_user); if (strcmp (auth_user->mount, httpp_getvar (client->parser, HTTPP_VAR_URI)) != 0) admin = "&admin=1"; mount = util_url_escape (auth_user->mount); config = config_get_config (); host = util_url_escape (config->hostname); port = config->port; config_release_config (); ipaddr = util_url_escape (client->con->ip); if (client->username) { user = util_url_escape(client->username); } else { user = strdup(""); } if (client->password) { pass = util_url_escape(client->password); } else { pass = strdup(""); } snprintf (post, sizeof (post), "action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s", mount, ipaddr, host, port, user, pass, admin); free (ipaddr); free (user); free (pass); free (mount); free (host); client->authenticated = 0; if (curl_easy_perform (url->handle)) ICECAST_LOG_WARN("auth to server %s failed with %s", url->stream_auth, url->errormsg); }
void event_config_read(void *arg) { int ret; ice_config_t *config; ice_config_t new_config; /* reread config file */ config = config_grab_config(); /* Both to get the lock, and to be able to find out the config filename */ xmlSetGenericErrorFunc ("config", log_parse_failure); ret = config_parse_file(config->config_filename, &new_config); if(ret < 0) { ICECAST_LOG_ERROR("Error parsing config, not replacing existing config"); switch(ret) { case CONFIG_EINSANE: ICECAST_LOG_ERROR("Config filename null or blank"); break; case CONFIG_ENOROOT: ICECAST_LOG_ERROR("Root element not found in %s", config->config_filename); break; case CONFIG_EBADROOT: ICECAST_LOG_ERROR("Not an icecast2 config file: %s", config->config_filename); break; default: ICECAST_LOG_ERROR("Parse error in reading %s", config->config_filename); break; } config_release_config(); } else { config_clear(config); config_set_config(&new_config); config = config_get_config_unlocked(); restart_logging (config); yp_recheck_config (config); fserve_recheck_mime_types (config); stats_global (config); config_release_config(); slave_update_all_mounts(); } }
int fserve_client_create(client_t *httpclient, char *path) { fserve_t *client = calloc(1, sizeof(fserve_t)); int bytes; int client_limit; ice_config_t *config = config_get_config(); client_limit = config->client_limit; config_release_config(); client->file = fopen(path, "rb"); if(!client->file) { client_send_404(httpclient, "File not readable"); return -1; } client->client = httpclient; client->offset = 0; client->datasize = 0; client->ready = 0; client->buf = malloc(BUFSIZE); global_lock(); if(global.clients >= client_limit) { httpclient->respcode = 504; bytes = sock_write(httpclient->con->sock, "HTTP/1.0 504 Server Full\r\n" "Content-Type: text/html\r\n\r\n" "<b>Server is full, try again later.</b>\r\n"); if(bytes > 0) httpclient->con->sent_bytes = bytes; fserve_client_destroy(client); global_unlock(); return -1; } global.clients++; global_unlock(); httpclient->respcode = 200; bytes = sock_write(httpclient->con->sock, "HTTP/1.0 200 OK\r\n" "Content-Type: %s\r\n\r\n", fserve_content_type(path)); if(bytes > 0) httpclient->con->sent_bytes = bytes; sock_set_blocking(client->client->con->sock, SOCK_NONBLOCK); sock_set_nodelay(client->client->con->sock); thread_mutex_lock (&pending_lock); client->next = (fserve_t *)pending_list; pending_list = client; thread_mutex_unlock (&pending_lock); return 0; }
static void _handle_get_request (client_t *client, char *passed_uri) { int port; char *serverhost = NULL; int serverport = 0; aliases *alias; ice_config_t *config; char *uri = passed_uri; listener_t *listen_sock; config = config_get_config(); port = config->port; listen_sock = config_get_listen_sock (config, client->con); if (listen_sock) { serverhost = listen_sock->bind_address; serverport = listen_sock->port; } alias = config->aliases; /* there are several types of HTTP GET clients ** media clients, which are looking for a source (eg, URI = /stream.ogg) ** stats clients, which are looking for /admin/stats.xml ** and directory server authorizers, which are looking for /GUID-xxxxxxxx ** (where xxxxxx is the GUID in question) - this isn't implemented yet. ** we need to handle the latter two before the former, as the latter two ** aren't subject to the limits. */ /* TODO: add GUID-xxxxxx */ /* Handle aliases */ while(alias) { if(strcmp(uri, alias->source) == 0 && (alias->port == -1 || alias->port == serverport) && (alias->bind_address == NULL || (serverhost != NULL && strcmp(alias->bind_address, serverhost) == 0))) { uri = strdup (alias->destination); DEBUG2 ("alias has made %s into %s", passed_uri, uri); break; } alias = alias->next; } config_release_config(); stats_event_inc(NULL, "client_connections"); /* Dispatch all admin requests */ if ((strcmp(uri, "/admin.cgi") == 0) || (strncmp(uri, "/admin/", 7) == 0)) { admin_handle_request(client, uri); if (uri != passed_uri) free (uri); return; } auth_add_listener (uri, client); if (uri != passed_uri) free (uri); }
int connection_check_admin_pass(http_parser_t *parser) { int ret; ice_config_t *config = config_get_config(); char *pass = config->admin_password; char *user = config->admin_username; const char *protocol; if(!pass || !user) { config_release_config(); return 0; } protocol = httpp_getvar (parser, HTTPP_VAR_PROTOCOL); if (protocol && strcmp (protocol, "ICY") == 0) ret = _check_pass_icy (parser, pass); else ret = _check_pass_http (parser, user, pass); config_release_config(); return ret; }
/* Add a listener. Check for any mount information that states any * authentication to be used. */ void auth_add_listener (const char *mount, client_t *client) { mount_proxy *mountinfo; ice_config_t *config = config_get_config(); mountinfo = config_find_mount (config, mount, MOUNT_TYPE_NORMAL); if (mountinfo && mountinfo->no_mount) { config_release_config (); client_send_403 (client, "mountpoint unavailable"); return; } if (mountinfo && mountinfo->auth) { auth_client *auth_user; if (mountinfo->auth->pending_count > 100) { config_release_config (); ICECAST_LOG_WARN("too many clients awaiting authentication"); client_send_403 (client, "busy, please try again later"); return; } auth_user = auth_client_setup (mount, client); auth_user->process = auth_new_listener; ICECAST_LOG_INFO("adding client for authentication"); queue_auth_client (auth_user, mountinfo); config_release_config (); } else { int ret = add_authenticated_listener (mount, mountinfo, client); config_release_config (); if (ret < 0) client_send_403 (client, "max listeners reached"); } }
void fserve_initialize(void) { ice_config_t *config = config_get_config(); mimetypes = NULL; active_list = NULL; pending_list = NULL; thread_spin_create (&pending_lock); fserve_recheck_mime_types (config); config_release_config(); stats_event (NULL, "file_connections", "0"); INFO0("file serving started"); }
static void source_shutdown (source_t *source) { mount_proxy *mountinfo; source->running = 0; INFO1("Source \"%s\" exiting", source->mount); mountinfo = config_find_mount (config_get_config(), source->mount); if (mountinfo) { if (mountinfo->on_disconnect) source_run_script (mountinfo->on_disconnect, source->mount); auth_stream_end (mountinfo, source->mount); } config_release_config(); /* we have de-activated the source now, so no more clients will be * added, now move the listeners we have to the fallback (if any) */ if (source->fallback_mount) { source_t *fallback_source; avl_tree_rlock(global.source_tree); fallback_source = source_find_mount (source->fallback_mount); if (fallback_source != NULL) source_move_clients (source, fallback_source); avl_tree_unlock (global.source_tree); } /* delete this sources stats */ stats_event(source->mount, NULL, NULL); /* we don't remove the source from the tree here, it may be a relay and therefore reserved */ source_clear_source (source); global_lock(); global.sources--; stats_event_args (NULL, "sources", "%d", global.sources); global_unlock(); /* release our hold on the lock so the main thread can continue cleaning up */ thread_rwlock_unlock(source->shutdown_rwlock); }
static int _handle_shoutcast_stage1 (connection_queue_t *node, char *shoutcast_mount, mount_proxy *mountinfo) { refbuf_t *refbuf = node->refbuf; char *source_password; int err, passlen; WARN ("IN"); if (mountinfo && mountinfo->password) { source_password = strdup (mountinfo->password); } else { ice_config_t *config = config_get_config (); source_password = strdup (config->source_password); config_release_config(); } passlen = util_read_header (node->con, refbuf, HEADER_READ_LINE); if (passlen <= 0) { WARN ("HEADER READ FAILED"); err = passlen; goto out_FAIL; } if (memmem (refbuf->data, passlen, source_password, strlen(source_password)) == NULL) { INFO ("password does not match (%ld) \"%s\" (%d) \"%s\"", strlen(source_password), source_password, passlen, refbuf->data); err = -ENOENT; goto out_FAIL; } /* send this non-blocking but if there is only a partial write * then leave to header timeout */ sock_write (node->con->sock, "OK2\r\nicy-caps:11\r\n\r\n"); WARN ("writting to client: OK2\r\nicy-caps:11\r\n\r\n"); refbuf->sync_point = snprintf (refbuf->data, refbuf->len, "POST %s HTTP/1.0\r\n", shoutcast_mount); /* we've checked the password, now send it back for reading headers */ free (source_password); return 0; out_FAIL: free (source_password); return err; }
int auth_postprocess_listener (auth_client *auth_user) { int ret; client_t *client = auth_user->client; ice_config_t *config = config_get_config(); mount_proxy *mountinfo = config_find_mount (config, auth_user->mount, MOUNT_TYPE_NORMAL); ret = add_authenticated_listener (auth_user->mount, mountinfo, client); config_release_config(); if (ret < 0) client_send_401 (auth_user->client); auth_user->client = NULL; return ret; }
static void _build_pool(void) { ice_config_t *config; int i; thread_type *tid; char buff[64]; int threadpool_size; config = config_get_config(); threadpool_size = config->threadpool_size; config_release_config(); for (i = 0; i < threadpool_size; i++) { snprintf(buff, 64, "Connection Thread #%d", i); tid = thread_create(buff, _handle_connection, NULL, THREAD_ATTACHED); _push_thread(&_conhands, tid); } }
int admin_send_response (xmlDocPtr doc, client_t *client, admin_response_type response, const char *xslt_template) { int ret = -1; if (response == RAW) { xmlChar *buff = NULL; int len = 0; unsigned int buf_len; const char *http = "HTTP/1.0 200 OK\r\n" "Content-Type: text/xml\r\n" "Content-Length: "; xmlDocDumpFormatMemoryEnc (doc, &buff, &len, NULL, 1); buf_len = strlen (http) + len + 20; client_set_queue (client, NULL); client->refbuf = refbuf_new (buf_len); len = snprintf (client->refbuf->data, buf_len, "%s%d\r\n\r\n%s", http, len, buff); client->refbuf->len = len; xmlFree(buff); xmlFreeDoc (doc); client->respcode = 200; return fserve_setup_client (client); } if (response == XSLT) { char *fullpath_xslt_template; int fullpath_xslt_template_len; ice_config_t *config = config_get_config(); fullpath_xslt_template_len = strlen (config->adminroot_dir) + strlen(xslt_template) + 2; fullpath_xslt_template = malloc(fullpath_xslt_template_len); snprintf(fullpath_xslt_template, fullpath_xslt_template_len, "%s%s%s", config->adminroot_dir, PATH_SEPARATOR, xslt_template); config_release_config(); DEBUG1("Sending XSLT (%s)", fullpath_xslt_template); ret = xslt_transform (doc, fullpath_xslt_template, client); free(fullpath_xslt_template); xmlFreeDoc(doc); } return ret; }
static http_parser_t *get_relay_response (connection_t *con, const char *mount, const char *server, int ask_for_metadata, const char *auth_header) { ice_config_t *config = config_get_config (); char *server_id = strdup (config->server_id); http_parser_t *parser = NULL; char response [4096]; config_release_config (); /* At this point we may not know if we are relaying an mp3 or vorbis * stream, but only send the icy-metadata header if the relay details * state so (the typical case). It's harmless in the vorbis case. If * we don't send in this header then relay will not have mp3 metadata. */ sock_write (con->sock, "GET %s HTTP/1.0\r\n" "User-Agent: %s\r\n" "Host: %s\r\n" "%s" "%s" "\r\n", mount, server_id, server, ask_for_metadata ? "Icy-MetaData: 1\r\n" : "", auth_header ? auth_header : ""); free (server_id); memset (response, 0, sizeof(response)); if (util_read_header (con->sock, response, 4096, READ_ENTIRE_HEADER) == 0) { INFO0 ("Header read failure"); return NULL; } parser = httpp_create_parser(); httpp_initialize (parser, NULL); if (! httpp_parse_response (parser, response, strlen(response), mount)) { INFO0 ("problem parsing response from relay"); httpp_destroy (parser); return NULL; } return parser; }
int client_send_401 (client_t *client, const char *realm) { ice_config_t *config = config_get_config (); if (realm == NULL) realm = config->server_id; client_set_queue (client, NULL); client->refbuf = refbuf_new (500); snprintf (client->refbuf->data, 500, "HTTP/1.0 401 Authentication Required\r\n" "WWW-Authenticate: Basic realm=\"%s\"\r\n" "\r\n" "You need to authenticate\r\n", realm); config_release_config(); client->respcode = 401; client->refbuf->len = strlen (client->refbuf->data); return fserve_setup_client (client); }