Commit b520eb32 authored by Michael Smith's avatar Michael Smith
Browse files

Implement listing of all currently connected clients on a mountpoint

svn path=/trunk/icecast/; revision=4434
parent d1e8e7bf
2003-03-08
Started implementing generic admin interface. Supports (so far):
- dynamic configuration of mount fallbacks
/admin/fallbacks?mount=/mount&fallback=/fallback
- setting of mp3 metadata
/admin/metadata?mount=/mount&mode=updinfo&song=New%20Title
- dumping raw xml stats
/admin/rawstats
- listing all connected clients on a mountpoint:
/admin/listclients?mount=/mountname
2003-03-05 2003-03-05
Implemented the ability to reread the config file on SIGHUP. For now, this Implemented the ability to reread the config file on SIGHUP. For now, this
does not affect configuration for currently running sources (only new does not affect configuration for currently running sources (only new
......
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include "config.h" #include "config.h"
#include "connection.h" #include "connection.h"
...@@ -21,6 +23,7 @@ ...@@ -21,6 +23,7 @@
#define COMMAND_FALLBACK 1 #define COMMAND_FALLBACK 1
#define COMMAND_RAW_STATS 2 #define COMMAND_RAW_STATS 2
#define COMMAND_METADATA_UPDATE 3 #define COMMAND_METADATA_UPDATE 3
#define COMMAND_SHOW_LISTENERS 4
int admin_get_command(char *command) int admin_get_command(char *command)
{ {
...@@ -32,12 +35,15 @@ int admin_get_command(char *command) ...@@ -32,12 +35,15 @@ int admin_get_command(char *command)
return COMMAND_RAW_STATS; return COMMAND_RAW_STATS;
else if(!strcmp(command, "metadata")) else if(!strcmp(command, "metadata"))
return COMMAND_METADATA_UPDATE; return COMMAND_METADATA_UPDATE;
else if(!strcmp(command, "listclients"))
return COMMAND_SHOW_LISTENERS;
else else
return COMMAND_ERROR; return COMMAND_ERROR;
} }
static void command_fallback(client_t *client, source_t *source); static void command_fallback(client_t *client, source_t *source);
static void command_metadata(client_t *client, source_t *source); static void command_metadata(client_t *client, source_t *source);
static void command_show_listeners(client_t *client, source_t *source);
static void command_raw_stats(client_t *client); static void command_raw_stats(client_t *client);
...@@ -132,10 +138,13 @@ static void admin_handle_mount_request(client_t *client, source_t *source, ...@@ -132,10 +138,13 @@ static void admin_handle_mount_request(client_t *client, source_t *source,
case COMMAND_METADATA_UPDATE: case COMMAND_METADATA_UPDATE:
command_metadata(client, source); command_metadata(client, source);
break; break;
case COMMAND_SHOW_LISTENERS:
command_show_listeners(client, source);
break;
default: default:
WARN0("Mount request not recognised"); WARN0("Mount request not recognised");
client_send_400(client, "Mount request unknown"); client_send_400(client, "Mount request unknown");
return; break;
} }
} }
...@@ -148,7 +157,7 @@ static void admin_handle_mount_request(client_t *client, source_t *source, ...@@ -148,7 +157,7 @@ static void admin_handle_mount_request(client_t *client, source_t *source,
} \ } \
} while(0); } while(0);
static void command_success(client_t *client, char *message) static void html_success(client_t *client, char *message)
{ {
int bytes; int bytes;
...@@ -161,6 +170,63 @@ static void command_success(client_t *client, char *message) ...@@ -161,6 +170,63 @@ static void command_success(client_t *client, char *message)
client_destroy(client); client_destroy(client);
} }
static void html_head(client_t *client)
{
int bytes;
client->respcode = 200;
bytes = sock_write(client->con->sock,
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<html><head><title>Admin request</title></head>"
"<body>");
if(bytes > 0) client->con->sent_bytes = bytes;
}
static void html_write(client_t *client, char *fmt, ...)
{
int bytes;
va_list ap;
va_start(ap, fmt);
bytes = sock_write_fmt(client->con->sock, fmt, ap);
va_end(ap);
if(bytes > 0) client->con->sent_bytes = bytes;
}
static void command_show_listeners(client_t *client, source_t *source)
{
avl_node *client_node;
client_t *current;
time_t now = time(NULL);
DEBUG1("Dumping listeners on mountpoint %s", source->mount);
html_head(client);
html_write(client,
"<table><tr><td>IP</td><td>Connected</td><td>ID</td></tr>");
avl_tree_rlock(source->client_tree);
client_node = avl_get_first(source->client_tree);
while(client_node) {
current = (client_t *)client_node->key;
html_write(client, "<tr><td>%s</td><td>%d</td><td>%ld</td></tr>",
current->con->ip, now-current->con->con_time, current->con->id);
client_node = avl_get_next(client_node);
}
avl_tree_unlock(source->client_tree);
html_write(client, "</table></body></html>");
client_destroy(client);
}
static void command_fallback(client_t *client, source_t *source) static void command_fallback(client_t *client, source_t *source)
{ {
char *fallback; char *fallback;
...@@ -174,7 +240,7 @@ static void command_fallback(client_t *client, source_t *source) ...@@ -174,7 +240,7 @@ static void command_fallback(client_t *client, source_t *source)
source->fallback_mount = strdup(fallback); source->fallback_mount = strdup(fallback);
free(old); free(old);
command_success(client, "Fallback configured"); html_success(client, "Fallback configured");
} }
static void command_metadata(client_t *client, source_t *source) static void command_metadata(client_t *client, source_t *source)
...@@ -210,7 +276,7 @@ static void command_metadata(client_t *client, source_t *source) ...@@ -210,7 +276,7 @@ static void command_metadata(client_t *client, source_t *source)
DEBUG2("Metadata on mountpoint %s changed to \"%s\"", source->mount, value); DEBUG2("Metadata on mountpoint %s changed to \"%s\"", source->mount, value);
stats_event(source->mount, "title", value); stats_event(source->mount, "title", value);
command_success(client, "Metadata update successful"); html_success(client, "Metadata update successful");
} }
static void command_raw_stats(client_t *client) { static void command_raw_stats(client_t *client) {
......
...@@ -314,6 +314,15 @@ int sock_write(sock_t sock, const char *fmt, ...) ...@@ -314,6 +314,15 @@ int sock_write(sock_t sock, const char *fmt, ...)
return sock_write_bytes(sock, buff, strlen(buff)); return sock_write_bytes(sock, buff, strlen(buff));
} }
int sock_write_fmt(sock_t sock, char *fmt, va_list ap)
{
char buff[1024];
vsnprintf(buff, 1024, fmt, ap);
return sock_write_bytes(sock, buff, strlen(buff));
}
int sock_read_bytes(sock_t sock, char *buff, const int len) int sock_read_bytes(sock_t sock, char *buff, const int len)
{ {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#ifndef __SOCK_H #ifndef __SOCK_H
#define __SOCK_H #define __SOCK_H
#include <stdarg.h>
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
...@@ -87,6 +88,7 @@ int sock_connected (int sock, unsigned timeout); ...@@ -87,6 +88,7 @@ int sock_connected (int sock, unsigned timeout);
/* Socket write functions */ /* Socket write functions */
int sock_write_bytes(sock_t sock, const void *buff, const size_t len); int sock_write_bytes(sock_t sock, const void *buff, const size_t len);
int sock_write(sock_t sock, const char *fmt, ...); int sock_write(sock_t sock, const char *fmt, ...);
int sock_write_fmt(sock_t sock, char *fmt, va_list ap);
int sock_write_string(sock_t sock, const char *buff); int sock_write_string(sock_t sock, const char *buff);
ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count); ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment