1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-23 06:25:24 +00:00

sync up work, initial work for showlog, merge reported trunk bugs

svn path=/icecast/branches/kh/icecast/; revision=11003
This commit is contained in:
Karl Heyes 2006-03-15 02:21:04 +00:00
parent bdb130e5b3
commit 7f8f5d0606
14 changed files with 171 additions and 32 deletions

View File

@ -70,11 +70,14 @@
#define COMMAND_PLAINTEXT_LISTSTREAM 104
#define COMMAND_RAW_ADMIN_FUNCTION 105
#define COMMAND_RAW_MANAGE_RELAY 106
#define COMMAND_PLAINTEXT_LISTLOG 107
#define COMMAND_TRANSFORMED_LIST_MOUNTS 201
#define COMMAND_TRANSFORMED_STATS 202
#define COMMAND_TRANSFORMED_LISTSTREAM 203
#define COMMAND_TRANSFORMED_ADMIN_FUNCTION 204
#define COMMAND_TRANSFORMED_MANAGE_RELAY 205
#define COMMAND_TRANSFORMED_LISTLOG 206
/* Client management commands */
#define COMMAND_RAW_KILL_CLIENT 301
@ -99,6 +102,8 @@
#define STREAMLIST_RAW_REQUEST "streamlist"
#define STREAMLIST_TRANSFORMED_REQUEST "streamlist.xsl"
#define STREAMLIST_PLAINTEXT_REQUEST "streamlist.txt"
#define LISTLOG_PLAINTEXT_REQUEST "showlog.txt"
#define LISTLOG_TRANSFORMED_REQUEST "showlog.xsl"
#define MOVECLIENTS_RAW_REQUEST "moveclients"
#define MOVECLIENTS_TRANSFORMED_REQUEST "moveclients.xsl"
#define KILLCLIENT_RAW_REQUEST "killclient"
@ -160,6 +165,10 @@ static int admin_get_command (const char *uri)
return COMMAND_RAW_LISTSTREAM;
else if(!strcmp(command, STREAMLIST_PLAINTEXT_REQUEST))
return COMMAND_PLAINTEXT_LISTSTREAM;
else if(!strcmp(command, LISTLOG_PLAINTEXT_REQUEST))
return COMMAND_PLAINTEXT_LISTLOG;
else if(!strcmp(command, LISTLOG_TRANSFORMED_REQUEST))
return COMMAND_TRANSFORMED_LISTLOG;
else if(!strcmp(command, MOVECLIENTS_RAW_REQUEST))
return COMMAND_RAW_MOVE_CLIENTS;
else if(!strcmp(command, MOVECLIENTS_TRANSFORMED_REQUEST))
@ -218,6 +227,7 @@ static void command_kill_source(client_t *client, source_t *source,
static void command_updatemetadata(client_t *client, source_t *source,
int response);
static void command_admin_function (client_t *client, int response);
static void command_list_log (client_t *client, int response);
static void command_manage_relay (client_t *client, int response);
static void admin_handle_mount_request(client_t *client, source_t *source,
@ -479,6 +489,12 @@ static void admin_handle_general_request(client_t *client, const char *uri)
case COMMAND_PLAINTEXT_LISTSTREAM:
command_list_mounts(client, PLAINTEXT);
break;
case COMMAND_PLAINTEXT_LISTLOG:
command_list_log(client, PLAINTEXT);
break;
case COMMAND_TRANSFORMED_LISTLOG:
command_list_log(client, TRANSFORMED);
break;
case COMMAND_TRANSFORMED_LIST_MOUNTS:
command_list_mounts(client, TRANSFORMED);
break;
@ -772,7 +788,7 @@ static void command_manage_relay (client_t *client, int response)
}
/* populata,e within srcnode, groups of 0 or more listener tags detailing
/* populate within srcnode, groups of 0 or more listener tags detailing
* information about each listener connected on the provide source.
*/
void admin_source_listeners (source_t *source, xmlNodePtr srcnode)
@ -1147,6 +1163,63 @@ static void command_stats (client_t *client)
xmlFreeDoc(doc);
}
static void command_list_log (client_t *client, int response)
{
refbuf_t *content;
const char *logname = httpp_get_query_param (client->parser, "log");
int log = -1;
if (logname == NULL)
{
client_send_400 (client, "No log specified");
return;
}
if (strcmp (logname, "errorlog") == 0)
log = errorlog;
else if (strcmp (logname, "accesslog") == 0)
log = accesslog;
else if (strcmp (logname, "playlistlog") == 0)
log = playlistlog;
else
{
WARN1 ("request to show unknown log \"%s\"", logname);
client_send_400 (client, "No such log");
return;
}
if (log >= 0)
{
content = refbuf_new (0);
log_contents (log, &content->data, &content->len);
}
if (response == TRANSFORMED)
{
xmlNodePtr xmlnode, lognode;
xmlDocPtr doc;
doc = xmlNewDoc(XMLSTR("1.0"));
xmlnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL);
xmlDocSetRootElement(doc, xmlnode);
lognode = xmlNewTextChild (xmlnode, NULL, XMLSTR("log"), content->data);
refbuf_release (content);
admin_send_response (doc, client, TRANSFORMED, "showlog.xsl");
}
else
{
refbuf_t *http = refbuf_new (100);
int len = snprintf (http->data, 100, "%s",
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
http->len = len;
http->next = content;
client->respcode = 200;
client_set_queue (client, http);
fserve_add_client (client, NULL);
}
}
static void command_list_mounts(client_t *client, int response)
{
DEBUG0("List mounts request");

View File

@ -344,6 +344,11 @@ static int add_client_to_source (source_t *source, client_t *client)
{
source_t *next = source_find_mount (source->fallback_mount);
thread_mutex_unlock (&source->lock);
if (!next)
{
ERROR2("Fallback '%s' for full source '%s' not found",
source->mount, source->fallback_mount);
}
INFO1 ("stream full trying %s", next->mount);
source = next;
loop--;
@ -507,7 +512,7 @@ void add_client (const char *mount, client_t *client)
int ret = add_authenticated_listener (mount, mountinfo, client);
config_release_config ();
if (ret < 0)
client_send_404 (client, "max listeners reached");
client_send_403 (client, "max listeners reached");
}
}
@ -550,7 +555,7 @@ static void get_authenticator (auth_t *auth, config_options_t *options)
{
#ifdef WIN32
ERROR1("Authenticator type: \"%s\" not supported on win32 platform", auth->type);
return NULL;
return;
#else
auth_get_cmd_auth (auth, options);
break;

View File

@ -977,6 +977,9 @@ static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node,
ice_config_t *configuration)
{
configuration->access_log_lines = 100;
configuration->error_log_lines = 100;
configuration->playlist_log_lines = 10;
do {
if (node == NULL) break;
if (xmlIsBlankNode(node)) continue;
@ -984,12 +987,24 @@ static void _parse_logging(xmlDocPtr doc, xmlNodePtr node,
if (xmlStrcmp(node->name, XMLSTR ("accesslog")) == 0) {
if (configuration->access_log && configuration->access_log != CONFIG_DEFAULT_ACCESS_LOG) xmlFree(configuration->access_log);
configuration->access_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (xmlStrcmp(node->name, XMLSTR ("accesslog_lines")) == 0) {
char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
configuration->access_log_lines = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (xmlStrcmp(node->name, XMLSTR ("errorlog")) == 0) {
if (configuration->error_log && configuration->error_log != CONFIG_DEFAULT_ERROR_LOG) xmlFree(configuration->error_log);
configuration->error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (xmlStrcmp(node->name, XMLSTR ("errorlog_lines")) == 0) {
char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
configuration->error_log_lines = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (xmlStrcmp(node->name, XMLSTR ("playlistlog")) == 0) {
if (configuration->playlist_log && configuration->playlist_log != CONFIG_DEFAULT_PLAYLIST_LOG) xmlFree(configuration->playlist_log);
configuration->playlist_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
} else if (xmlStrcmp(node->name, XMLSTR ("playlistlog_lines")) == 0) {
char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
configuration->playlist_log_lines = atoi(tmp);
if (tmp) xmlFree(tmp);
} else if (xmlStrcmp(node->name, XMLSTR ("logsize")) == 0) {
char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
configuration->logsize = atoi(tmp);

View File

@ -162,8 +162,11 @@ typedef struct ice_config_tag
unsigned slaves_count;
char *access_log;
int access_log_lines;
char *error_log;
int error_log_lines;
char *playlist_log;
int playlist_log_lines;
int loglevel;
int logsize;
int logarchive;

View File

@ -28,7 +28,6 @@
#include <sys/socket.h>
#include <netinet/in.h>
#else
#include <winsock2.h>
#define snprintf _snprintf
#define strcasecmp stricmp
#define strncasecmp strnicmp
@ -120,6 +119,10 @@ void connection_initialize(void)
thread_mutex_create("move_clients", &move_clients_mutex);
thread_rwlock_create(&_source_shutdown_rwlock);
thread_cond_create(&global.shutdown_cond);
_req_queue = NULL;
_req_queue_tail = &_req_queue;
_con_queue = NULL;
_con_queue_tail = &_con_queue;
_initialized = 1;
}
@ -519,6 +522,7 @@ static void process_request_queue (void)
*node_ref = node->next;
node->next = NULL;
_add_connection (node);
continue;
}
}
else
@ -1138,7 +1142,10 @@ static void _handle_shoutcast_compatible (client_queue_t *node)
source_startup (client, shoutcast_mount, SHOUTCAST_SOURCE_AUTH);
}
else
{
httpp_destroy (parser);
client_destroy (client);
}
free (http_compliant);
free (shoutcast_mount);
free (node);

View File

@ -107,7 +107,8 @@ static void find_client_start (source_t *source, client_t *client)
/* we only want to attempt a burst at connection time, not midstream
* however streams like theora may not have the most recent page marked as
* a starting point, so look for one from the burst point */
if (client->intro_offset == -1 && source->stream_data_tail->sync_point)
if (client->intro_offset == -1 && source->stream_data_tail
&& source->stream_data_tail->sync_point)
refbuf = source->stream_data_tail;
else
{

View File

@ -45,7 +45,7 @@ typedef struct vorbis_codec_tag
int initial_audio_page;
ogg_stream_state new_os;
int page_samples_trigger;
ogg_int64_t page_samples_trigger;
ogg_int64_t prev_granulepos;
ogg_packet *prev_packet;
ogg_int64_t granulepos;
@ -555,7 +555,7 @@ static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info,
if (ogg_info->codecs->next == NULL)
{
/* set queued vorbis pages to contain about 1/2 of a second worth of samples */
source_vorbis->page_samples_trigger = source_vorbis->vi.rate / 2;
source_vorbis->page_samples_trigger = (ogg_int64_t)(source_vorbis->vi.rate / 2);
source_vorbis->process_packet = process_vorbis_headers;
source_vorbis->initial_audio_page = 1;
}

View File

@ -262,13 +262,19 @@ static void *fserv_thread_function(void *arg)
bytes = 0;
if (bytes == 0)
{
fserve_t *to_go = fclient;
fclient = fclient->next;
*trail = fclient;
fserve_client_destroy (to_go);
fserve_clients--;
client_tree_changed = 1;
continue;
if (refbuf->next == NULL)
{
fserve_t *to_go = fclient;
fclient = fclient->next;
*trail = fclient;
fserve_client_destroy (to_go);
fserve_clients--;
client_tree_changed = 1;
continue;
}
client_set_queue (client, refbuf->next);
refbuf = client->refbuf;
bytes = refbuf->len;
}
refbuf->len = bytes;
client->pos = 0;
@ -555,6 +561,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
} while (0);
/* If we run into any issues with the ranges
we fallback to a normal/non-range request */
fclose (file);
client_send_416 (httpclient);
return -1;
}

View File

@ -255,6 +255,9 @@ static int _start_logging(void)
log_set_level(errorlog, config->loglevel);
log_set_level(accesslog, 4);
log_set_level(playlistlog, 4);
log_set_lines_kept (errorlog, config->error_log_lines);
log_set_lines_kept (accesslog, config->access_log_lines);
log_set_lines_kept (playlistlog, config->playlist_log_lines);
if (errorlog >= 0 && accesslog >= 0) return 1;
@ -433,7 +436,11 @@ static void _ch_root_uid_setup(void)
#endif
}
#ifdef WIN32_SERVICE
int mainService(int argc, char **argv)
#else
int main(int argc, char **argv)
#endif
{
int res, ret;
char filename[512];

View File

@ -314,6 +314,7 @@ static void *start_relay_stream (void *arg)
break;
}
global_unlock ();
sock_set_blocking (streamsock, SOCK_NONBLOCK);
con = NULL;
parser = NULL;
client_set_queue (src->client, NULL);

View File

@ -396,6 +396,29 @@ void source_move_clients (source_t *source, source_t *dest)
thread_mutex_unlock (&move_clients_mutex);
}
/* Update stats from source processing, this should be called regulary (every
* few seconds) to keep totals up to date.
*/
static void update_source_stats (source_t *source)
{
int64_t kbytes_sent = source->bytes_sent_since_update/1024;
source->format->sent_bytes += kbytes_sent*1024;
source->bytes_sent_since_update %= 1024;
stats_event_args (source->mount, "outgoing_bitrate", "%ld",
(8 * rate_avg (source->format->out_bitrate))/1000);
stats_event_args (source->mount, "incoming_bitrate", "%ld",
(8 * rate_avg (source->format->in_bitrate))/1000);
stats_event_args (source->mount, "total_bytes_read",
FORMAT_UINT64, source->format->read_bytes);
stats_event_args (source->mount, "total_bytes_sent",
FORMAT_UINT64, source->format->sent_bytes);
if (source->client)
stats_event_args (source->mount, "connected", FORMAT_UINT64,
(uint64_t)(global.time - source->client->con->con_time));
stats_event_add (NULL, "stream_kbytes_sent", kbytes_sent);
}
/* get some data from the source. The stream data is placed in a refbuf
* and sent back, however NULL is also valid as in the case of a short
@ -438,16 +461,7 @@ static void get_next_buffer (source_t *source)
if (source->client && current >= source->client_stats_update)
{
stats_event_args (source->mount, "outgoing_bitrate", "%ld",
(8 * rate_avg (source->format->out_bitrate))/1000);
stats_event_args (source->mount, "incoming_bitrate", "%ld",
(8 * rate_avg (source->format->in_bitrate))/1000);
stats_event_args (source->mount, "total_bytes_read",
FORMAT_UINT64, source->format->read_bytes);
stats_event_args (source->mount, "total_bytes_sent",
FORMAT_UINT64, source->format->sent_bytes);
stats_event_args (source->mount, "connected", FORMAT_UINT64,
(uint64_t)(current - source->client->con->con_time));
update_source_stats (source);
source->client_stats_update = current + 5;
}
if (fds < 0)
@ -537,7 +551,7 @@ static int send_to_listener (source_t *source, client_t *client, int deletion_ex
{
int bytes;
int loop = 10; /* max number of iterations in one go */
int total_written = 0;
unsigned int total_written = 0;
int ret = 0;
while (1)
@ -574,7 +588,7 @@ static int send_to_listener (source_t *source, client_t *client, int deletion_ex
total_written += bytes;
}
rate_add (source->format->out_bitrate, total_written, global.time);
source->format->sent_bytes += total_written;
source->bytes_sent_since_update += total_written;
/* the refbuf referenced at head (last in queue) may be marked for deletion
* if so, check to see if this client is still referring to it */
@ -695,6 +709,7 @@ static void source_init (source_t *source)
DEBUG0("Source creation complete");
source->last_read = global.time;
source->prev_listeners = -1;
source->bytes_sent_since_update = 0;
source->running = 1;
source->fast_clients_p = &source->active_clients;
@ -800,6 +815,7 @@ static void source_shutdown (source_t *source)
INFO1("Source \"%s\" exiting", source->mount);
source->running = 0;
update_source_stats (source);
mountinfo = config_find_mount (config_get_config(), source->mount);
if (mountinfo)
{

View File

@ -70,6 +70,7 @@ typedef struct source_tag
int on_demand;
int on_demand_req;
int hidden;
uint64_t bytes_sent_since_update;
time_t last_read;

View File

@ -44,6 +44,7 @@
#ifdef _WIN32
#define vsnprintf _vsnprintf
#define snprintf _snprintf
#define atoll _atoi64
#endif
#define STATS_EVENT_SET 0
@ -400,24 +401,24 @@ static void modify_node_event (stats_node_t *node, stats_event_t *event)
}
if (event->action != STATS_EVENT_SET)
{
int value = 0;
int64_t value = 0;
switch (event->action)
{
case STATS_EVENT_INC:
value = atoi (node->value)+1;
value = atoll (node->value)+1;
break;
case STATS_EVENT_DEC:
value = atoi (node->value)-1;
value = atoll (node->value)-1;
break;
case STATS_EVENT_ADD:
value = atoi (node->value)+atoi (event->value);
value = atoll (node->value) + atoll (event->value);
break;
default:
break;
}
str = malloc (16);
snprintf (str, 16, "%d", value);
str = malloc (20);
snprintf (str, 20, FORMAT_INT64, value);
if (event->value == NULL)
event->value = strdup (str);
}

View File

@ -819,6 +819,8 @@ static void add_yp_info (ypdata_t *yp, void *info, int type)
free (yp->subtype);
yp->subtype = escaped;
break;
default:
free (escaped);
}
}