mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
update file serving setup and processing. Do http header writing in fserve
thread by using generic write routine. small leak plugged on failure case. extend mime type handling slightly for rare case svn path=/icecast/trunk/icecast/; revision=9440
This commit is contained in:
parent
29c83ae4eb
commit
c59a276ab5
94
src/fserve.c
94
src/fserve.c
@ -31,6 +31,7 @@
|
|||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "thread/thread.h"
|
#include "thread/thread.h"
|
||||||
@ -252,10 +253,13 @@ static void *fserv_thread_function(void *arg)
|
|||||||
/* process this client, if it is ready */
|
/* process this client, if it is ready */
|
||||||
if (fclient->ready)
|
if (fclient->ready)
|
||||||
{
|
{
|
||||||
|
client_t *client = fclient->client;
|
||||||
|
refbuf_t *refbuf = client->refbuf;
|
||||||
fclient->ready = 0;
|
fclient->ready = 0;
|
||||||
if(fclient->offset >= fclient->datasize) {
|
if (client->pos == refbuf->len)
|
||||||
|
{
|
||||||
/* Grab a new chunk */
|
/* Grab a new chunk */
|
||||||
bytes = fread(fclient->buf, 1, BUFSIZE, fclient->file);
|
bytes = fread (refbuf->data, 1, BUFSIZE, fclient->file);
|
||||||
if (bytes == 0)
|
if (bytes == 0)
|
||||||
{
|
{
|
||||||
fserve_t *to_go = fclient;
|
fserve_t *to_go = fclient;
|
||||||
@ -266,21 +270,14 @@ static void *fserv_thread_function(void *arg)
|
|||||||
client_tree_changed = 1;
|
client_tree_changed = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fclient->offset = 0;
|
refbuf->len = bytes;
|
||||||
fclient->datasize = bytes;
|
client->pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now try and send current chunk. */
|
/* Now try and send current chunk. */
|
||||||
sbytes = client_send_bytes (fclient->client,
|
sbytes = format_generic_write_to_client (client);
|
||||||
&fclient->buf[fclient->offset],
|
|
||||||
fclient->datasize - fclient->offset);
|
|
||||||
|
|
||||||
/* TODO: remove clients if they take too long. */
|
if (client->con->error)
|
||||||
if(sbytes > 0) {
|
|
||||||
fclient->offset += sbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fclient->client->con->error)
|
|
||||||
{
|
{
|
||||||
fserve_t *to_go = fclient;
|
fserve_t *to_go = fclient;
|
||||||
fclient = fclient->next;
|
fclient = fclient->next;
|
||||||
@ -340,32 +337,33 @@ char *fserve_content_type (const char *path)
|
|||||||
return "text/css";
|
return "text/css";
|
||||||
else if(!strcmp(ext, "txt"))
|
else if(!strcmp(ext, "txt"))
|
||||||
return "text/plain";
|
return "text/plain";
|
||||||
|
else if(!strcmp(ext, "jpg"))
|
||||||
|
return "image/jpeg";
|
||||||
|
else if(!strcmp(ext, "png"))
|
||||||
|
return "image/png";
|
||||||
else
|
else
|
||||||
return "application/octet-stream";
|
return "application/octet-stream";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fserve_client_destroy(fserve_t *client)
|
static void fserve_client_destroy(fserve_t *fclient)
|
||||||
{
|
{
|
||||||
if(client) {
|
if (fclient)
|
||||||
if(client->buf)
|
{
|
||||||
free(client->buf);
|
if (fclient->file)
|
||||||
if(client->file)
|
fclose (fclient->file);
|
||||||
fclose(client->file);
|
|
||||||
|
|
||||||
if(client->client)
|
if (fclient->client)
|
||||||
client_destroy(client->client);
|
client_destroy (fclient->client);
|
||||||
free(client);
|
free (fclient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int fserve_client_create(client_t *httpclient, const char *path)
|
int fserve_client_create(client_t *httpclient, const char *path)
|
||||||
{
|
{
|
||||||
fserve_t *client = calloc(1, sizeof(fserve_t));
|
fserve_t *client;
|
||||||
int bytes;
|
int bytes;
|
||||||
int client_limit;
|
|
||||||
ice_config_t *config = config_get_config();
|
|
||||||
struct stat file_buf;
|
struct stat file_buf;
|
||||||
char *range = NULL;
|
char *range = NULL;
|
||||||
int64_t new_content_len = 0;
|
int64_t new_content_len = 0;
|
||||||
@ -373,24 +371,31 @@ int fserve_client_create(client_t *httpclient, const char *path)
|
|||||||
int rangeproblem = 0;
|
int rangeproblem = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
client_limit = config->client_limit;
|
if (stat (path, &file_buf) != 0)
|
||||||
config_release_config();
|
{
|
||||||
|
client_send_404 (httpclient, "The file you requested could not be found");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = calloc (1, sizeof(fserve_t));
|
||||||
|
if (client == NULL)
|
||||||
|
{
|
||||||
|
client_send_404 (httpclient, "memory exhausted");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
client->file = fopen (path, "rb");
|
client->file = fopen (path, "rb");
|
||||||
if(!client->file) {
|
if (client->file == NULL)
|
||||||
|
{
|
||||||
client_send_404 (httpclient, "File not readable");
|
client_send_404 (httpclient, "File not readable");
|
||||||
return -1;
|
fserve_client_destroy (client);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->client = httpclient;
|
client->client = httpclient;
|
||||||
client->offset = 0;
|
|
||||||
client->datasize = 0;
|
|
||||||
client->ready = 0;
|
client->ready = 0;
|
||||||
client->content_length = 0;
|
client_set_queue (httpclient, NULL);
|
||||||
client->buf = malloc(BUFSIZE);
|
httpclient->refbuf = refbuf_new (BUFSIZE);
|
||||||
if (stat(path, &file_buf) == 0) {
|
|
||||||
client->content_length = (int64_t)file_buf.st_size;
|
client->content_length = (int64_t)file_buf.st_size;
|
||||||
}
|
|
||||||
|
|
||||||
range = httpp_getvar (client->client->parser, "range");
|
range = httpp_getvar (client->client->parser, "range");
|
||||||
|
|
||||||
@ -429,7 +434,7 @@ int fserve_client_create(client_t *httpclient, const char *path)
|
|||||||
strflen = strftime(currenttime, 50, "%a, %d-%b-%Y %X GMT",
|
strflen = strftime(currenttime, 50, "%a, %d-%b-%Y %X GMT",
|
||||||
gmtime_r(&now, &result));
|
gmtime_r(&now, &result));
|
||||||
httpclient->respcode = 206;
|
httpclient->respcode = 206;
|
||||||
bytes = sock_write(httpclient->con->sock,
|
bytes = snprintf (httpclient->refbuf->data, BUFSIZE,
|
||||||
"HTTP/1.1 206 Partial Content\r\n"
|
"HTTP/1.1 206 Partial Content\r\n"
|
||||||
"Date: %s\r\n"
|
"Date: %s\r\n"
|
||||||
"Content-Length: " FORMAT_INT64 "\r\n"
|
"Content-Length: " FORMAT_INT64 "\r\n"
|
||||||
@ -442,13 +447,11 @@ int fserve_client_create(client_t *httpclient, const char *path)
|
|||||||
endpos,
|
endpos,
|
||||||
client->content_length,
|
client->content_length,
|
||||||
fserve_content_type(path));
|
fserve_content_type(path));
|
||||||
if(bytes > 0) httpclient->con->sent_bytes = bytes;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
httpclient->respcode = 416;
|
httpclient->respcode = 416;
|
||||||
bytes = sock_write(httpclient->con->sock,
|
bytes = snprintf (httpclient->refbuf->data, BUFSIZE,
|
||||||
"HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n");
|
"HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n");
|
||||||
if(bytes > 0) httpclient->con->sent_bytes = bytes;
|
|
||||||
fserve_client_destroy(client);
|
fserve_client_destroy(client);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -457,9 +460,8 @@ int fserve_client_create(client_t *httpclient, const char *path)
|
|||||||
/* If we run into any issues with the ranges
|
/* If we run into any issues with the ranges
|
||||||
we fallback to a normal/non-range request */
|
we fallback to a normal/non-range request */
|
||||||
httpclient->respcode = 416;
|
httpclient->respcode = 416;
|
||||||
bytes = sock_write(httpclient->con->sock,
|
bytes = snprintf (httpclient->refbuf->data, BUFSIZE,
|
||||||
"HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n");
|
"HTTP/1.0 416 Request Range Not Satisfiable\r\n\r\n");
|
||||||
if(bytes > 0) httpclient->con->sent_bytes = bytes;
|
|
||||||
fserve_client_destroy(client);
|
fserve_client_destroy(client);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -467,15 +469,14 @@ int fserve_client_create(client_t *httpclient, const char *path)
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
httpclient->respcode = 200;
|
httpclient->respcode = 200;
|
||||||
bytes = sock_write(httpclient->con->sock,
|
bytes = snprintf (httpclient->refbuf->data, BUFSIZE,
|
||||||
"HTTP/1.0 200 OK\r\n"
|
"HTTP/1.0 200 OK\r\n"
|
||||||
"Content-Length: " FORMAT_INT64 "\r\n"
|
"Content-Length: " FORMAT_INT64 "\r\n"
|
||||||
"Content-Type: %s\r\n\r\n",
|
"Content-Type: %s\r\n\r\n",
|
||||||
client->content_length,
|
client->content_length,
|
||||||
fserve_content_type(path));
|
fserve_content_type(path));
|
||||||
if(bytes > 0) httpclient->con->sent_bytes = bytes;
|
|
||||||
}
|
}
|
||||||
|
httpclient->refbuf->len = bytes;
|
||||||
stats_event_inc (NULL, "file_connections");
|
stats_event_inc (NULL, "file_connections");
|
||||||
sock_set_blocking(client->client->con->sock, SOCK_NONBLOCK);
|
sock_set_blocking(client->client->con->sock, SOCK_NONBLOCK);
|
||||||
sock_set_nodelay(client->client->con->sock);
|
sock_set_nodelay(client->client->con->sock);
|
||||||
@ -513,8 +514,11 @@ static void create_mime_mappings(const char *fn) {
|
|||||||
|
|
||||||
mimetypes = avl_tree_new(_compare_mappings, NULL);
|
mimetypes = avl_tree_new(_compare_mappings, NULL);
|
||||||
|
|
||||||
if(!mimefile)
|
if (mimefile == NULL)
|
||||||
|
{
|
||||||
|
WARN1 ("Cannot open mime type file %s", fn);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while(fgets(line, 4096, mimefile))
|
while(fgets(line, 4096, mimefile))
|
||||||
{
|
{
|
||||||
|
@ -21,11 +21,8 @@ typedef struct _fserve_t
|
|||||||
client_t *client;
|
client_t *client;
|
||||||
|
|
||||||
FILE *file;
|
FILE *file;
|
||||||
int offset;
|
|
||||||
int64_t content_length;
|
int64_t content_length;
|
||||||
int datasize;
|
|
||||||
int ready;
|
int ready;
|
||||||
unsigned char *buf;
|
|
||||||
struct _fserve_t *next;
|
struct _fserve_t *next;
|
||||||
} fserve_t;
|
} fserve_t;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user