static void command_metadata(client_t *client, source_t *source, int response) { const char *action; const char *song, *title, *artist, *charset; format_plugin_t *plugin; xmlDocPtr doc; xmlNodePtr node; int same_ip = 1; doc = xmlNewDoc (XMLSTR("1.0")); node = xmlNewDocNode (doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); DEBUG0("Got metadata update request"); COMMAND_REQUIRE(client, "mode", action); COMMAND_OPTIONAL(client, "song", song); COMMAND_OPTIONAL(client, "title", title); COMMAND_OPTIONAL(client, "artist", artist); COMMAND_OPTIONAL(client, "charset", charset); if (strcmp (action, "updinfo") != 0) { xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("No such action")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("0")); admin_send_response(doc, client, response, ADMIN_XSL_RESPONSE); xmlFreeDoc(doc); return; } plugin = source->format; if (source->client && strcmp (client->con->ip, source->client->con->ip) != 0) if (response == RAW && connection_check_admin_pass (client->parser) == 0) same_ip = 0; if (same_ip && plugin && plugin->set_tag) { if (song) { plugin->set_tag (plugin, "song", song, charset); INFO2 ("Metadata on mountpoint %s changed to \"%s\"", source->mount, song); } else { if (artist && title) { plugin->set_tag (plugin, "title", title, charset); plugin->set_tag (plugin, "artist", artist, charset); INFO3("Metadata on mountpoint %s changed to \"%s - %s\"", source->mount, artist, title); } } /* updates are now done, let them be pushed into the stream */ plugin->set_tag (plugin, NULL, NULL, NULL); } else { xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Mountpoint will not accept URL updates")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); admin_send_response(doc, client, response, ADMIN_XSL_RESPONSE); xmlFreeDoc(doc); return; } xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); admin_send_response(doc, client, response, ADMIN_XSL_RESPONSE); xmlFreeDoc(doc); }
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 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]; const char *userAgent = NULL; time_t now = time(NULL); doc = xmlNewDoc (XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); srcnode = xmlNewChild(node, NULL, XMLSTR("source"), NULL); xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount)); xmlDocSetRootElement(doc, node); memset(buf, '\000', sizeof(buf)); snprintf (buf, sizeof(buf), "%lu", source->listeners); xmlNewChild(srcnode, NULL, XMLSTR("Listeners"), XMLSTR(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, XMLSTR("listener"), NULL); xmlNewChild(listenernode, NULL, XMLSTR("IP"), XMLSTR(current->con->ip)); userAgent = httpp_getvar(current->parser, "user-agent"); if (userAgent) { xmlNewChild(listenernode, NULL, XMLSTR("UserAgent"), XMLSTR(userAgent)); } else { xmlNewChild(listenernode, NULL, XMLSTR("UserAgent"), XMLSTR("Unknown")); } memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf), "%lu", (unsigned long)(now - current->con->con_time)); xmlNewChild(listenernode, NULL, XMLSTR("Connected"), XMLSTR(buf)); memset(buf, '\000', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "%lu", current->con->id); xmlNewChild(listenernode, NULL, XMLSTR("ID"), XMLSTR(buf)); if (current->username) { xmlNewChild(listenernode, NULL, XMLSTR("username"), XMLSTR(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); }
static void command_manageauth(client_t *client, source_t *source, int response) { xmlDocPtr doc; xmlNodePtr node, srcnode, msgnode; const char *action = NULL; const char *username = NULL; char *message = NULL; int ret = AUTH_OK; ice_config_t *config = config_get_config (); mount_proxy *mountinfo = config_find_mount (config, source->mount); do { if (mountinfo == NULL || mountinfo->auth == NULL) { WARN1 ("manage auth request for %s but no facility available", source->mount); break; } COMMAND_OPTIONAL(client, "action", action); COMMAND_OPTIONAL (client, "username", username); if (action == NULL) action = "list"; if (!strcmp(action, "add")) { const char *password = NULL; COMMAND_OPTIONAL (client, "password", password); if (username == NULL || password == NULL) { WARN1 ("manage auth request add for %s but no user/pass", source->mount); break; } ret = mountinfo->auth->adduser(mountinfo->auth, username, password); if (ret == AUTH_FAILED) { message = strdup("User add failed - check the icecast error log"); } if (ret == AUTH_USERADDED) { message = strdup("User added"); } if (ret == AUTH_USEREXISTS) { message = strdup("User already exists - not added"); } } if (!strcmp(action, "delete")) { if (username == NULL) { WARN1 ("manage auth request delete for %s but no username", source->mount); break; } ret = mountinfo->auth->deleteuser(mountinfo->auth, username); if (ret == AUTH_FAILED) { message = strdup("User delete failed - check the icecast error log"); } if (ret == AUTH_USERDELETED) { message = strdup("User deleted"); } } doc = xmlNewDoc (XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); srcnode = xmlNewChild(node, NULL, XMLSTR("source"), NULL); xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount)); if (message) { msgnode = xmlNewChild(node, NULL, XMLSTR("iceresponse"), NULL); xmlNewChild(msgnode, NULL, XMLSTR("message"), XMLSTR(message)); } xmlDocSetRootElement(doc, node); if (mountinfo && mountinfo->auth && mountinfo->auth->listuser) mountinfo->auth->listuser (mountinfo->auth, srcnode); config_release_config (); admin_send_response(doc, client, response, MANAGEAUTH_TRANSFORMED_REQUEST); free (message); xmlFreeDoc(doc); return; } while (0); config_release_config (); client_send_400 (client, "missing parameter"); }
static void command_move_clients(client_t *client, source_t *source, int response) { const char *dest_source; source_t *dest; xmlDocPtr doc; xmlNodePtr node; char buf[255]; int parameters_passed = 0; DEBUG0("Doing optional check"); if((COMMAND_OPTIONAL(client, "destination", dest_source))) { parameters_passed = 1; } DEBUG1("Done optional check (%d)", parameters_passed); if (!parameters_passed) { doc = admin_build_sourcelist(source->mount); admin_send_response(doc, client, response, MOVECLIENTS_TRANSFORMED_REQUEST); xmlFreeDoc(doc); return; } dest = source_find_mount (dest_source); if (dest == NULL) { client_send_400 (client, "No such destination"); return; } if (strcmp (dest->mount, source->mount) == 0) { client_send_400 (client, "supplied mountpoints are identical"); return; } if (dest->running == 0 && dest->on_demand == 0) { client_send_400 (client, "Destination not running"); return; } INFO2 ("source is \"%s\", destination is \"%s\"", source->mount, dest->mount); doc = xmlNewDoc (XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); source_move_clients (source, dest); memset(buf, '\000', sizeof(buf)); snprintf (buf, sizeof(buf), "Clients moved from %s to %s", source->mount, dest_source); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); admin_send_response(doc, client, response, ADMIN_XSL_RESPONSE); xmlFreeDoc(doc); }
/* build an XML doc containing information about currently running sources. * If a mountpoint is passed then that source will not be added to the XML * doc even if the source is running */ xmlDocPtr admin_build_sourcelist (const char *mount) { avl_node *node; source_t *source; xmlNodePtr xmlnode, srcnode; xmlDocPtr doc; char buf[22]; time_t now = time(NULL); doc = xmlNewDoc (XMLSTR("1.0")); xmlnode = xmlNewDocNode (doc, NULL, XMLSTR("icestats"), NULL); xmlDocSetRootElement(doc, xmlnode); if (mount) { xmlNewChild (xmlnode, NULL, XMLSTR("current_source"), XMLSTR(mount)); } node = avl_get_first(global.source_tree); while(node) { source = (source_t *)node->key; if (mount && strcmp (mount, source->mount) == 0) { node = avl_get_next (node); continue; } if (source->running || source->on_demand) { ice_config_t *config; mount_proxy *mountinfo; srcnode = xmlNewChild(xmlnode, NULL, XMLSTR("source"), NULL); xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount)); xmlNewChild(srcnode, NULL, XMLSTR("fallback"), (source->fallback_mount != NULL)? XMLSTR(source->fallback_mount):XMLSTR("")); snprintf (buf, sizeof(buf), "%lu", source->listeners); xmlNewChild(srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf)); config = config_get_config(); mountinfo = config_find_mount (config, source->mount); if (mountinfo && mountinfo->auth) { xmlNewChild(srcnode, NULL, XMLSTR("authenticator"), XMLSTR(mountinfo->auth->type)); } config_release_config(); if (source->running) { if (source->client) { snprintf (buf, sizeof(buf), "%lu", (unsigned long)(now - source->con->con_time)); xmlNewChild (srcnode, NULL, XMLSTR("Connected"), XMLSTR(buf)); } xmlNewChild (srcnode, NULL, XMLSTR("content-type"), XMLSTR(source->format->contenttype)); } } node = avl_get_next(node); } return(doc); }
static int command_metadata (client_t *client, source_t *source, int response) { const char *song, *title, *artist, *artwork, *charset, *url; format_plugin_t *plugin; xmlDocPtr doc; xmlNodePtr node; int same_ip = 1; doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); DEBUG0("Got metadata update request"); COMMAND_OPTIONAL(client, "song", song); COMMAND_OPTIONAL(client, "title", title); COMMAND_OPTIONAL(client, "artist", artist); COMMAND_OPTIONAL(client, "url", url); COMMAND_OPTIONAL(client, "artwork", artwork); COMMAND_OPTIONAL(client, "charset", charset); plugin = source->format; if (source_running (source)) if (strcmp (client->connection.ip, source->client->connection.ip) != 0) if (response == RAW && connection_check_admin_pass (client->parser) == 0) same_ip = 0; do { if (same_ip == 0 || plugin == NULL) break; if (artwork) stats_event (source->mount, "artwork", artwork); if (plugin->set_tag) { if (url) { plugin->set_tag (plugin, "url", url, charset); INFO2 ("Metadata url on %s set to \"%s\"", source->mount, url); } if (song) { plugin->set_tag (plugin, "artist", NULL, NULL); plugin->set_tag (plugin, "title", song, charset); INFO2("Metadata song on %s set to \"%s\"", source->mount, song); } if (artist) { plugin->set_tag (plugin, "artist", artist, charset); INFO2 ("Metadata artist on %s changed to \"%s\"", source->mount, artist); } if (title) { plugin->set_tag (plugin, "title", title, charset); INFO2 ("Metadata title on %s changed to \"%s\"", source->mount, title); } /* updates are now done, let them be pushed into the stream */ plugin->set_tag (plugin, NULL, NULL, charset); } else { break; } thread_rwlock_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); } while (0); INFO1 ("Metadata on mountpoint %s prevented", source->mount); thread_rwlock_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Mountpoint will not accept this URL update")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); }
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"); }
static void add_relay_xmlnode (xmlNodePtr node, relay_server *relay) { xmlNodePtr relaynode = xmlNewChild (node, NULL, XMLSTR("relay"), NULL); relay_server_host *host = relay->hosts; char str [50]; xmlNewChild (relaynode, NULL, XMLSTR("localmount"), XMLSTR(relay->localmount)); snprintf (str, sizeof (str), "%d", (relay->flags & RELAY_RUNNING) ? 1 : 0); xmlNewChild (relaynode, NULL, XMLSTR("enable"), XMLSTR(str)); snprintf (str, sizeof (str), "%d", (relay->flags & RELAY_ON_DEMAND) ? 1 : 0); xmlNewChild (relaynode, NULL, XMLSTR("on_demand"), XMLSTR(str)); snprintf (str, sizeof (str), "%d", (relay->flags & RELAY_FROM_MASTER ? 1 : 0)); xmlNewChild (relaynode, NULL, XMLSTR("from_master"), XMLSTR(str)); while (host) { xmlNodePtr masternode = xmlNewChild (relaynode, NULL, XMLSTR("master"), NULL); xmlNewChild (masternode, NULL, XMLSTR("server"), XMLSTR(host->ip)); xmlNewChild (masternode, NULL, XMLSTR("mount"), XMLSTR(host->mount)); snprintf (str, sizeof (str), "%d", host->port); xmlNewChild (masternode, NULL, XMLSTR("port"), XMLSTR(str)); host = host->next; } }