Commit b520eb32 authored by Michael Smith's avatar Michael Smith

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
Implemented the ability to reread the config file on SIGHUP. For now, this
does not affect configuration for currently running sources (only new
......
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include "config.h"
#include "connection.h"
......@@ -21,6 +23,7 @@
#define COMMAND_FALLBACK 1
#define COMMAND_RAW_STATS 2
#define COMMAND_METADATA_UPDATE 3
#define COMMAND_SHOW_LISTENERS 4
int admin_get_command(char *command)
{
......@@ -32,12 +35,15 @@ int admin_get_command(char *command)
return COMMAND_RAW_STATS;
else if(!strcmp(command, "metadata"))
return COMMAND_METADATA_UPDATE;
else if(!strcmp(command, "listclients"))
return COMMAND_SHOW_LISTENERS;
else
return COMMAND_ERROR;
}
static void command_fallback(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);
......@@ -132,10 +138,13 @@ static void admin_handle_mount_request(client_t *client, source_t *source,
case COMMAND_METADATA_UPDATE:
command_metadata(client, source);
break;
case COMMAND_SHOW_LISTENERS:
command_show_listeners(client, source);
break;
default:
WARN0("Mount request not recognised");
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,
} \
} while(0);
static void command_success(client_t *client, char *message)
static void html_success(client_t *client, char *message)
{
int bytes;
......@@ -161,6 +170,63 @@ static void command_success(client_t *client, char *message)
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)
{
char *fallback;
......@@ -174,7 +240,7 @@ static void command_fallback(client_t *client, source_t *source)
source->fallback_mount = strdup(fallback);
free(old);
command_success(client, "Fallback configured");
html_success(client, "Fallback configured");
}
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);
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) {
......
......@@ -314,6 +314,15 @@ int sock_write(sock_t sock, const char *fmt, ...)
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)
{
......
......@@ -22,6 +22,7 @@
#ifndef __SOCK_H
#define __SOCK_H
#include <stdarg.h>
#ifdef _WIN32
#include <winsock2.h>
......@@ -87,6 +88,7 @@ int sock_connected (int sock, unsigned timeout);
/* Socket write functions */
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_fmt(sock_t sock, char *fmt, va_list ap);
int sock_write_string(sock_t sock, const char *buff);
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