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 &&
|
else if(config_get_config()->fileserve &&
|
||||||
stat(fullpath, &statbuf) == 0) {
|
stat(fullpath, &statbuf) == 0) {
|
||||||
client->respcode = 200;
|
fserve_client_create(client, fullpath);
|
||||||
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);
|
|
||||||
free(fullpath);
|
free(fullpath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
94
src/fserve.c
94
src/fserve.c
@ -2,6 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -41,6 +42,11 @@ static avl_tree *pending_tree;
|
|||||||
static cond_t fserv_cond;
|
static cond_t fserv_cond;
|
||||||
static thread_t *fserv_thread;
|
static thread_t *fserv_thread;
|
||||||
static int run_fserv;
|
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 */
|
/* avl tree helper */
|
||||||
static int _compare_clients(void *compare_arg, void *a, void *b);
|
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);
|
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)
|
void *fserv_thread_function(void *arg)
|
||||||
{
|
{
|
||||||
avl_node *client_node, *pending_node;
|
avl_node *client_node, *pending_node;
|
||||||
@ -88,15 +130,25 @@ void *fserv_thread_function(void *arg)
|
|||||||
|
|
||||||
client_node = avl_get_first(client_tree);
|
client_node = avl_get_first(client_tree);
|
||||||
if(!client_node) {
|
if(!client_node) {
|
||||||
|
avl_tree_rlock(pending_tree);
|
||||||
pending_node = avl_get_first(pending_tree);
|
pending_node = avl_get_first(pending_tree);
|
||||||
if(!pending_node) {
|
if(!pending_node) {
|
||||||
/* There are no current clients. Wait until there are... */
|
/* There are no current clients. Wait until there are... */
|
||||||
|
avl_tree_unlock(pending_tree);
|
||||||
avl_tree_unlock(client_tree);
|
avl_tree_unlock(client_tree);
|
||||||
thread_cond_wait(&fserv_cond);
|
thread_cond_wait(&fserv_cond);
|
||||||
continue;
|
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) {
|
while(client_node) {
|
||||||
avl_node_wlock(client_node);
|
avl_node_wlock(client_node);
|
||||||
|
|
||||||
@ -145,8 +197,10 @@ void *fserv_thread_function(void *arg)
|
|||||||
while(client_node) {
|
while(client_node) {
|
||||||
client = (fserve_t *)client_node->key;
|
client = (fserve_t *)client_node->key;
|
||||||
if(client->client->con->error) {
|
if(client->client->con->error) {
|
||||||
|
fserve_clients--;
|
||||||
client_node = avl_get_next(client_node);
|
client_node = avl_get_next(client_node);
|
||||||
avl_delete(client_tree, (void *)client, _free_client);
|
avl_delete(client_tree, (void *)client, _free_client);
|
||||||
|
client_tree_changed = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
client_node = avl_get_next(client_node);
|
client_node = avl_get_next(client_node);
|
||||||
@ -159,6 +213,9 @@ void *fserv_thread_function(void *arg)
|
|||||||
while(client_node) {
|
while(client_node) {
|
||||||
client = (fserve_t *)client_node->key;
|
client = (fserve_t *)client_node->key;
|
||||||
avl_insert(client_tree, client);
|
avl_insert(client_tree, client);
|
||||||
|
client_tree_changed = 1;
|
||||||
|
fserve_clients++;
|
||||||
|
stats_event_inc(NULL, "clients");
|
||||||
client_node = avl_get_next(client_node);
|
client_node = avl_get_next(client_node);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -191,7 +248,7 @@ void *fserv_thread_function(void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *fserve_content_type(char *path)
|
static char *fserve_content_type(char *path)
|
||||||
{
|
{
|
||||||
char *ext = util_get_extension(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)
|
int fserve_client_create(client_t *httpclient, char *path)
|
||||||
{
|
{
|
||||||
fserve_t *client = calloc(1, sizeof(fserve_t));
|
fserve_t *client = calloc(1, sizeof(fserve_t));
|
||||||
|
int bytes;
|
||||||
|
|
||||||
client->client = httpclient;
|
|
||||||
client->file = fopen(path, "rb");
|
client->file = fopen(path, "rb");
|
||||||
if(!client->file) {
|
if(!client->file) {
|
||||||
fserve_client_destroy(client);
|
client_send_404(httpclient, "File not readable");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client->client = httpclient;
|
||||||
client->offset = 0;
|
client->offset = 0;
|
||||||
client->datasize = 0;
|
client->datasize = 0;
|
||||||
client->buf = malloc(BUFSIZE);
|
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_tree_wlock(pending_tree);
|
||||||
avl_insert(pending_tree, client);
|
avl_insert(pending_tree, client);
|
||||||
avl_tree_unlock(pending_tree);
|
avl_tree_unlock(pending_tree);
|
||||||
@ -266,6 +349,11 @@ static int _free_client(void *key)
|
|||||||
fserve_t *client = (fserve_t *)key;
|
fserve_t *client = (fserve_t *)key;
|
||||||
|
|
||||||
fserve_client_destroy(client);
|
fserve_client_destroy(client);
|
||||||
|
global_lock();
|
||||||
|
global.clients--;
|
||||||
|
global_unlock();
|
||||||
|
stats_event_dec(NULL, "clients");
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ typedef struct
|
|||||||
|
|
||||||
void fserve_initialize(void);
|
void fserve_initialize(void);
|
||||||
void fserve_shutdown(void);
|
void fserve_shutdown(void);
|
||||||
char *fserve_content_type(char *path);
|
|
||||||
int fserve_client_create(client_t *httpclient, 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");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _stop_logging(void)
|
||||||
|
{
|
||||||
|
log_close(errorlog);
|
||||||
|
log_close(accesslog);
|
||||||
|
}
|
||||||
|
|
||||||
static void _initialize_subsystems(void)
|
static void _initialize_subsystems(void)
|
||||||
{
|
{
|
||||||
log_initialize();
|
log_initialize();
|
||||||
@ -54,7 +60,6 @@ static void _initialize_subsystems(void)
|
|||||||
global_initialize();
|
global_initialize();
|
||||||
refbuf_initialize();
|
refbuf_initialize();
|
||||||
xslt_initialize();
|
xslt_initialize();
|
||||||
DEBUG0("Calling fserve_initialize()");
|
|
||||||
fserve_initialize();
|
fserve_initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +70,10 @@ static void _shutdown_subsystems(void)
|
|||||||
refbuf_shutdown();
|
refbuf_shutdown();
|
||||||
stats_shutdown();
|
stats_shutdown();
|
||||||
slave_shutdown();
|
slave_shutdown();
|
||||||
|
|
||||||
|
/* Now that these are done, we can stop the loggers. */
|
||||||
|
_stop_logging();
|
||||||
|
|
||||||
global_shutdown();
|
global_shutdown();
|
||||||
connection_shutdown();
|
connection_shutdown();
|
||||||
config_shutdown();
|
config_shutdown();
|
||||||
@ -127,12 +136,6 @@ static int _start_logging(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _stop_logging(void)
|
|
||||||
{
|
|
||||||
log_close(errorlog);
|
|
||||||
log_close(accesslog);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _setup_socket(void)
|
static int _setup_socket(void)
|
||||||
{
|
{
|
||||||
ice_config_t *config;
|
ice_config_t *config;
|
||||||
@ -345,8 +348,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
INFO0("Shutting down");
|
INFO0("Shutting down");
|
||||||
|
|
||||||
_stop_logging();
|
|
||||||
|
|
||||||
_shutdown_subsystems();
|
_shutdown_subsystems();
|
||||||
|
|
||||||
return 0;
|
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','+','/'
|
'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 */
|
/* This isn't efficient, but it doesn't need to be */
|
||||||
char *util_base64_encode(char *data)
|
char *util_base64_encode(char *data)
|
||||||
{
|
{
|
||||||
@ -309,25 +328,7 @@ char *util_base64_encode(char *data)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int base64chartoval(char input)
|
char *util_base64_decode(unsigned 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)
|
|
||||||
{
|
{
|
||||||
int len = strlen(input);
|
int len = strlen(input);
|
||||||
char *out = malloc(len*3/4 + 5);
|
char *out = malloc(len*3/4 + 5);
|
||||||
@ -341,10 +342,10 @@ char *util_base64_decode(char *input)
|
|||||||
return NULL; /* Invalid Base64 data */
|
return NULL; /* Invalid Base64 data */
|
||||||
}
|
}
|
||||||
|
|
||||||
vals[0] = base64chartoval(*input++);
|
vals[0] = base64decode[*input++];
|
||||||
vals[1] = base64chartoval(*input++);
|
vals[1] = base64decode[*input++];
|
||||||
vals[2] = base64chartoval(*input++);
|
vals[2] = base64decode[*input++];
|
||||||
vals[3] = base64chartoval(*input++);
|
vals[3] = base64decode[*input++];
|
||||||
|
|
||||||
if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1) {
|
if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -12,6 +12,6 @@ char *util_get_path_from_uri(char *uri);
|
|||||||
char *util_get_path_from_normalised_uri(char *uri);
|
char *util_get_path_from_normalised_uri(char *uri);
|
||||||
char *util_normalise_uri(char *uri);
|
char *util_normalise_uri(char *uri);
|
||||||
char *util_base64_encode(char *data);
|
char *util_base64_encode(char *data);
|
||||||
char *util_base64_decode(char *input);
|
char *util_base64_decode(unsigned char *input);
|
||||||
|
|
||||||
#endif /* __UTIL_H__ */
|
#endif /* __UTIL_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user