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) { doc = xmlNewDoc (XMLSTR("1.0")); node = xmlNewDocNode (doc, NULL, XMLSTR("icerelaystats"), NULL); xmlDocSetRootElement(doc, node); thread_mutex_lock (&(config_locks()->relay_lock)); for (relay = global.relays; relay; relay=relay->next) add_relay_xmlnode (node, relay, 0); for (relay = global.master_relays; relay; relay=relay->next) add_relay_xmlnode (node, relay, 1); thread_mutex_unlock (&(config_locks()->relay_lock)); return admin_send_response (doc, client, response, "managerelays.xsl"); } thread_mutex_lock (&(config_locks()->relay_lock)); relay = slave_find_relay (global.relays, relay_mount); if (relay == NULL) relay = slave_find_relay (global.master_relays, relay_mount); msg = "no such relay"; if (relay) { source_t *source = relay->source; client_t *client; thread_mutex_lock (&source->lock); client = source->client; relay->running = atoi (enable) ? 1 : 0; if (client) { client->schedule_ms = 0; worker_wakeup (client->worker); } thread_mutex_unlock (&source->lock); msg = "relay has been changed"; } thread_mutex_unlock (&(config_locks()->relay_lock)); 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 command_manageauth(client_t *client, source_t *source, int response) { xmlDocPtr doc; xmlNodePtr node, srcnode, msgnode; char *action = NULL; char *username = NULL; char *password = NULL; char *message = NULL; int ret = AUTH_OK; if((COMMAND_OPTIONAL(client, "action", action))) { if (!strcmp(action, "add")) { COMMAND_REQUIRE(client, "username", username); COMMAND_REQUIRE(client, "password", password); ret = auth_adduser(source, 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")) { COMMAND_REQUIRE(client, "username", username); ret = auth_deleteuser(source, 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("1.0"); node = xmlNewDocNode(doc, NULL, "icestats", NULL); srcnode = xmlNewChild(node, NULL, "source", NULL); xmlSetProp(srcnode, "mount", source->mount); if (message) { msgnode = xmlNewChild(node, NULL, "iceresponse", NULL); xmlNewChild(msgnode, NULL, "message", message); } xmlDocSetRootElement(doc, node); auth_get_userlist(source, srcnode); admin_send_response(doc, client, response, MANAGEAUTH_TRANSFORMED_REQUEST); if (message) { free(message); } xmlFreeDoc(doc); client_destroy(client); }
static int command_show_listeners (client_t *client, source_t *source, int response) { xmlDocPtr doc; xmlNodePtr node, srcnode; long id = -1; const char *ID_str = NULL; char buf[22]; 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); snprintf(buf, sizeof(buf), "%lu", source->listeners); xmlNewChild(srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf)); COMMAND_OPTIONAL(client, "id", ID_str); if (ID_str) id = atoi (ID_str); if (id == -1) admin_source_listeners (source, srcnode); else { client_t *listener = source_find_client (source, id); if (listener) stats_listener_to_xml (listener, srcnode); } thread_mutex_unlock (&source->lock); return admin_send_response (doc, client, response, "listclients.xsl"); }
static int command_move_clients (client_t *client, source_t *source, int response) { const char *dest_source; xmlDocPtr doc; xmlNodePtr node; int parameters_passed = 0; char buf[255]; if((COMMAND_OPTIONAL(client, "destination", dest_source))) { parameters_passed = 1; } if (!parameters_passed) { doc = admin_build_sourcelist(source->mount); thread_mutex_unlock (&source->lock); return admin_send_response(doc, client, response, "moveclients.xsl"); } INFO2 ("source is \"%s\", destination is \"%s\"", source->mount, dest_source); doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); source_set_fallback (source, dest_source); source->termination_count = source->listeners; source->flags |= SOURCE_LISTENERS_SYNC; snprintf (buf, sizeof(buf), "Clients moved from %s to %s", source->mount, dest_source); thread_mutex_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response (doc, client, response, "response.xsl"); }
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; 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 (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); } } } 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); }
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); }
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_mutex_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_mutex_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_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; /* Update stream metadata if needed */ if (same_ip) { static const struct { const char *param; const char *stat_name; const char *hdr[3]; } fwd[] = { {"xstreamname", "server_name", {"ice-name", "icy-name", "x-audiocast-name"}}, {"xstreamdesc", "server_description", {"ice-description", "icy-description", "x-audiocast-description"}}, {"xstreamurl", "server_url", {"ice-url", "icy-url", "x-audiocast-url"}}, {"xstreamgenre", "genre", {"ice-genre", "icy-genre", "x-audiocast-genre"}} }; unsigned i; for (i = 0; i < sizeof(fwd) / sizeof(*fwd); i++) { const char *value; unsigned j; COMMAND_OPTIONAL(client, fwd[i].param, value); if (value && *value) { value = auto_recode(value); if (source->format->charset) stats_set_conv (source->stats, fwd[i].stat_name, value, source->format->charset); else stats_set (source->stats, fwd[i].stat_name, value); } else if (value) { stats_set (source->stats, fwd[i].stat_name, NULL); } for (j = 0; j < 3; j++) { if (j == 0 && value && *value) { httpp_setvar(source->format->parser, fwd[i].hdr[j], value); } else if (value && !*value) { httpp_deletevar(source->format->parser, fwd[i].hdr[j]); } } } } do { if (same_ip == 0 || plugin == NULL) break; /* Charset detection (if none specified) */ if (!charset) { const char *r; int len; charset = "UTF8"; #define CCONV(s) \ if (s && (r = auto_recode(s))) { \ len = strlen(r); \ s = alloca(len + 1); \ memcpy((char*)s, r, len + 1); \ } CCONV(title); CCONV(song); CCONV(artist); } /* Now send prepared metadata */ 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, NULL); } else { break; } thread_mutex_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); thread_mutex_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"); }