[xiph-cvs] cvs commit: icecast/src config.c config.h connection.c format.c format_mp3.c format_mp3.h refbuf.c refbuf.h slave.c source.c
Michael Smith
msmith at xiph.org
Mon Feb 24 05:37:16 PST 2003
msmith 03/02/24 08:37:16
Modified: . TODO
conf icecast.xml
src config.c config.h connection.c format.c
format_mp3.c format_mp3.h refbuf.c refbuf.h slave.c
source.c
Log:
Max queue length for clients is now
a) based on total bytes in queue, not total number of buffers in queue
b) configurable (defaults to 100 kB)
mp3 metadata relaying (inline). Untested.
Revision Changes Path
1.10 +6 -3 icecast/TODO
Index: TODO
===================================================================
RCS file: /usr/local/cvsroot/icecast/TODO,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- TODO 11 Feb 2003 14:23:33 -0000 1.9
+++ TODO 24 Feb 2003 13:37:15 -0000 1.10
@@ -2,12 +2,12 @@
----
- stats get off? this needs testing more testing.
-- autoconf doesn't set HAVE_POLL (still true?)
-
- some stuff (like 'genre') isn't making it into the stats dump
- make install - doesn't install configs?
+- logging - bytes send and time listening may both be broken?
+
FEATURES
--------
@@ -46,7 +46,10 @@
- httpp - split out query string for further processing
-- binding to multiple ports (possibly including full ipv6 support)
+- binding to multiple ports
+
+- option to use ipv6 (equiv to using <bind-address>::</bindaddress>, I think.
+- per-mountpoint listener maximums.
<p><p>1.17 +4 -0 icecast/conf/icecast.xml
Index: icecast.xml
===================================================================
RCS file: /usr/local/cvsroot/icecast/conf/icecast.xml,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- icecast.xml 11 Feb 2003 14:23:34 -0000 1.16
+++ icecast.xml 24 Feb 2003 13:37:15 -0000 1.17
@@ -6,6 +6,7 @@
<clients>100</clients>
<sources>2</sources>
<threadpool>5</threadpool>
+ <queue-size>102400</queue-size>
<client-timeout>30</client-timeout>
<header-timeout>15</header-timeout>
<source-timeout>10</source-timeout>
@@ -42,6 +43,9 @@
<server>127.0.0.1</server>
<port>8001</port>
<mount>/example.ogg</mount>
+ <local-mount>/different.ogg</local-mount>
+
+ <relay-shoutcast-metadata>0</relay-shoutcast-metadata>
</relay>
-->
<p><p>1.27 +11 -0 icecast/src/config.c
Index: config.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- config.c 12 Feb 2003 11:04:26 -0000 1.26
+++ config.c 24 Feb 2003 13:37:15 -0000 1.27
@@ -13,6 +13,7 @@
#define CONFIG_DEFAULT_ADMIN "icemaster at localhost"
#define CONFIG_DEFAULT_CLIENT_LIMIT 256
#define CONFIG_DEFAULT_SOURCE_LIMIT 16
+#define CONFIG_DEFAULT_QUEUE_SIZE_LIMIT (100*1024)
#define CONFIG_DEFAULT_THREADPOOL_SIZE 4
#define CONFIG_DEFAULT_CLIENT_TIMEOUT 30
#define CONFIG_DEFAULT_HEADER_TIMEOUT 15
@@ -193,6 +194,7 @@
_configuration.admin = CONFIG_DEFAULT_ADMIN;
_configuration.client_limit = CONFIG_DEFAULT_CLIENT_LIMIT;
_configuration.source_limit = CONFIG_DEFAULT_SOURCE_LIMIT;
+ _configuration.queue_size_limit = CONFIG_DEFAULT_QUEUE_SIZE_LIMIT;
_configuration.threadpool_size = CONFIG_DEFAULT_THREADPOOL_SIZE;
_configuration.client_timeout = CONFIG_DEFAULT_CLIENT_TIMEOUT;
_configuration.header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
@@ -318,6 +320,10 @@
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.source_limit = atoi(tmp);
if (tmp) xmlFree(tmp);
+ } else if (strcmp(node->name, "queue-size") == 0) {
+ tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ _configuration.queue_size_limit = atoi(tmp);
+ if (tmp) xmlFree(tmp);
} else if (strcmp(node->name, "threadpool") == 0) {
tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
_configuration.threadpool_size = atoi(tmp);
@@ -424,6 +430,11 @@
else if (strcmp(node->name, "local-mount") == 0) {
relay->localmount = (char *)xmlNodeListGetString(
doc, node->xmlChildrenNode, 1);
+ }
+ else if (strcmp(node->name, "relay-shoutcast-metadata") == 0) {
+ tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ relay->mp3metadata = atoi(tmp);
+ if(tmp) xmlFree(tmp);
}
} while ((node = node->next));
}
<p><p>1.16 +2 -0 icecast/src/config.h
Index: config.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- config.h 12 Feb 2003 11:04:26 -0000 1.15
+++ config.h 24 Feb 2003 13:37:15 -0000 1.16
@@ -20,6 +20,7 @@
int port;
char *mount;
char *localmount;
+ int mp3metadata;
struct _relay_server *next;
} relay_server;
@@ -44,6 +45,7 @@
int client_limit;
int source_limit;
+ long queue_size_limit;
int threadpool_size;
int client_timeout;
int header_timeout;
<p><p>1.54 +1 -0 icecast/src/connection.c
Index: connection.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- connection.c 20 Feb 2003 22:18:24 -0000 1.53
+++ connection.c 24 Feb 2003 13:37:15 -0000 1.54
@@ -535,6 +535,7 @@
free(state->metadata);
state->metadata = strdup(value);
state->metadata_age++;
+ state->metadata_raw = 0;
thread_mutex_unlock(&(state->lock));
DEBUG2("Metadata on mountpoint %s changed to \"%s\"", mount, value);
<p><p>1.19 +1 -1 icecast/src/format.c
Index: format.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/format.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- format.c 17 Feb 2003 12:05:45 -0000 1.18
+++ format.c 24 Feb 2003 13:37:15 -0000 1.19
@@ -80,7 +80,7 @@
client_t *client, unsigned char *buf, int len)
{
int ret;
-
+
ret = sock_write_bytes(client->con->sock, buf, len);
if(ret < 0) {
<p><p>1.15 +104 -10 icecast/src/format_mp3.c
Index: format_mp3.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/format_mp3.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- format_mp3.c 17 Feb 2003 12:05:45 -0000 1.14
+++ format_mp3.c 24 Feb 2003 13:37:15 -0000 1.15
@@ -101,15 +101,19 @@
return 0;
}
- fullmetadata_size = strlen(source_state->metadata) +
- strlen("StreamTitle='';StreamUrl=''") + 1;
-
- fullmetadata = alloca(fullmetadata_size);
+ if(source_state->metadata_raw) {
+ fullmetadata_size = strlen(source_state->metadata);
+ fullmetadata = source_state->metadata;
+ }
+ else {
+ fullmetadata_size = strlen(source_state->metadata) +
+ strlen("StreamTitle='';StreamUrl=''") + 1;
- memset(fullmetadata, 0, fullmetadata_size);
+ fullmetadata = alloca(fullmetadata_size);
- sprintf(fullmetadata, "StreamTitle='%s';StreamUrl=''",
- source_state->metadata);
+ sprintf(fullmetadata, "StreamTitle='%s';StreamUrl=''",
+ source_state->metadata);
+ }
source_age = source_state->metadata_age;
send_metadata = source_age != client_state->metadata_age;
@@ -210,14 +214,104 @@
refbuf_t *refbuf;
mp3_state *state = self->_state;
- if(!data) {
- *buffer = NULL;
+ /* Set this to NULL in case it doesn't get set to a valid buffer later */
+ *buffer = NULL;
+
+ if(!data)
return 0;
- }
+
if(state->inline_metadata_interval) {
+ /* Source is sending metadata, handle it... */
+
+ while(len > 0) {
+ int to_read = state->inline_metadata_interval - state->offset;
+ if(to_read > 0) {
+ refbuf_t *old_refbuf = *buffer;
+
+ if(to_read > len)
+ to_read = len;
+
+ if(old_refbuf) {
+ refbuf = refbuf_new(to_read + old_refbuf->len);
+ memcpy(refbuf->data, old_refbuf->data, old_refbuf->len);
+ memcpy(refbuf->data+old_refbuf->len, data, to_read);
+
+ refbuf_release(old_refbuf);
+ }
+ else {
+ refbuf = refbuf_new(to_read);
+ memcpy(refbuf->data, data, to_read);
+ }
+
+ *buffer = refbuf;
+
+ state->offset += to_read;
+ data += to_read;
+ len -= to_read;
+ }
+ else if(!state->metadata_length) {
+ /* Next up is the metadata byte... */
+ unsigned char byte = data[0];
+ data++;
+ len--;
+
+ /* According to the "spec"... this byte * 16 */
+ state->metadata_length = byte * 16;
+ if(state->metadata_length) {
+ state->metadata_buffer =
+ calloc(state->metadata_length + 1, 1);
+
+ /* Ensure we have a null-terminator even if the source
+ * stream is invalid.
+ */
+ state->metadata_buffer[state->metadata_length] = 0;
+ }
+ else {
+ state->offset = 0;
+ }
+
+ state->metadata_offset = 0;
+ }
+ else {
+ /* Metadata to read! */
+ int readable = state->metadata_length - state->metadata_offset;
+
+ if(readable > len)
+ readable = len;
+
+ memcpy(state->metadata_buffer + state->metadata_offset,
+ data, readable);
+
+ data += readable;
+ len -= readable;
+
+ if(state->metadata_offset == state->metadata_length)
+ {
+ state->offset = 0;
+ state->metadata_length = 0;
+
+ if(state->metadata_length)
+ {
+ thread_mutex_lock(&(state->lock));
+ free(state->metadata);
+ state->metadata = state->metadata_buffer;
+ state->metadata_buffer = NULL;
+ state->metadata_age++;
+ state->metadata_raw = 1;
+ thread_mutex_unlock(&(state->lock));
+ }
+ }
+ }
+ }
+
+ /* Either we got a buffer above (in which case it can be used), or
+ * we set *buffer to NULL in the prologue, so the return value is
+ * correct anyway...
+ */
return 0;
}
else {
+ /* Simple case - no metadata, just dump data directly to a buffer */
refbuf = refbuf_new(len);
memcpy(refbuf->data, data, len);
<p><p>1.5 +8 -2 icecast/src/format_mp3.h
Index: format_mp3.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/format_mp3.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- format_mp3.h 17 Feb 2003 12:05:45 -0000 1.4
+++ format_mp3.h 24 Feb 2003 13:37:15 -0000 1.5
@@ -9,9 +9,15 @@
typedef struct {
char *metadata;
int metadata_age;
- int metadata_formatted;
- int inline_metadata_interval;
+ int metadata_raw;
mutex_t lock;
+
+ /* These are for inline metadata */
+ int inline_metadata_interval;
+ int offset;
+ int metadata_length;
+ char *metadata_buffer;
+ int metadata_offset;
} mp3_state;
format_plugin_t *format_mp3_get_plugin(http_parser_t *parser);
<p><p>1.2 +12 -0 icecast/src/refbuf.c
Index: refbuf.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/refbuf.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- refbuf.c 10 Sep 2001 02:21:51 -0000 1.1
+++ refbuf.c 24 Feb 2003 13:37:15 -0000 1.2
@@ -83,8 +83,12 @@
refbuf = item->refbuf;
item->refbuf = NULL;
+
+ if(*queue)
+ (*queue)->total_length = item->total_length - refbuf->len;
free(item);
+
return refbuf;
}
@@ -95,6 +99,7 @@
item->refbuf = refbuf;
item->next = *queue;
+ item->total_length = item->next->total_length + item->refbuf->len;
*queue = item;
}
@@ -111,5 +116,12 @@
return size;
}
+int refbuf_queue_length(refbuf_queue_t **queue)
+{
+ if(*queue)
+ return (*queue)->total_length;
+ else
+ return 0;
+}
<p><p>1.2 +5 -0 icecast/src/refbuf.h
Index: refbuf.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/refbuf.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- refbuf.h 10 Sep 2001 02:21:51 -0000 1.1
+++ refbuf.h 24 Feb 2003 13:37:15 -0000 1.2
@@ -17,6 +17,7 @@
typedef struct _refbuf_queue_tag
{
refbuf_t *refbuf;
+ long total_length;
struct _refbuf_queue_tag *next;
} refbuf_queue_t;
@@ -31,7 +32,11 @@
void refbuf_queue_add(refbuf_queue_t **queue, refbuf_t *refbuf);
refbuf_t *refbuf_queue_remove(refbuf_queue_t **queue);
void refbuf_queue_insert(refbuf_queue_t **queue, refbuf_t *refbuf);
+
+/* Size in buffers */
int refbuf_queue_size(refbuf_queue_t **queue);
+/* Size in bytes */
+int refbuf_queue_length(refbuf_queue_t **queue);
#endif /* __REFBUF_H__ */
<p><p>1.19 +10 -4 icecast/src/slave.c
Index: slave.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/slave.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- slave.c 17 Feb 2003 11:56:12 -0000 1.18
+++ slave.c 24 Feb 2003 13:37:15 -0000 1.19
@@ -66,7 +66,7 @@
}
static void create_relay_stream(char *server, int port,
- char *remotemount, char *localmount)
+ char *remotemount, char *localmount, int mp3)
{
sock_t streamsock;
char header[4096];
@@ -85,7 +85,13 @@
return;
}
con = create_connection(streamsock, NULL);
- sock_write(streamsock, "GET %s HTTP/1.0\r\n\r\n", remotemount);
+ if(mp3) {
+ sock_write(streamsock, "GET %s HTTP/1.0\r\nIcy-MetaData: 1\r\n",
+ remotemount);
+ }
+ else {
+ sock_write(streamsock, "GET %s HTTP/1.0\r\n\r\n", remotemount);
+ }
memset(header, 0, sizeof(header));
if (util_read_header(con->sock, header, 4096) == 0) {
connection_close(con);
@@ -168,7 +174,7 @@
create_relay_stream(
config_get_config()->master_server,
config_get_config()->master_server_port,
- buf, NULL);
+ buf, NULL, 0);
}
else
avl_tree_unlock(global.source_tree);
@@ -184,7 +190,7 @@
avl_tree_unlock(global.source_tree);
create_relay_stream(relay->server, relay->port, relay->mount,
- relay->localmount);
+ relay->localmount, relay->mp3metadata);
}
else
avl_tree_unlock(global.source_tree);
<p><p>1.35 +3 -3 icecast/src/source.c
Index: source.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- source.c 17 Feb 2003 13:01:37 -0000 1.34
+++ source.c 24 Feb 2003 13:37:15 -0000 1.35
@@ -153,6 +153,8 @@
int i=0;
int suppress_yp = 0;
+ long queue_limit = config_get_config()->queue_size_limit;
+
timeout = config_get_config()->source_timeout;
/* grab a read lock, to make sure we get a chance to cleanup */
@@ -447,10 +449,8 @@
/* if the client is too slow, its queue will slowly build up.
** we need to make sure the client is keeping up with the
** data, so we'll kick any client who's queue gets to large.
- ** the queue_limit might need to be tuned, but should work fine.
- ** TODO: put queue_limit in a config file
*/
- if (refbuf_queue_size(&client->queue) > 25) {
+ if (refbuf_queue_length(&client->queue) > queue_limit) {
DEBUG0("Client has fallen too far behind, removing");
client->con->error = 1;
}
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list