1
0
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:
Karl Heyes 2005-06-11 17:21:00 +00:00
parent 29c83ae4eb
commit c59a276ab5
2 changed files with 52 additions and 51 deletions

View File

@ -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))
{ {

View File

@ -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;