mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Do normal http header writing in source thread instead of the connection
thread, this will allow on-demand relays to fail and still handle the initial listener correctly (fallback or 404 response). svn path=/icecast/trunk/icecast/; revision=9399
This commit is contained in:
parent
b8f6429198
commit
743dbbaeca
@ -63,7 +63,7 @@ client_t *client_create(connection_t *con, http_parser_t *parser)
|
|||||||
client->parser = parser;
|
client->parser = parser;
|
||||||
client->refbuf = NULL;
|
client->refbuf = NULL;
|
||||||
client->pos = 0;
|
client->pos = 0;
|
||||||
client->check_buffer = format_advance_queue;
|
client->write_to_client = format_generic_write_to_client;
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,9 @@ typedef struct _client_tag
|
|||||||
/* function to call to release format specific resources */
|
/* function to call to release format specific resources */
|
||||||
void (*free_client_data)(struct _client_tag *client);
|
void (*free_client_data)(struct _client_tag *client);
|
||||||
|
|
||||||
|
/* write out data associated with client */
|
||||||
|
int (*write_to_client)(struct _client_tag *client);
|
||||||
|
|
||||||
/* function to check if refbuf needs updating */
|
/* function to check if refbuf needs updating */
|
||||||
int (*check_buffer)(struct source_tag *source, struct _client_tag *client);
|
int (*check_buffer)(struct source_tag *source, struct _client_tag *client);
|
||||||
|
|
||||||
|
@ -943,17 +943,12 @@ static void _handle_get_request (client_t *client, char *passed_uri)
|
|||||||
}
|
}
|
||||||
global_unlock();
|
global_unlock();
|
||||||
|
|
||||||
source->format->create_client_data (source, client);
|
|
||||||
|
|
||||||
source->format->client_send_headers(source->format, source, client);
|
|
||||||
|
|
||||||
bytes = sock_write(client->con->sock, "\r\n");
|
|
||||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
|
||||||
|
|
||||||
sock_set_blocking(client->con->sock, SOCK_NONBLOCK);
|
sock_set_blocking(client->con->sock, SOCK_NONBLOCK);
|
||||||
sock_set_nodelay(client->con->sock);
|
sock_set_nodelay(client->con->sock);
|
||||||
|
|
||||||
client->check_buffer = format_check_file_buffer;
|
client->write_to_client = format_generic_write_to_client;
|
||||||
|
client->check_buffer = format_check_http_buffer;
|
||||||
|
client->refbuf = refbuf_new (4096);
|
||||||
|
|
||||||
avl_tree_wlock(source->pending_tree);
|
avl_tree_wlock(source->pending_tree);
|
||||||
avl_insert(source->pending_tree, (void *)client);
|
avl_insert(source->pending_tree, (void *)client);
|
||||||
|
147
src/format.c
147
src/format.c
@ -46,8 +46,12 @@
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#define strcasecmp stricmp
|
#define strcasecmp stricmp
|
||||||
#define strncasecmp strnicmp
|
#define strncasecmp strnicmp
|
||||||
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int format_prepare_headers (source_t *source, client_t *client);
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
@ -144,18 +148,10 @@ int format_check_file_buffer (source_t *source, client_t *client)
|
|||||||
|
|
||||||
if (refbuf == NULL)
|
if (refbuf == NULL)
|
||||||
{
|
{
|
||||||
if (source->intro_file && client->intro_offset == 0)
|
/* client refers to no data, must be from a move */
|
||||||
{
|
|
||||||
refbuf = refbuf_new (4096);
|
|
||||||
client->refbuf = refbuf;
|
|
||||||
client->pos = refbuf->len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
find_client_start (source, client);
|
find_client_start (source, client);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (client->pos == refbuf->len)
|
if (client->pos == refbuf->len)
|
||||||
{
|
{
|
||||||
if (get_file_data (source->intro_file, client))
|
if (get_file_data (source->intro_file, client))
|
||||||
@ -168,7 +164,6 @@ int format_check_file_buffer (source_t *source, client_t *client)
|
|||||||
if (source->stream_data_tail)
|
if (source->stream_data_tail)
|
||||||
{
|
{
|
||||||
/* better find the right place in queue for this client */
|
/* better find the right place in queue for this client */
|
||||||
client->intro_offset = -1;
|
|
||||||
client_set_queue (client, NULL);
|
client_set_queue (client, NULL);
|
||||||
find_client_start (source, client);
|
find_client_start (source, client);
|
||||||
}
|
}
|
||||||
@ -181,6 +176,57 @@ int format_check_file_buffer (source_t *source, client_t *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* call this to verify that the HTTP data has been sent and if so setup
|
||||||
|
* callbacks to the appropriate format functions
|
||||||
|
*/
|
||||||
|
int format_check_http_buffer (source_t *source, client_t *client)
|
||||||
|
{
|
||||||
|
refbuf_t *refbuf = client->refbuf;
|
||||||
|
|
||||||
|
if (refbuf == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (client->respcode == 0)
|
||||||
|
{
|
||||||
|
DEBUG0("processing pending client headers");
|
||||||
|
|
||||||
|
client->respcode = 200;
|
||||||
|
if (format_prepare_headers (source, client) < 0)
|
||||||
|
{
|
||||||
|
ERROR0 ("internal problem, dropping client");
|
||||||
|
client->con->error = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->pos == refbuf->len)
|
||||||
|
{
|
||||||
|
client->write_to_client = source->format->write_buf_to_client;
|
||||||
|
client->check_buffer = format_check_file_buffer;
|
||||||
|
client->intro_offset = 0;
|
||||||
|
client->pos = refbuf->len = 4096;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int format_generic_write_to_client (client_t *client)
|
||||||
|
{
|
||||||
|
refbuf_t *refbuf = client->refbuf;
|
||||||
|
int ret;
|
||||||
|
const char *buf = refbuf->data + client->pos;
|
||||||
|
unsigned int len = refbuf->len - client->pos;
|
||||||
|
|
||||||
|
ret = client_send_bytes (client, buf, len);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
client->pos += ret;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is the commonly used for source streams, here we just progress to
|
/* This is the commonly used for source streams, here we just progress to
|
||||||
* the next buffer in the queue if there is no more left to be written from
|
* the next buffer in the queue if there is no more left to be written from
|
||||||
* the existing buffer.
|
* the existing buffer.
|
||||||
@ -205,64 +251,95 @@ int format_advance_queue (source_t *source, client_t *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void format_send_general_headers(format_plugin_t *format,
|
static int format_prepare_headers (source_t *source, client_t *client)
|
||||||
source_t *source, client_t *client)
|
|
||||||
{
|
{
|
||||||
http_var_t *var;
|
unsigned remaining;
|
||||||
avl_node *node;
|
char *ptr;
|
||||||
int bytes;
|
int bytes;
|
||||||
|
int bitrate_filtered = 0;
|
||||||
|
avl_node *node;
|
||||||
|
|
||||||
|
remaining = client->refbuf->len;
|
||||||
|
ptr = client->refbuf->data;
|
||||||
|
client->respcode = 200;
|
||||||
|
|
||||||
|
bytes = snprintf (ptr, remaining, "HTTP/1.0 200 OK\r\n"
|
||||||
|
"Content-Type: %s\r\n", source->format->contenttype);
|
||||||
|
|
||||||
|
remaining -= bytes;
|
||||||
|
ptr += bytes;
|
||||||
|
|
||||||
/* iterate through source http headers and send to client */
|
/* iterate through source http headers and send to client */
|
||||||
avl_tree_rlock(source->parser->vars);
|
avl_tree_rlock(source->parser->vars);
|
||||||
node = avl_get_first(source->parser->vars);
|
node = avl_get_first(source->parser->vars);
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
var = (http_var_t *)node->key;
|
int next = 1;
|
||||||
if (!strcasecmp(var->name, "ice-audio-info")) {
|
http_var_t *var = (http_var_t *)node->key;
|
||||||
|
bytes = 0;
|
||||||
|
if (!strcasecmp(var->name, "ice-audio-info"))
|
||||||
|
{
|
||||||
/* convert ice-audio-info to icy-br */
|
/* convert ice-audio-info to icy-br */
|
||||||
char *brfield;
|
char *brfield = NULL;
|
||||||
unsigned int bitrate;
|
unsigned int bitrate;
|
||||||
|
|
||||||
|
if (bitrate_filtered == 0)
|
||||||
brfield = strstr(var->value, "bitrate=");
|
brfield = strstr(var->value, "bitrate=");
|
||||||
if (brfield && sscanf(var->value, "bitrate=%u", &bitrate)) {
|
if (brfield && sscanf (brfield, "bitrate=%u", &bitrate))
|
||||||
bytes = sock_write(client->con->sock, "icy-br:%u\r\n", bitrate);
|
{
|
||||||
if (bytes > 0)
|
bytes = snprintf (ptr, remaining, "icy-br:%u\r\n", bitrate);
|
||||||
client->con->sent_bytes += bytes;
|
next = 0;
|
||||||
|
bitrate_filtered = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
/* show ice-audio_info header as well because of relays */
|
||||||
|
bytes = snprintf (ptr, remaining, "%s: %s\r\n", var->name, var->value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (strcasecmp(var->name, "ice-password") &&
|
if (strcasecmp(var->name, "ice-password") &&
|
||||||
strcasecmp(var->name, "icy-metaint"))
|
strcasecmp(var->name, "icy-metaint"))
|
||||||
{
|
{
|
||||||
bytes = 0;
|
|
||||||
if (!strncasecmp("ice-", var->name, 4))
|
if (!strncasecmp("ice-", var->name, 4))
|
||||||
{
|
{
|
||||||
if (!strcasecmp("ice-bitrate", var->name))
|
|
||||||
bytes += sock_write(client->con->sock, "icy-br:%s\r\n", var->value);
|
|
||||||
else
|
|
||||||
if (!strcasecmp("ice-public", var->name))
|
if (!strcasecmp("ice-public", var->name))
|
||||||
bytes += sock_write(client->con->sock,
|
bytes = snprintf (ptr, remaining, "icy-pub:%s\r\n", var->value);
|
||||||
"icy-pub:%s\r\n", var->value);
|
|
||||||
else
|
else
|
||||||
bytes = sock_write(client->con->sock, "icy%s:%s\r\n",
|
if (!strcasecmp ("ice-bitrate", var->name))
|
||||||
|
bytes = snprintf (ptr, remaining, "icy-br:%s\r\n", var->value);
|
||||||
|
else
|
||||||
|
bytes = snprintf (ptr, remaining, "icy%s:%s\r\n",
|
||||||
var->name + 3, var->value);
|
var->name + 3, var->value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!strncasecmp("icy-", var->name, 4))
|
if (!strncasecmp("icy-", var->name, 4))
|
||||||
{
|
{
|
||||||
bytes = sock_write(client->con->sock, "icy%s:%s\r\n",
|
bytes = snprintf (ptr, remaining, "icy%s:%s\r\n",
|
||||||
var->name + 3, var->value);
|
var->name + 3, var->value);
|
||||||
}
|
}
|
||||||
if (bytes > 0)
|
|
||||||
client->con->sent_bytes += bytes;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remaining -= bytes;
|
||||||
|
ptr += bytes;
|
||||||
|
if (next)
|
||||||
node = avl_get_next(node);
|
node = avl_get_next(node);
|
||||||
}
|
}
|
||||||
avl_tree_unlock(source->parser->vars);
|
avl_tree_unlock(source->parser->vars);
|
||||||
bytes = sock_write(client->con->sock,
|
|
||||||
"Server: %s\r\n", ICECAST_VERSION_STRING);
|
bytes = snprintf (ptr, remaining, "Server: %s\r\n", ICECAST_VERSION_STRING);
|
||||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
remaining -= bytes;
|
||||||
|
ptr += bytes;
|
||||||
|
|
||||||
|
bytes = snprintf (ptr, remaining, "\r\n");
|
||||||
|
remaining -= bytes;
|
||||||
|
ptr += bytes;
|
||||||
|
|
||||||
|
client->refbuf->len -= remaining;
|
||||||
|
if (source->format->create_client_data)
|
||||||
|
if (source->format->create_client_data (source, client) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,11 +44,9 @@ typedef struct _format_plugin_tag
|
|||||||
uint64_t sent_bytes;
|
uint64_t sent_bytes;
|
||||||
|
|
||||||
refbuf_t *(*get_buffer)(struct source_tag *);
|
refbuf_t *(*get_buffer)(struct source_tag *);
|
||||||
int (*write_buf_to_client)(struct _format_plugin_tag *format, client_t *client);
|
int (*write_buf_to_client)(client_t *client);
|
||||||
void (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf);
|
void (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf);
|
||||||
int (*create_client_data)(struct source_tag *source, client_t *client);
|
int (*create_client_data)(struct source_tag *source, client_t *client);
|
||||||
void (*client_send_headers)(struct _format_plugin_tag *format,
|
|
||||||
struct source_tag *source, client_t *client);
|
|
||||||
void (*set_tag)(struct _format_plugin_tag *plugin, char *tag, char *value);
|
void (*set_tag)(struct _format_plugin_tag *plugin, char *tag, char *value);
|
||||||
void (*free_plugin)(struct _format_plugin_tag *self);
|
void (*free_plugin)(struct _format_plugin_tag *self);
|
||||||
void (*apply_settings)(client_t *client, struct _format_plugin_tag *format, struct _mount_proxy *mount);
|
void (*apply_settings)(client_t *client, struct _format_plugin_tag *format, struct _mount_proxy *mount);
|
||||||
@ -61,7 +59,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);
|
||||||
int format_get_plugin(format_type_t type, struct source_tag *source);
|
int format_get_plugin(format_type_t type, struct source_tag *source);
|
||||||
|
|
||||||
|
int format_generic_write_to_client (client_t *client);
|
||||||
int format_advance_queue (struct source_tag *source, client_t *client);
|
int format_advance_queue (struct source_tag *source, client_t *client);
|
||||||
|
int format_check_http_buffer (struct source_tag *source, client_t *client);
|
||||||
int format_check_file_buffer (struct source_tag *source, client_t *client);
|
int format_check_file_buffer (struct source_tag *source, client_t *client);
|
||||||
|
|
||||||
void format_send_general_headers(format_plugin_t *format,
|
void format_send_general_headers(format_plugin_t *format,
|
||||||
|
@ -59,9 +59,7 @@ static refbuf_t *mp3_get_no_meta (source_t *source);
|
|||||||
|
|
||||||
static int format_mp3_create_client_data (source_t *source, client_t *client);
|
static int format_mp3_create_client_data (source_t *source, client_t *client);
|
||||||
static void free_mp3_client_data (client_t *client);
|
static void free_mp3_client_data (client_t *client);
|
||||||
static int format_mp3_write_buf_to_client(format_plugin_t *self, client_t *client);
|
static int format_mp3_write_buf_to_client(client_t *client);
|
||||||
static void format_mp3_send_headers(format_plugin_t *self,
|
|
||||||
source_t *source, client_t *client);
|
|
||||||
static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf);
|
static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf);
|
||||||
static void mp3_set_tag (format_plugin_t *plugin, char *tag, char *value);
|
static void mp3_set_tag (format_plugin_t *plugin, char *tag, char *value);
|
||||||
static void format_mp3_apply_settings(client_t *client, format_plugin_t *format, mount_proxy *mount);
|
static void format_mp3_apply_settings(client_t *client, format_plugin_t *format, mount_proxy *mount);
|
||||||
@ -89,7 +87,6 @@ int format_mp3_get_plugin (source_t *source)
|
|||||||
plugin->write_buf_to_client = format_mp3_write_buf_to_client;
|
plugin->write_buf_to_client = format_mp3_write_buf_to_client;
|
||||||
plugin->write_buf_to_file = write_mp3_to_file;
|
plugin->write_buf_to_file = write_mp3_to_file;
|
||||||
plugin->create_client_data = format_mp3_create_client_data;
|
plugin->create_client_data = format_mp3_create_client_data;
|
||||||
plugin->client_send_headers = format_mp3_send_headers;
|
|
||||||
plugin->free_plugin = format_mp3_free_plugin;
|
plugin->free_plugin = format_mp3_free_plugin;
|
||||||
plugin->set_tag = mp3_set_tag;
|
plugin->set_tag = mp3_set_tag;
|
||||||
plugin->apply_settings = format_mp3_apply_settings;
|
plugin->apply_settings = format_mp3_apply_settings;
|
||||||
@ -320,7 +317,7 @@ static int send_mp3_metadata (client_t *client, refbuf_t *associated)
|
|||||||
/* Handler for writing mp3 data to a client, taking into account whether
|
/* Handler for writing mp3 data to a client, taking into account whether
|
||||||
* client has requested shoutcast style metadata updates
|
* client has requested shoutcast style metadata updates
|
||||||
*/
|
*/
|
||||||
static int format_mp3_write_buf_to_client (format_plugin_t *self, client_t *client)
|
static int format_mp3_write_buf_to_client(client_t *client)
|
||||||
{
|
{
|
||||||
int ret, written = 0;
|
int ret, written = 0;
|
||||||
mp3_client_data *client_mp3 = client->format_data;
|
mp3_client_data *client_mp3 = client->format_data;
|
||||||
@ -573,12 +570,24 @@ static refbuf_t *mp3_get_filter_meta (source_t *source)
|
|||||||
static int format_mp3_create_client_data(source_t *source, client_t *client)
|
static int format_mp3_create_client_data(source_t *source, client_t *client)
|
||||||
{
|
{
|
||||||
mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data));
|
mp3_client_data *client_mp3 = calloc(1,sizeof(mp3_client_data));
|
||||||
char *metadata;
|
|
||||||
mp3_state *source_mp3 = source->format->_state;
|
mp3_state *source_mp3 = source->format->_state;
|
||||||
|
const char *metadata;
|
||||||
|
/* the +-2 is for overwriting the last set of \r\n */
|
||||||
|
unsigned remaining = 4096 - client->refbuf->len + 2;
|
||||||
|
char *ptr = client->refbuf->data + client->refbuf->len - 2;
|
||||||
|
int bytes;
|
||||||
|
|
||||||
if (client_mp3 == NULL)
|
if (client_mp3 == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* hack for flash player, it wants a length */
|
||||||
|
if (httpp_getvar(client->parser, "x-flash-version"))
|
||||||
|
{
|
||||||
|
bytes = snprintf (ptr, remaining, "Content-Length: 347122319\r\n");
|
||||||
|
remaining -= bytes;
|
||||||
|
ptr += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
client->format_data = client_mp3;
|
client->format_data = client_mp3;
|
||||||
client->free_client_data = free_mp3_client_data;
|
client->free_client_data = free_mp3_client_data;
|
||||||
metadata = httpp_getvar(client->parser, "icy-metadata");
|
metadata = httpp_getvar(client->parser, "icy-metadata");
|
||||||
@ -588,8 +597,19 @@ static int format_mp3_create_client_data(source_t *source, client_t *client)
|
|||||||
client_mp3->interval = source_mp3->interval;
|
client_mp3->interval = source_mp3->interval;
|
||||||
else
|
else
|
||||||
client_mp3->interval = ICY_METADATA_INTERVAL;
|
client_mp3->interval = ICY_METADATA_INTERVAL;
|
||||||
|
bytes = snprintf (ptr, remaining, "icy-metaint:%u\r\n",
|
||||||
|
client_mp3->interval);
|
||||||
|
if (bytes > 0)
|
||||||
|
{
|
||||||
|
remaining -= bytes;
|
||||||
|
ptr += bytes;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
bytes = snprintf (ptr, remaining, "\r\n");
|
||||||
|
remaining -= bytes;
|
||||||
|
ptr += bytes;
|
||||||
|
|
||||||
|
client->refbuf->len = 4096 - remaining;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -602,54 +622,6 @@ static void free_mp3_client_data (client_t *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void format_mp3_send_headers(format_plugin_t *self,
|
|
||||||
source_t *source, client_t *client)
|
|
||||||
{
|
|
||||||
int bytes;
|
|
||||||
char *content_length;
|
|
||||||
|
|
||||||
mp3_client_data *mp3data = client->format_data;
|
|
||||||
|
|
||||||
client->respcode = 200;
|
|
||||||
|
|
||||||
/* This little bit of code is for compatability with
|
|
||||||
flash mp3 streaming. Flash requires a content-length
|
|
||||||
in order for it to stream mp3s, and so based off a
|
|
||||||
trial and error effort, the following number was derived.
|
|
||||||
It is the largest content-length that we can send, anything
|
|
||||||
larger causes flash streaming not to work. Note that it
|
|
||||||
is also possible that other flash-based players may not
|
|
||||||
send this request header (x-flash-version), but given the
|
|
||||||
sampleset I had access to, this should suffice. */
|
|
||||||
if (httpp_getvar(client->parser, "x-flash-version")) {
|
|
||||||
content_length = "Content-Length: 347122319\r\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
content_length = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: This may need to be ICY/1.0 for shoutcast-compatibility? */
|
|
||||||
bytes = sock_write(client->con->sock,
|
|
||||||
"HTTP/1.0 200 OK\r\n"
|
|
||||||
"Content-Type: %s\r\n"
|
|
||||||
"%s",
|
|
||||||
source->format->contenttype,
|
|
||||||
content_length);
|
|
||||||
|
|
||||||
if (bytes > 0)
|
|
||||||
client->con->sent_bytes += bytes;
|
|
||||||
|
|
||||||
if (mp3data->interval)
|
|
||||||
{
|
|
||||||
int bytes = sock_write(client->con->sock, "icy-metaint:%d\r\n",
|
|
||||||
mp3data->interval);
|
|
||||||
if(bytes > 0)
|
|
||||||
client->con->sent_bytes += bytes;
|
|
||||||
}
|
|
||||||
format_send_general_headers(self, source, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf)
|
static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf)
|
||||||
{
|
{
|
||||||
if (refbuf->len == 0)
|
if (refbuf->len == 0)
|
||||||
|
@ -54,13 +54,11 @@ struct _ogg_state_tag;
|
|||||||
|
|
||||||
static void format_ogg_free_plugin (format_plugin_t *plugin);
|
static void format_ogg_free_plugin (format_plugin_t *plugin);
|
||||||
static int create_ogg_client_data(source_t *source, client_t *client);
|
static int create_ogg_client_data(source_t *source, client_t *client);
|
||||||
static void format_ogg_send_headers(format_plugin_t *self,
|
|
||||||
source_t *source, client_t *client);
|
|
||||||
static void free_ogg_client_data (client_t *client);
|
static void free_ogg_client_data (client_t *client);
|
||||||
|
|
||||||
static void write_ogg_to_file (struct source_tag *source, refbuf_t *refbuf);
|
static void write_ogg_to_file (struct source_tag *source, refbuf_t *refbuf);
|
||||||
static refbuf_t *ogg_get_buffer (source_t *source);
|
static refbuf_t *ogg_get_buffer (source_t *source);
|
||||||
static int write_buf_to_client (format_plugin_t *self, client_t *client);
|
static int write_buf_to_client (client_t *client);
|
||||||
|
|
||||||
|
|
||||||
struct ogg_client
|
struct ogg_client
|
||||||
@ -167,7 +165,6 @@ int format_ogg_get_plugin (source_t *source)
|
|||||||
plugin->write_buf_to_client = write_buf_to_client;
|
plugin->write_buf_to_client = write_buf_to_client;
|
||||||
plugin->write_buf_to_file = write_ogg_to_file;
|
plugin->write_buf_to_file = write_ogg_to_file;
|
||||||
plugin->create_client_data = create_ogg_client_data;
|
plugin->create_client_data = create_ogg_client_data;
|
||||||
plugin->client_send_headers = format_ogg_send_headers;
|
|
||||||
plugin->free_plugin = format_ogg_free_plugin;
|
plugin->free_plugin = format_ogg_free_plugin;
|
||||||
plugin->set_tag = NULL;
|
plugin->set_tag = NULL;
|
||||||
plugin->contenttype = "application/ogg";
|
plugin->contenttype = "application/ogg";
|
||||||
@ -501,7 +498,7 @@ static int send_ogg_headers (client_t *client, refbuf_t *headers)
|
|||||||
/* main client write routine for sending ogg data. Each refbuf has a
|
/* main client write routine for sending ogg data. Each refbuf has a
|
||||||
* single page so we only need to determine if there are new headers
|
* single page so we only need to determine if there are new headers
|
||||||
*/
|
*/
|
||||||
static int write_buf_to_client (format_plugin_t *self, client_t *client)
|
static int write_buf_to_client (client_t *client)
|
||||||
{
|
{
|
||||||
refbuf_t *refbuf = client->refbuf;
|
refbuf_t *refbuf = client->refbuf;
|
||||||
char *buf = refbuf->data + client->pos;
|
char *buf = refbuf->data + client->pos;
|
||||||
@ -570,19 +567,3 @@ static void write_ogg_to_file (struct source_tag *source, refbuf_t *refbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void format_ogg_send_headers(format_plugin_t *self,
|
|
||||||
source_t *source, client_t *client)
|
|
||||||
{
|
|
||||||
int bytes;
|
|
||||||
|
|
||||||
client->respcode = 200;
|
|
||||||
bytes = sock_write(client->con->sock,
|
|
||||||
"HTTP/1.0 200 OK\r\n"
|
|
||||||
"Content-Type: %s\r\n",
|
|
||||||
source->format->contenttype);
|
|
||||||
|
|
||||||
if(bytes > 0) client->con->sent_bytes += bytes;
|
|
||||||
|
|
||||||
format_send_general_headers(self, source, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -475,7 +475,7 @@ static void send_to_listener (source_t *source, client_t *client, int deletion_e
|
|||||||
if (client->check_buffer (source, client) < 0)
|
if (client->check_buffer (source, client) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
bytes = source->format->write_buf_to_client (source->format, client);
|
bytes = client->write_to_client (client);
|
||||||
if (bytes <= 0)
|
if (bytes <= 0)
|
||||||
break; /* can't write any more */
|
break; /* can't write any more */
|
||||||
|
|
||||||
@ -790,6 +790,10 @@ static int _free_client(void *key)
|
|||||||
{
|
{
|
||||||
client_t *client = (client_t *)key;
|
client_t *client = (client_t *)key;
|
||||||
|
|
||||||
|
/* if no response has been sent then send a 404 */
|
||||||
|
if (client->respcode == 0)
|
||||||
|
client_send_404 (client, "Mount unavailable");
|
||||||
|
else
|
||||||
client_destroy(client);
|
client_destroy(client);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user