From b8e157d7d133158c41455cf5a51674b1cc49fd72 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sun, 29 Dec 2002 08:10:10 +0000 Subject: [PATCH] Add infrastructure for better/more flexible format support. Will be needed for mp3 metadata, for example. svn path=/trunk/icecast/; revision=4167 --- src/client.h | 3 +++ src/connection.c | 2 +- src/format.c | 23 +++++++++++++++++++++++ src/format.h | 10 ++++++++++ src/format_mp3.c | 13 ++++++++++--- src/format_vorbis.c | 13 ++++++++++--- src/main.c | 7 ++++--- src/source.c | 37 ++++++++++++------------------------- 8 files changed, 73 insertions(+), 35 deletions(-) diff --git a/src/client.h b/src/client.h index 9fa6bc38..5af322eb 100644 --- a/src/client.h +++ b/src/client.h @@ -20,6 +20,9 @@ typedef struct _client_tag refbuf_queue_t *queue; /* position in first buffer */ unsigned long pos; + + /* Format-handler-specific data for this client */ + void *format_data; } client_t; client_t *client_create(connection_t *con, http_parser_t *parser); diff --git a/src/connection.c b/src/connection.c index f56782e1..4894806a 100644 --- a/src/connection.c +++ b/src/connection.c @@ -122,7 +122,7 @@ static connection_t *_accept_connection(void) return NULL; } - /* malloc enough room for 123.123.123.123\0 */ + /* malloc enough room for 123.123.123.123\0 (TODO: ipv6?)*/ ip = (char *)malloc(16); sock = sock_accept(global.serversock, ip, 16); diff --git a/src/format.c b/src/format.c index c10a9809..bf685eb0 100644 --- a/src/format.c +++ b/src/format.c @@ -16,6 +16,9 @@ #include "format_vorbis.h" #include "format_mp3.h" +#include "logging.h" +#define CATMODULE "format" + format_type_t format_get_type(char *contenttype) { if(strcmp(contenttype, "application/x-ogg") == 0) @@ -60,3 +63,23 @@ format_plugin_t *format_get_plugin(format_type_t type, char *mount) return plugin; } + +int format_generic_write_buf_to_client(format_plugin_t *format, + client_t *client, unsigned char *buf, int len) +{ + int ret; + + ret = sock_write_bytes(client->con->sock, buf, len); + + if(ret < 0) { + if(sock_recoverable(ret)) { + DEBUG1("Client had recoverable error %ld", ret); + ret = 0; + } + } + else + client->con->sent_bytes += ret; + + return ret; +} + diff --git a/src/format.h b/src/format.h index 946bc224..e9f3585b 100644 --- a/src/format.h +++ b/src/format.h @@ -6,6 +6,9 @@ #ifndef __FORMAT_H__ #define __FORMAT_H__ +#include "client.h" +#include "refbuf.h" + typedef enum _format_type_tag { FORMAT_TYPE_VORBIS, @@ -29,6 +32,10 @@ typedef struct _format_plugin_tag int (*get_buffer)(struct _format_plugin_tag *self, char *data, unsigned long len, refbuf_t **buffer); refbuf_queue_t *(*get_predata)(struct _format_plugin_tag *self); + int (*write_buf_to_client)(struct _format_plugin_tag *format, + client_t *client, unsigned char *buf, int len); + void *(*create_client_data)(struct _format_plugin_tag *format); + void (*free_plugin)(struct _format_plugin_tag *self); /* for internal state management */ @@ -39,6 +46,9 @@ format_type_t format_get_type(char *contenttype); char *format_get_mimetype(format_type_t type); format_plugin_t *format_get_plugin(format_type_t type, char *mount); +int format_generic_write_buf_to_client(format_plugin_t *format, + client_t *client, unsigned char *buf, int len); + #endif /* __FORMAT_H__ */ diff --git a/src/format_mp3.c b/src/format_mp3.c index 50253b21..acabd73c 100644 --- a/src/format_mp3.c +++ b/src/format_mp3.c @@ -13,9 +13,11 @@ #include "stats.h" #include "format.h" -void format_mp3_free_plugin(format_plugin_t *self); -int format_mp3_get_buffer(format_plugin_t *self, char *data, unsigned long len, refbuf_t **buffer); -refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self); +static void format_mp3_free_plugin(format_plugin_t *self); +static int format_mp3_get_buffer(format_plugin_t *self, char *data, + unsigned long len, refbuf_t **buffer); +static refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self); +static void *format_mp3_create_client_data(format_plugin_t *self); format_plugin_t *format_mp3_get_plugin(void) { @@ -27,6 +29,8 @@ format_plugin_t *format_mp3_get_plugin(void) plugin->has_predata = 0; plugin->get_buffer = format_mp3_get_buffer; plugin->get_predata = format_mp3_get_predata; + plugin->write_buf_to_client = format_generic_write_buf_to_client; + plugin->create_client_data = format_mp3_create_client_data; plugin->free_plugin = format_mp3_free_plugin; plugin->format_description = "MP3 audio"; @@ -61,5 +65,8 @@ refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self) return NULL; } +static void *format_mp3_create_client_data(format_plugin_t *self) { + return NULL; +} diff --git a/src/format_vorbis.c b/src/format_vorbis.c index 0f0a0267..a5ade849 100644 --- a/src/format_vorbis.c +++ b/src/format_vorbis.c @@ -36,9 +36,11 @@ typedef struct _vstate_tag int packets; } vstate_t; -void format_vorbis_free_plugin(format_plugin_t *self); -int format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long len, refbuf_t **buffer); -refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self); +static void format_vorbis_free_plugin(format_plugin_t *self); +static int format_vorbis_get_buffer(format_plugin_t *self, char *data, + unsigned long len, refbuf_t **buffer); +static refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self); +static void *format_vorbis_create_client_data(format_plugin_t *self); format_plugin_t *format_vorbis_get_plugin(void) { @@ -51,6 +53,8 @@ format_plugin_t *format_vorbis_get_plugin(void) plugin->has_predata = 1; plugin->get_buffer = format_vorbis_get_buffer; plugin->get_predata = format_vorbis_get_predata; + plugin->write_buf_to_client = format_generic_write_buf_to_client; + plugin->create_client_data = format_vorbis_create_client_data; plugin->free_plugin = format_vorbis_free_plugin; plugin->format_description = "Ogg Vorbis"; @@ -214,5 +218,8 @@ refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self) return queue; } +static void *format_vorbis_create_client_data(format_plugin_t *self) { + return NULL; +} diff --git a/src/main.c b/src/main.c index 8a9b5ba5..5d051e4d 100644 --- a/src/main.c +++ b/src/main.c @@ -91,7 +91,8 @@ static int _parse_config_file(int argc, char **argv, char *filename, int size) while (i < argc) { if (strcmp(argv[i], "-c") == 0) { if (i + 1 < argc) { - strncpy(filename, argv[i + 1], size); + strncpy(filename, argv[i + 1], size-1); + filename[size-1] = 0; return 1; } else { return -1; @@ -262,12 +263,12 @@ static void _ch_root_uid_setup(void) int main(int argc, char **argv) { int res, ret; - char filename[256]; + char filename[512]; /* parse the '-c icecast.xml' option ** only, so that we can read a configfile */ - res = _parse_config_file(argc, argv, filename, 256); + res = _parse_config_file(argc, argv, filename, 512); if (res == 1) { /* startup all the modules */ _initialize_subsystems(); diff --git a/src/source.c b/src/source.c index 67caa424..24bbd2ac 100644 --- a/src/source.c +++ b/src/source.c @@ -219,9 +219,9 @@ void *source_main(void *arg) else bytes = abuf->len; - sbytes = sock_write_bytes(client->con->sock, &abuf->data[client->pos], bytes); + sbytes = source->format->write_buf_to_client(source->format, + client, &abuf->data[client->pos], bytes); if (sbytes >= 0) { - client->con->sent_bytes += sbytes; if(sbytes != bytes) { /* We didn't send the entire buffer. Leave it for * the moment, handle it in the next iteration. @@ -232,16 +232,9 @@ void *source_main(void *arg) break; } } - if (sbytes < 0) { - if (!sock_recoverable(sock_error())) { - DEBUG0("Client has unrecoverable error catching up. Client has probably disconnected"); - client->con->error = 1; - } else { - DEBUG1("Client had recoverable error %ld", sock_error()); - /* put the refbuf back on top of the queue, since we didn't finish with it */ - refbuf_queue_insert(&client->queue, abuf); - } - + else { + DEBUG0("Client has unrecoverable error catching up. Client has probably disconnected"); + client->con->error = 1; data_done = 1; break; } @@ -258,9 +251,9 @@ void *source_main(void *arg) refbuf_addref(refbuf); refbuf_queue_add(&client->queue, refbuf); } else { - sbytes = sock_write_bytes(client->con->sock, refbuf->data, refbuf->len); + sbytes = source->format->write_buf_to_client(source->format, + client, refbuf->data, refbuf->len); if (sbytes >= 0) { - client->con->sent_bytes += sbytes; if(sbytes != refbuf->len) { /* Didn't send the entire buffer, queue it */ client->pos = sbytes; @@ -268,17 +261,9 @@ void *source_main(void *arg) refbuf_queue_insert(&client->queue, refbuf); } } - if (sbytes < 0) { - bytes = sock_error(); - if (!sock_recoverable(bytes)) { - DEBUG0("Client had unrecoverable error with new data, probably due to client disconnection"); - client->con->error = 1; - } else { - DEBUG1("Client had recoverable error %ld", bytes); - client->pos = 0; - refbuf_addref(refbuf); - refbuf_queue_insert(&client->queue, refbuf); - } + else { + DEBUG0("Client had unrecoverable error with new data, probably due to client disconnection"); + client->con->error = 1; } } @@ -340,6 +325,8 @@ void *source_main(void *arg) */ if (source->format->has_predata) { client = (client_t *)client_node->key; + client->format_data = source->format->create_client_data( + source->format); client->queue = source->format->get_predata(source->format); }