int format_ogg_get_plugin (format_plugin_t *plugin, client_t *client) { ogg_state_t *state = calloc (1, sizeof (ogg_state_t)); plugin->get_buffer = ogg_get_buffer; plugin->write_buf_to_client = write_buf_to_client; plugin->write_buf_to_file = write_ogg_to_file; plugin->create_client_data = create_ogg_client_data; plugin->free_plugin = format_ogg_free_plugin; plugin->get_image = get_image; plugin->set_tag = NULL; plugin->apply_settings = apply_ogg_settings; if (plugin->parser) { const char *s = httpp_getvar (plugin->parser, "content-type");; if (s==NULL || strcmp (s, "application/x-ogg") == 0) httpp_setvar (plugin->parser, "content-type", "application/ogg"); plugin->contenttype = strdup (httpp_getvar (plugin->parser, "content-type")); } else plugin->contenttype = strdup ("application/ogg"); ogg_sync_init (&state->oy); plugin->_state = state; state->mount = plugin->mount; state->bos_end = &state->header_pages; return 0; }
int format_ogg_get_plugin (source_t *source) { format_plugin_t *plugin; ogg_state_t *state = calloc (1, sizeof (ogg_state_t)); plugin = (format_plugin_t *)calloc(1, sizeof(format_plugin_t)); plugin->type = FORMAT_TYPE_OGG; plugin->get_buffer = ogg_get_buffer; plugin->write_buf_to_client = write_buf_to_client; plugin->write_buf_to_file = write_ogg_to_file; plugin->create_client_data = create_ogg_client_data; plugin->free_plugin = format_ogg_free_plugin; plugin->set_tag = NULL; if (strcmp (httpp_getvar (source->parser, "content-type"), "application/x-ogg") == 0) httpp_setvar (source->parser, "content-type", "application/ogg"); plugin->contenttype = httpp_getvar (source->parser, "content-type"); ogg_sync_init (&state->oy); plugin->_state = state; source->format = plugin; state->mount = source->mount; state->bos_end = &state->header_pages; return 0; }
static void ogg_apply_client (format_plugin_t *plugin, client_t *client) { ogg_state_t *state = plugin->_state; state->mount = NULL; ogg_sync_clear (&state->oy); if (client == NULL) return; plugin->parser = client->parser; if (plugin->parser) { const char *s = httpp_getvar (plugin->parser, "content-type"); if (s==NULL || strcmp (s, "application/x-ogg") == 0) httpp_setvar (plugin->parser, "content-type", "application/ogg"); s = httpp_getvar (plugin->parser, "content-type"); if (s) plugin->contenttype = strdup (s); } ogg_sync_init (&state->oy); state->mount = plugin->mount; state->bos_end = &state->header_pages; }
static int format_mp3_create_client_data(source_t *source, client_t *client) { mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data)); mp3_state *source_mp3 = source->format->_state; const char *metadata; /* the +-2 is for overwriting the last set of \r\n */ unsigned remaining = 4096 - client->refbuf->len + 2; char *ptr = client->refbuf->data + client->refbuf->len - 2; int bytes; const char *useragent; if (client_mp3 == NULL) return -1; /* hack for flash player, it wants a length. It has also been reported that the useragent * appears as MSIE if run in internet explorer */ useragent = httpp_getvar (client->parser, "user-agent"); if (httpp_getvar(client->parser, "x-flash-version") || (useragent && strstr(useragent, "MSIE"))) { bytes = snprintf (ptr, remaining, "Content-Length: 221183499\r\n"); remaining -= bytes; ptr += bytes; } client->format_data = client_mp3; client->free_client_data = free_mp3_client_data; metadata = httpp_getvar(client->parser, "icy-metadata"); if (metadata && atoi(metadata)) { if (source_mp3->interval >= 0) client_mp3->interval = source_mp3->interval; else client_mp3->interval = ICY_METADATA_INTERVAL; if (client_mp3->interval) { bytes = snprintf (ptr, remaining, "icy-metaint:%u\r\n", client_mp3->interval); if (bytes > 0) { remaining -= bytes; ptr += bytes; } } } bytes = snprintf (ptr, remaining, "\r\n"); remaining -= bytes; ptr += bytes; client->refbuf->len = 4096 - remaining; return 0; }
int format_mp3_get_plugin (source_t *source) { const char *metadata; format_plugin_t *plugin; mp3_state *state = calloc(1, sizeof(mp3_state)); refbuf_t *meta; plugin = (format_plugin_t *)calloc(1, sizeof(format_plugin_t)); plugin->type = FORMAT_TYPE_GENERIC; plugin->get_buffer = mp3_get_no_meta; plugin->write_buf_to_client = format_mp3_write_buf_to_client; plugin->write_buf_to_file = write_mp3_to_file; plugin->create_client_data = format_mp3_create_client_data; plugin->free_plugin = format_mp3_free_plugin; plugin->set_tag = mp3_set_tag; plugin->apply_settings = format_mp3_apply_settings; plugin->contenttype = httpp_getvar (source->parser, "content-type"); if (plugin->contenttype == NULL) { /* We default to MP3 audio for old clients without content types */ plugin->contenttype = "audio/mpeg"; } plugin->_state = state; /* initial metadata needs to be blank for sending to clients and for comparing with new metadata */ meta = refbuf_new (17); memcpy (meta->data, "\001StreamTitle='';", 17); state->metadata = meta; state->interval = -1; metadata = httpp_getvar (source->parser, "icy-metaint"); if (metadata) { state->inline_metadata_interval = atoi (metadata); if (state->inline_metadata_interval > 0) { state->offset = 0; plugin->get_buffer = mp3_get_filter_meta; state->interval = state->inline_metadata_interval; } } source->format = plugin; thread_mutex_create (&state->url_lock); return 0; }
int command_list_mounts(client_t *client, int response) { DEBUG0("List mounts request"); client_set_queue (client, NULL); client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE); if (response == TEXT) { redirector_update (client); snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); client->refbuf->len = strlen (client->refbuf->data); client->respcode = 200; if (strcmp (httpp_getvar (client->parser, HTTPP_VAR_URI), "/admin/streams") == 0) client->refbuf->next = stats_get_streams (1); else client->refbuf->next = stats_get_streams (0); return fserve_setup_client (client); } else { xmlDocPtr doc; avl_tree_rlock (global.source_tree); doc = admin_build_sourcelist(NULL); avl_tree_unlock (global.source_tree); return admin_send_response (doc, client, response, "listmounts.xsl"); } }
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 void format_mp3_apply_settings (client_t *client, format_plugin_t *format, mount_proxy *mount) { mp3_state *source_mp3 = format->_state; source_mp3->interval = -1; free (format->charset); format->charset = NULL; if (mount) { if (mount->mp3_meta_interval >= 0) source_mp3->interval = mount->mp3_meta_interval; if (mount->charset) format->charset = strdup (mount->charset); } if (source_mp3->interval < 0) { const char *metadata = httpp_getvar (client->parser, "icy-metaint"); source_mp3->interval = ICY_METADATA_INTERVAL; if (metadata) { int interval = atoi (metadata); if (interval > 0) source_mp3->interval = interval; } } if (format->charset == NULL) format->charset = strdup ("ISO8859-1"); ICECAST_LOG_DEBUG("sending metadata interval %d", source_mp3->interval); ICECAST_LOG_DEBUG("charset %s", format->charset); }
void source_client_callback (client_t *client, void *arg) { const char *agent; source_t *source = arg; refbuf_t *old_data = client->refbuf; if (client->con->error) { global_lock(); global.sources--; global_unlock(); source_clear_source (source); source_free_source (source); return; } client->refbuf = old_data->associated; old_data->associated = NULL; refbuf_release (old_data); stats_event (source->mount, "source_ip", source->client->con->ip); agent = httpp_getvar (source->client->parser, "user-agent"); if (agent) stats_event (source->mount, "user_agent", agent); thread_create ("Source Thread", source_client_thread, source, THREAD_DETACHED); }
static void command_list_mounts(client_t *client, int response) { DEBUG0("List mounts request"); if (response == PLAINTEXT) { snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); client->refbuf->len = strlen (client->refbuf->data); client->respcode = 200; const char *url = httpp_getvar(client->parser, "x-origin"); stats_event_args(NULL, "relay_url", "%s", url); client->refbuf->next = stats_get_streams (); fserve_add_client (client, NULL); } else { xmlDocPtr doc; avl_tree_rlock (global.source_tree); doc = admin_build_sourcelist(NULL); avl_tree_unlock (global.source_tree); admin_send_response(doc, client, response, LISTMOUNTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); } }
/* return 0 for failed, 1 for ok */ int connection_check_pass (http_parser_t *parser, const char *user, const char *pass) { int ret; const char *protocol; if(!pass) { WARN0("No source password set, rejecting source"); return -1; } 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_config_t *config = config_get_config_unlocked(); if (config->ice_login) { ret = _check_pass_ice(parser, pass); if(ret) WARN0("Source is using deprecated icecast login"); } } } return ret; }
static int format_mp3_create_client_data(source_t *source, client_t *client) { mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data)); mp3_state *source_mp3 = source->format->_state; const char *metadata; /* the +-2 is for overwriting the last set of \r\n */ unsigned remaining = 4096 - client->refbuf->len + 2; char *ptr = client->refbuf->data + client->refbuf->len - 2; int bytes; if (client_mp3 == NULL) return -1; /* hack for flash player, it wants a length */ if (httpp_getvar(client->parser, "x-flash-version")) { bytes = snprintf (ptr, remaining, "Content-Length: 347122319\r\n"); remaining -= bytes; ptr += bytes; } client->format_data = client_mp3; client->free_client_data = free_mp3_client_data; metadata = httpp_getvar(client->parser, "icy-metadata"); if (metadata && atoi(metadata)) { if (source_mp3->interval > 0) client_mp3->interval = source_mp3->interval; else client_mp3->interval = ICY_METADATA_INTERVAL; bytes = snprintf (ptr, remaining, "icy-metaint:%u\r\n", client_mp3->interval); if (bytes > 0) { remaining -= bytes; ptr += bytes; } } bytes = snprintf (ptr, remaining, "\r\n"); remaining -= bytes; ptr += bytes; client->refbuf->len = 4096 - remaining; return 0; }
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); }
static int _handle_client (client_t *client) { const char *rawuri; http_parser_t *parser = client->parser; char *uri; rawuri = httpp_getvar(parser, HTTPP_VAR_URI); if (strcmp("ICE", httpp_getvar(parser, HTTPP_VAR_PROTOCOL)) && strcmp("HTTP", httpp_getvar(parser, HTTPP_VAR_PROTOCOL))) { client_send_400 (client, "Bad HTTP protocol"); return -EINPROGRESS; } uri = util_normalise_uri(rawuri); if (uri == NULL) { client_send_400 (client, "Couldn't normalize uri"); return -EINPROGRESS; } if (parser->req_type == httpp_req_source) { _handle_source_request (client, uri); } else if (parser->req_type == httpp_req_post) { _handle_post_request (client, uri); } else if (parser->req_type == httpp_req_stats) { _handle_stats_request (client, uri); } else if (parser->req_type == httpp_req_get) { _handle_get_request (client, uri); } else { client_send_400 (client, "Wrong request type from client"); return -EINPROGRESS; } free(uri); return 1; }
static void command_show_listeners(client_t *client, source_t *source, int response) { xmlDocPtr doc; xmlNodePtr node, srcnode, listenernode; avl_node *client_node; client_t *current; char buf[22]; char *userAgent = NULL; time_t now = time(NULL); doc = xmlNewDoc("1.0"); node = xmlNewDocNode(doc, NULL, "icestats", NULL); srcnode = xmlNewChild(node, NULL, "source", NULL); xmlSetProp(srcnode, "mount", source->mount); xmlDocSetRootElement(doc, node); memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%ld", source->listeners); xmlNewChild(srcnode, NULL, "Listeners", buf); avl_tree_rlock(source->client_tree); client_node = avl_get_first(source->client_tree); while(client_node) { current = (client_t *)client_node->key; listenernode = xmlNewChild(srcnode, NULL, "listener", NULL); xmlNewChild(listenernode, NULL, "IP", current->con->ip); userAgent = httpp_getvar(current->parser, "user-agent"); if (userAgent) { xmlNewChild(listenernode, NULL, "UserAgent", userAgent); } else { xmlNewChild(listenernode, NULL, "UserAgent", "Unknown"); } memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%ld", now - current->con->con_time); xmlNewChild(listenernode, NULL, "Connected", buf); memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%lu", current->con->id); xmlNewChild(listenernode, NULL, "ID", buf); if (current->username) { xmlNewChild(listenernode, NULL, "username", current->username); } client_node = avl_get_next(client_node); } avl_tree_unlock(source->client_tree); admin_send_response(doc, client, response, LISTCLIENTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); client_destroy(client); }
void client_destroy(client_t *client) { if (client == NULL) return; if (client->worker) { WARN0 ("client still on worker thread"); return; } /* release the buffer now, as the buffer could be on the source queue * and may of disappeared after auth completes */ if (client->refbuf) { refbuf_release (client->refbuf); client->refbuf = NULL; } if (client->flags & CLIENT_AUTHENTICATED) DEBUG1 ("client still in auth \"%s\"", httpp_getvar (client->parser, HTTPP_VAR_URI)); /* write log entry if ip is set (some things don't set it, like outgoing * slave requests */ if (client->respcode > 0 && client->parser) logging_access(client); if (client->flags & CLIENT_IP_BAN_LIFT) { INFO1 ("lifting IP ban on client at %s", client->connection.ip); connection_release_banned_ip (client->connection.ip); client->flags &= ~CLIENT_IP_BAN_LIFT; } connection_close (&client->connection); if (client->parser) httpp_destroy (client->parser); global_lock (); global.clients--; stats_event_args (NULL, "clients", "%d", global.clients); config_clear_listener (client->server_conn); global_unlock (); /* we need to free client specific format data (if any) */ if (client->free_client_data) client->free_client_data (client); free(client->username); free(client->password); free(client); }
static int _check_pass_ice(http_parser_t *parser, const char *correctpass) { const char *password; password = httpp_getvar(parser, "ice-password"); if(!password) password = ""; if (strcmp(password, correctpass)) return 0; else return 1; }
static int _check_pass_icy(http_parser_t *parser, const char *correctpass) { const char *password; password = httpp_getvar(parser, HTTPP_VAR_ICYPASSWORD); if(!password) return 0; if (strcmp(password, correctpass)) return 0; else return 1; }
auth_result auth_check_client(source_t *source, client_t *client) { auth_t *authenticator = source->authenticator; auth_result result; if(authenticator) { /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */ char *header = httpp_getvar(client->parser, "authorization"); char *userpass, *tmp; char *username, *password; if(header == NULL) return AUTH_FAILED; if(strncmp(header, "Basic ", 6)) { INFO0("Authorization not using Basic"); return 0; } userpass = util_base64_decode(header+6); if(userpass == NULL) { WARN1("Base64 decode of Authorization header \"%s\" failed", header+6); return AUTH_FAILED; } tmp = strchr(userpass, ':'); if(!tmp) { free(userpass); return AUTH_FAILED; } *tmp = 0; username = userpass; password = tmp+1; result = authenticator->authenticate( authenticator, source, username, password); if(result == AUTH_OK) client->username = strdup(username); free(userpass); return result; } else return AUTH_FAILED; }
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; }
static auth_client *auth_client_setup (const char *mount, client_t *client) { /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */ const char *header = httpp_getvar(client->parser, "authorization"); char *userpass, *tmp; char *username, *password; auth_client *auth_user; do { if (header == NULL) break; if (strncmp(header, "Basic ", 6) == 0) { userpass = util_base64_decode (header+6); if (userpass == NULL) { ICECAST_LOG_WARN("Base64 decode of Authorization header \"%s\" failed", header+6); break; } tmp = strchr(userpass, ':'); if (tmp == NULL) { free (userpass); break; } *tmp = 0; username = userpass; password = tmp+1; client->username = strdup (username); client->password = strdup (password); free (userpass); break; } ICECAST_LOG_INFO("unhandled authorization header: %s", header); } while (0); auth_user = calloc (1, sizeof(auth_client)); auth_user->mount = strdup (mount); auth_user->client = client; return auth_user; }
/* ** ADDR IDENT USER DATE REQUEST CODE BYTES REFERER AGENT [TIME] ** ** ADDR = client->con->ip ** IDENT = always - , we don't support it because it's useless ** USER = client->username ** DATE = _make_date(client->con->con_time) ** REQUEST = build from client->parser ** CODE = client->respcode ** BYTES = client->con->sent_bytes ** REFERER = get from client->parser ** AGENT = get from client->parser ** TIME = timing_get_time() - client->con->con_time */ void logging_access(client_t *client) { char datebuf[128]; char reqbuf[1024]; struct tm thetime; time_t now; time_t stayed; const char *referrer, *user_agent, *username; now = time(NULL); localtime_r (&now, &thetime); /* build the data */ #ifdef _WIN32 memset(datebuf, '\000', sizeof(datebuf)); get_clf_time(datebuf, sizeof(datebuf)-1, &thetime); #else strftime (datebuf, sizeof(datebuf), LOGGING_FORMAT_CLF, &thetime); #endif /* build the request */ snprintf (reqbuf, sizeof(reqbuf), "%s %s %s/%s", httpp_getvar (client->parser, HTTPP_VAR_REQ_TYPE), httpp_getvar (client->parser, HTTPP_VAR_URI), httpp_getvar (client->parser, HTTPP_VAR_PROTOCOL), httpp_getvar (client->parser, HTTPP_VAR_VERSION)); stayed = now - client->con->con_time; if (client->username == NULL) username = "******"; else username = client->username; referrer = httpp_getvar (client->parser, "referer"); if (referrer == NULL) referrer = "-"; user_agent = httpp_getvar (client->parser, "user-agent"); if (user_agent == NULL) user_agent = "-"; log_write_direct (accesslog, "%s - %s [%s] \"%s\" %d %" PRIu64 " \"%s\" \"%s\" %lu", client->con->ip, username, datebuf, reqbuf, client->respcode, client->con->sent_bytes, referrer, user_agent, (unsigned long)stayed); }
static void ebml_apply_client (format_plugin_t *plugin, client_t *client) { ebml_source_state_t *ebml_source_state = plugin->_state; const char *s; refbuf_release (ebml_source_state->header); ebml_source_state->header = NULL; ebml_destroy (ebml_source_state->ebml); ebml_source_state->ebml = NULL; free (plugin->contenttype); if (client == NULL) return; s = plugin->parser ? httpp_getvar (plugin->parser, "content-type") : NULL; plugin->contenttype = strdup (s ? s : "video/x-matroska"); ebml_source_state->ebml = ebml_create(); }
/* Decide whether we need to start a source or just process a source * admin request. */ void auth_postprocess_source (auth_client *auth_user) { client_t *client = auth_user->client; const char *mount = auth_user->mount; const char *req = httpp_getvar (client->parser, HTTPP_VAR_URI); auth_user->client = NULL; if (strcmp (req, "/admin.cgi") == 0 || strncmp ("/admin/metadata", req, 15) == 0) { DEBUG2 ("metadata request (%s, %s)", req, mount); admin_mount_request (client, "metadata"); } else { DEBUG1 ("on mountpoint %s", mount); source_startup (client, mount); } }
void httpp_setvar(http_parser_t *parser, const char *name, const char *value) { http_var_t *var; if (name == NULL || value == NULL) return; var = (http_var_t *)amalloc(sizeof(http_var_t)); var->name = strdup(name); var->value = strdup(value); if (httpp_getvar(parser, name) == NULL) { avl_insert(parser->vars, (void *)var); } else { avl_delete(parser->vars, (void *)var, _free_vars); avl_insert(parser->vars, (void *)var); } }
static void format_mp3_apply_settings (client_t *client, format_plugin_t *format, mount_proxy *mount) { mp3_state *source_mp3 = format->_state; if (mount == NULL || mount->mp3_meta_interval <= 0) { char *metadata = httpp_getvar (client->parser, "icy-metaint"); source_mp3->interval = -1; if (metadata) { int interval = atoi (metadata); if (interval > 0) source_mp3->interval = interval; } } else source_mp3->interval = mount->mp3_meta_interval; DEBUG1 ("mp3 interval %d", source_mp3->interval); }
void stats_listener_to_xml (client_t *listener, xmlNodePtr parent) { const char *useragent; char buf[30]; xmlNodePtr node = xmlNewChild (parent, NULL, XMLSTR("listener"), NULL); snprintf (buf, sizeof (buf), "%lu", listener->connection.id); xmlSetProp (node, XMLSTR("id"), XMLSTR(buf)); xmlNewChild (node, NULL, XMLSTR("IP"), XMLSTR(listener->connection.ip)); useragent = httpp_getvar (listener->parser, "user-agent"); if (useragent && xmlCheckUTF8((unsigned char *)useragent)) { xmlChar *str = xmlEncodeEntitiesReentrant (parent->doc, XMLSTR(useragent)); xmlNewChild (node, NULL, XMLSTR("UserAgent"), str); xmlFree (str); } if ((listener->flags & (CLIENT_ACTIVE|CLIENT_IN_FSERVE)) == CLIENT_ACTIVE) { source_t *source = listener->shared_data; snprintf (buf, sizeof (buf), "%"PRIu64, source->client->queue_pos - listener->queue_pos); } else snprintf (buf, sizeof (buf), "0"); xmlNewChild (node, NULL, XMLSTR("lag"), XMLSTR(buf)); if (listener->worker) { snprintf (buf, sizeof (buf), "%lu", (unsigned long)(listener->worker->current_time.tv_sec - listener->connection.con_time)); xmlNewChild (node, NULL, XMLSTR("Connected"), XMLSTR(buf)); } if (listener->username) { xmlChar *str = xmlEncodeEntitiesReentrant (parent->doc, XMLSTR(listener->username)); xmlNewChild (node, NULL, XMLSTR("username"), str); xmlFree (str); } }
static void url_stream_auth (auth_client *auth_user) { client_t *client = auth_user->client; auth_url *url = auth_user->auth->state; auth_thread_data *atd = auth_user->thread_data; char *mount, *host, *user, *pass, *ipaddr, *admin=""; char post [4096]; if (strchr (url->stream_auth, '@') == NULL) { if (url->userpwd) curl_easy_setopt (atd->curl, CURLOPT_USERPWD, url->userpwd); else curl_easy_setopt (atd->curl, CURLOPT_USERPWD, ""); } else curl_easy_setopt (atd->curl, CURLOPT_USERPWD, ""); curl_easy_setopt (atd->curl, CURLOPT_URL, url->stream_auth); curl_easy_setopt (atd->curl, CURLOPT_POSTFIELDS, post); curl_easy_setopt (atd->curl, CURLOPT_WRITEHEADER, auth_user); curl_easy_setopt (atd->curl, CURLOPT_WRITEDATA, 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); host = util_url_escape (auth_user->hostname); user = util_url_escape (client->username); pass = util_url_escape (client->password); ipaddr = util_url_escape (client->connection.ip); snprintf (post, sizeof (post), "action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s", mount, ipaddr, host, auth_user->port, user, pass, admin); free (ipaddr); free (user); free (pass); free (mount); free (host); client->flags &= ~CLIENT_AUTHENTICATED; if (curl_easy_perform (atd->curl)) WARN3 ("auth to server %s (%s) failed with %s", url->stream_auth, auth_user->mount, atd->errormsg); }
/* Called when the stream ends so that the authentication engine can do * any authentication cleanup */ void auth_stream_end (mount_proxy *mountinfo, source_t *source) { if (mountinfo && mountinfo->auth && mountinfo->auth->stream_end) { client_t *client = source->client; const char *agent = httpp_getvar (client->parser, "user-agent"), *mount = source->mount; auth_client *auth_user = auth_client_setup (mount, NULL); // use a blank client copy to avoid a race auth_user->client = calloc (1, sizeof (client_t)); auth_user->client->connection.ip = strdup (client->connection.ip); if (agent) auth_user->client->shared_data = strdup (agent); auth_user->process = stream_end_callback; INFO1 ("request stream end for \"%s\"", mount); queue_auth_client (auth_user, mountinfo); } }
static int command_buildm3u (client_t *client, const char *mount) { const char *username = NULL; const char *password = NULL; ice_config_t *config; const char *host = httpp_getvar (client->parser, "host"); if (COMMAND_REQUIRE(client, "username", username) < 0 || COMMAND_REQUIRE(client, "password", password) < 0) return client_send_400 (client, "missing arg, username/password"); client->respcode = 200; config = config_get_config(); if (host) { char port[10] = ""; if (strchr (host, ':') == NULL) snprintf (port, sizeof (port), ":%u", config->port); 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%s%s\r\n", username, password, host, port, mount); } else { 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); return fserve_setup_client (client); }