mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Add infrastructure for better/more flexible format support. Will be needed
for mp3 metadata, for example. svn path=/trunk/icecast/; revision=4167
This commit is contained in:
parent
b3bc17fa73
commit
b8e157d7d1
@ -20,6 +20,9 @@ typedef struct _client_tag
|
|||||||
refbuf_queue_t *queue;
|
refbuf_queue_t *queue;
|
||||||
/* position in first buffer */
|
/* position in first buffer */
|
||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
|
|
||||||
|
/* Format-handler-specific data for this client */
|
||||||
|
void *format_data;
|
||||||
} client_t;
|
} client_t;
|
||||||
|
|
||||||
client_t *client_create(connection_t *con, http_parser_t *parser);
|
client_t *client_create(connection_t *con, http_parser_t *parser);
|
||||||
|
@ -122,7 +122,7 @@ static connection_t *_accept_connection(void)
|
|||||||
return NULL;
|
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);
|
ip = (char *)malloc(16);
|
||||||
|
|
||||||
sock = sock_accept(global.serversock, ip, 16);
|
sock = sock_accept(global.serversock, ip, 16);
|
||||||
|
23
src/format.c
23
src/format.c
@ -16,6 +16,9 @@
|
|||||||
#include "format_vorbis.h"
|
#include "format_vorbis.h"
|
||||||
#include "format_mp3.h"
|
#include "format_mp3.h"
|
||||||
|
|
||||||
|
#include "logging.h"
|
||||||
|
#define CATMODULE "format"
|
||||||
|
|
||||||
format_type_t format_get_type(char *contenttype)
|
format_type_t format_get_type(char *contenttype)
|
||||||
{
|
{
|
||||||
if(strcmp(contenttype, "application/x-ogg") == 0)
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
10
src/format.h
10
src/format.h
@ -6,6 +6,9 @@
|
|||||||
#ifndef __FORMAT_H__
|
#ifndef __FORMAT_H__
|
||||||
#define __FORMAT_H__
|
#define __FORMAT_H__
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include "refbuf.h"
|
||||||
|
|
||||||
typedef enum _format_type_tag
|
typedef enum _format_type_tag
|
||||||
{
|
{
|
||||||
FORMAT_TYPE_VORBIS,
|
FORMAT_TYPE_VORBIS,
|
||||||
@ -29,6 +32,10 @@ typedef struct _format_plugin_tag
|
|||||||
int (*get_buffer)(struct _format_plugin_tag *self, char *data, unsigned long
|
int (*get_buffer)(struct _format_plugin_tag *self, char *data, unsigned long
|
||||||
len, refbuf_t **buffer);
|
len, refbuf_t **buffer);
|
||||||
refbuf_queue_t *(*get_predata)(struct _format_plugin_tag *self);
|
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);
|
void (*free_plugin)(struct _format_plugin_tag *self);
|
||||||
|
|
||||||
/* for internal state management */
|
/* for internal state management */
|
||||||
@ -39,6 +46,9 @@ format_type_t format_get_type(char *contenttype);
|
|||||||
char *format_get_mimetype(format_type_t type);
|
char *format_get_mimetype(format_type_t type);
|
||||||
format_plugin_t *format_get_plugin(format_type_t type, char *mount);
|
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__ */
|
#endif /* __FORMAT_H__ */
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,9 +13,11 @@
|
|||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
||||||
void format_mp3_free_plugin(format_plugin_t *self);
|
static 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);
|
static int format_mp3_get_buffer(format_plugin_t *self, char *data,
|
||||||
refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self);
|
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)
|
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->has_predata = 0;
|
||||||
plugin->get_buffer = format_mp3_get_buffer;
|
plugin->get_buffer = format_mp3_get_buffer;
|
||||||
plugin->get_predata = format_mp3_get_predata;
|
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->free_plugin = format_mp3_free_plugin;
|
||||||
plugin->format_description = "MP3 audio";
|
plugin->format_description = "MP3 audio";
|
||||||
|
|
||||||
@ -61,5 +65,8 @@ refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *format_mp3_create_client_data(format_plugin_t *self) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,9 +36,11 @@ typedef struct _vstate_tag
|
|||||||
int packets;
|
int packets;
|
||||||
} vstate_t;
|
} vstate_t;
|
||||||
|
|
||||||
void format_vorbis_free_plugin(format_plugin_t *self);
|
static 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);
|
static int format_vorbis_get_buffer(format_plugin_t *self, char *data,
|
||||||
refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self);
|
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)
|
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->has_predata = 1;
|
||||||
plugin->get_buffer = format_vorbis_get_buffer;
|
plugin->get_buffer = format_vorbis_get_buffer;
|
||||||
plugin->get_predata = format_vorbis_get_predata;
|
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->free_plugin = format_vorbis_free_plugin;
|
||||||
plugin->format_description = "Ogg Vorbis";
|
plugin->format_description = "Ogg Vorbis";
|
||||||
|
|
||||||
@ -214,5 +218,8 @@ refbuf_queue_t *format_vorbis_get_predata(format_plugin_t *self)
|
|||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *format_vorbis_create_client_data(format_plugin_t *self) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +91,8 @@ static int _parse_config_file(int argc, char **argv, char *filename, int size)
|
|||||||
while (i < argc) {
|
while (i < argc) {
|
||||||
if (strcmp(argv[i], "-c") == 0) {
|
if (strcmp(argv[i], "-c") == 0) {
|
||||||
if (i + 1 < argc) {
|
if (i + 1 < argc) {
|
||||||
strncpy(filename, argv[i + 1], size);
|
strncpy(filename, argv[i + 1], size-1);
|
||||||
|
filename[size-1] = 0;
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
@ -262,12 +263,12 @@ static void _ch_root_uid_setup(void)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int res, ret;
|
int res, ret;
|
||||||
char filename[256];
|
char filename[512];
|
||||||
|
|
||||||
/* parse the '-c icecast.xml' option
|
/* parse the '-c icecast.xml' option
|
||||||
** only, so that we can read a configfile
|
** 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) {
|
if (res == 1) {
|
||||||
/* startup all the modules */
|
/* startup all the modules */
|
||||||
_initialize_subsystems();
|
_initialize_subsystems();
|
||||||
|
37
src/source.c
37
src/source.c
@ -219,9 +219,9 @@ void *source_main(void *arg)
|
|||||||
else
|
else
|
||||||
bytes = abuf->len;
|
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) {
|
if (sbytes >= 0) {
|
||||||
client->con->sent_bytes += sbytes;
|
|
||||||
if(sbytes != bytes) {
|
if(sbytes != bytes) {
|
||||||
/* We didn't send the entire buffer. Leave it for
|
/* We didn't send the entire buffer. Leave it for
|
||||||
* the moment, handle it in the next iteration.
|
* the moment, handle it in the next iteration.
|
||||||
@ -232,16 +232,9 @@ void *source_main(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sbytes < 0) {
|
else {
|
||||||
if (!sock_recoverable(sock_error())) {
|
DEBUG0("Client has unrecoverable error catching up. Client has probably disconnected");
|
||||||
DEBUG0("Client has unrecoverable error catching up. Client has probably disconnected");
|
client->con->error = 1;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
data_done = 1;
|
data_done = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -258,9 +251,9 @@ void *source_main(void *arg)
|
|||||||
refbuf_addref(refbuf);
|
refbuf_addref(refbuf);
|
||||||
refbuf_queue_add(&client->queue, refbuf);
|
refbuf_queue_add(&client->queue, refbuf);
|
||||||
} else {
|
} 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) {
|
if (sbytes >= 0) {
|
||||||
client->con->sent_bytes += sbytes;
|
|
||||||
if(sbytes != refbuf->len) {
|
if(sbytes != refbuf->len) {
|
||||||
/* Didn't send the entire buffer, queue it */
|
/* Didn't send the entire buffer, queue it */
|
||||||
client->pos = sbytes;
|
client->pos = sbytes;
|
||||||
@ -268,17 +261,9 @@ void *source_main(void *arg)
|
|||||||
refbuf_queue_insert(&client->queue, refbuf);
|
refbuf_queue_insert(&client->queue, refbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sbytes < 0) {
|
else {
|
||||||
bytes = sock_error();
|
DEBUG0("Client had unrecoverable error with new data, probably due to client disconnection");
|
||||||
if (!sock_recoverable(bytes)) {
|
client->con->error = 1;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,6 +325,8 @@ void *source_main(void *arg)
|
|||||||
*/
|
*/
|
||||||
if (source->format->has_predata) {
|
if (source->format->has_predata) {
|
||||||
client = (client_t *)client_node->key;
|
client = (client_t *)client_node->key;
|
||||||
|
client->format_data = source->format->create_client_data(
|
||||||
|
source->format);
|
||||||
client->queue = source->format->get_predata(source->format);
|
client->queue = source->format->get_predata(source->format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user