mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Fileserving that might actually work for > 1 user.
cleanups for the base64 decoder. svn path=/trunk/icecast/; revision=3856
This commit is contained in:
parent
b048ecc171
commit
3c59c90e36
@ -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;
|
||||
}
|
||||
|
94
src/fserve.c
94
src/fserve.c
@ -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);
|
||||
|
||||
|
||||
|
19
src/main.c
19
src/main.c
@ -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;
|
||||
|
47
src/util.c
47
src/util.c
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user