Commit 3c59c90e authored by Michael Smith's avatar Michael Smith

Fileserving that might actually work for > 1 user.

cleanups for the base64 decoder.

svn path=/trunk/icecast/; revision=3856
parent b048ecc1
......@@ -533,13 +533,7 @@ static void _handle_get_request(connection_t *con,
}
else if(config_get_config()->fileserve &&
stat(fullpath, &statbuf) == 0) {
client->respcode = 200;
bytes = sock_write(client->con->sock,
"HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n",
fserve_content_type(fullpath));
if(bytes > 0) client->con->sent_bytes = bytes;
if(fserve_client_create(client, fullpath) < 0)
client_destroy(client);
fserve_client_create(client, fullpath);
free(fullpath);
return;
}
......
......@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/poll.h>
#ifndef _WIN32
#include <unistd.h>
......@@ -41,6 +42,11 @@ static avl_tree *pending_tree;
static cond_t fserv_cond;
static thread_t *fserv_thread;
static int run_fserv;
static int fserve_clients;
static int client_tree_changed=0;
static struct pollfd *ufds = NULL;
static int ufdssize = 0;
/* avl tree helper */
static int _compare_clients(void *compare_arg, void *a, void *b);
......@@ -77,6 +83,42 @@ void fserve_shutdown(void)
avl_tree_free(pending_tree, _free_client);
}
static void wait_for_fds() {
avl_node *client_node;
fserve_t *client;
int i;
while(run_fserv) {
if(client_tree_changed) {
client_tree_changed = 0;
i = 0;
ufdssize = fserve_clients;
ufds = realloc(ufds, ufdssize * sizeof(struct pollfd));
avl_tree_rlock(client_tree);
client_node = avl_get_first(client_tree);
while(client_node) {
client = client_node->key;
ufds[i].fd = client->client->con->sock;
ufds[i].events = POLLOUT;
client_node = avl_get_next(client_node);
}
avl_tree_unlock(client_tree);
}
if(poll(ufds, ufdssize, 200) > 0) {
return;
}
else {
avl_tree_rlock(pending_tree);
client_node = avl_get_first(pending_tree);
avl_tree_unlock(pending_tree);
if(client_node)
return;
}
}
}
void *fserv_thread_function(void *arg)
{
avl_node *client_node, *pending_node;
......@@ -88,15 +130,25 @@ void *fserv_thread_function(void *arg)
client_node = avl_get_first(client_tree);
if(!client_node) {
avl_tree_rlock(pending_tree);
pending_node = avl_get_first(pending_tree);
if(!pending_node) {
/* There are no current clients. Wait until there are... */
avl_tree_unlock(pending_tree);
avl_tree_unlock(client_tree);
thread_cond_wait(&fserv_cond);
continue;
}
avl_tree_unlock(pending_tree);
}
/* This isn't hugely efficient, but it'll do for now */
avl_tree_unlock(client_tree);
wait_for_fds();
avl_tree_rlock(client_tree);
client_node = avl_get_first(client_tree);
while(client_node) {
avl_node_wlock(client_node);
......@@ -145,8 +197,10 @@ void *fserv_thread_function(void *arg)
while(client_node) {
client = (fserve_t *)client_node->key;
if(client->client->con->error) {
fserve_clients--;
client_node = avl_get_next(client_node);
avl_delete(client_tree, (void *)client, _free_client);
client_tree_changed = 1;
continue;
}
client_node = avl_get_next(client_node);
......@@ -159,6 +213,9 @@ void *fserv_thread_function(void *arg)
while(client_node) {
client = (fserve_t *)client_node->key;
avl_insert(client_tree, client);
client_tree_changed = 1;
fserve_clients++;
stats_event_inc(NULL, "clients");
client_node = avl_get_next(client_node);
}
......@@ -191,7 +248,7 @@ void *fserv_thread_function(void *arg)
return NULL;
}
char *fserve_content_type(char *path)
static char *fserve_content_type(char *path)
{
char *ext = util_get_extension(path);
......@@ -225,17 +282,43 @@ static void fserve_client_destroy(fserve_t *client)
int fserve_client_create(client_t *httpclient, char *path)
{
fserve_t *client = calloc(1, sizeof(fserve_t));
int bytes;
client->client = httpclient;
client->file = fopen(path, "rb");
if(!client->file) {
fserve_client_destroy(client);
client_send_404(httpclient, "File not readable");
return -1;
}
client->client = httpclient;
client->offset = 0;
client->datasize = 0;
client->buf = malloc(BUFSIZE);
global_lock();
if(global.clients >= config_get_config()->client_limit) {
httpclient->respcode = 504;
bytes = sock_write(httpclient->con->sock,
"HTTP/1.0 504 Server Full\r\n"
"Content-Type: text/html\r\n\r\n"
"<b>Server is full, try again later.</b>\r\n");
if(bytes > 0) httpclient->con->sent_bytes = bytes;
fserve_client_destroy(client);
global_unlock();
return -1;
}
global.clients++;
global_unlock();
httpclient->respcode = 200;
bytes = sock_write(httpclient->con->sock,
"HTTP/1.0 200 OK\r\n"
"Content-Type: %s\r\n\r\n",
fserve_content_type(path));
if(bytes > 0) httpclient->con->sent_bytes = bytes;
sock_set_blocking(client->client->con->sock, SOCK_NONBLOCK);
avl_tree_wlock(pending_tree);
avl_insert(pending_tree, client);
avl_tree_unlock(pending_tree);
......@@ -266,6 +349,11 @@ static int _free_client(void *key)
fserve_t *client = (fserve_t *)key;
fserve_client_destroy(client);
global_lock();
global.clients--;
global_unlock();
stats_event_dec(NULL, "clients");
return 1;
}
......
......@@ -15,7 +15,6 @@ typedef struct
void fserve_initialize(void);
void fserve_shutdown(void);
char *fserve_content_type(char *path);
int fserve_client_create(client_t *httpclient, char *path);
......
......@@ -43,6 +43,12 @@ static void _print_usage()
printf("\n");
}
static void _stop_logging(void)
{
log_close(errorlog);
log_close(accesslog);
}
static void _initialize_subsystems(void)
{
log_initialize();
......@@ -54,7 +60,6 @@ static void _initialize_subsystems(void)
global_initialize();
refbuf_initialize();
xslt_initialize();
DEBUG0("Calling fserve_initialize()");
fserve_initialize();
}
......@@ -65,6 +70,10 @@ static void _shutdown_subsystems(void)
refbuf_shutdown();
stats_shutdown();
slave_shutdown();
/* Now that these are done, we can stop the loggers. */
_stop_logging();
global_shutdown();
connection_shutdown();
config_shutdown();
......@@ -127,12 +136,6 @@ static int _start_logging(void)
return 0;
}
static void _stop_logging(void)
{
log_close(errorlog);
log_close(accesslog);
}
static int _setup_socket(void)
{
ice_config_t *config;
......@@ -345,8 +348,6 @@ int main(int argc, char **argv)
INFO0("Shutting down");
_stop_logging();
_shutdown_subsystems();
return 0;
......
......@@ -275,6 +275,25 @@ static char base64table[64] = {
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
static signed char base64decode[256] = {
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -1, -2, -2,
-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
-2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
};
/* This isn't efficient, but it doesn't need to be */
char *util_base64_encode(char *data)
{
......@@ -309,25 +328,7 @@ char *util_base64_encode(char *data)
return result;
}
static int base64chartoval(char input)
{
if(input >= 'A' && input <= 'Z')
return input - 'A';
else if(input >= 'a' && input <= 'z')
return input - 'a' + 26;
else if(input >= '0' && input <= '9')
return input - '0' + 52;
else if(input == '+')
return 62;
else if(input == '/')
return 63;
else if(input == '=')
return -1;
else
return -2;
}
char *util_base64_decode(char *input)
char *util_base64_decode(unsigned char *input)
{
int len = strlen(input);
char *out = malloc(len*3/4 + 5);
......@@ -341,10 +342,10 @@ char *util_base64_decode(char *input)
return NULL; /* Invalid Base64 data */
}
vals[0] = base64chartoval(*input++);
vals[1] = base64chartoval(*input++);
vals[2] = base64chartoval(*input++);
vals[3] = base64chartoval(*input++);
vals[0] = base64decode[*input++];
vals[1] = base64decode[*input++];
vals[2] = base64decode[*input++];
vals[3] = base64decode[*input++];
if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1) {
continue;
......
......@@ -12,6 +12,6 @@ char *util_get_path_from_uri(char *uri);
char *util_get_path_from_normalised_uri(char *uri);
char *util_normalise_uri(char *uri);
char *util_base64_encode(char *data);
char *util_base64_decode(char *input);
char *util_base64_decode(unsigned char *input);
#endif /* __UTIL_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment