Commit dde143d4 authored by Karl Heyes's avatar Karl Heyes

make various responses going back to the client be done via the file serving thread

svn path=/icecast/trunk/icecast/; revision=9740
parent 61267a30
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "refbuf.h" #include "refbuf.h"
#include "format.h" #include "format.h"
#include "stats.h" #include "stats.h"
#include "fserve.h"
#include "client.h" #include "client.h"
#include "logging.h" #include "logging.h"
...@@ -143,46 +144,36 @@ int client_read_bytes (client_t *client, void *buf, unsigned len) ...@@ -143,46 +144,36 @@ int client_read_bytes (client_t *client, void *buf, unsigned len)
void client_send_400(client_t *client, char *message) { void client_send_400(client_t *client, char *message) {
int bytes; snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
bytes = sock_write(client->con->sock, "HTTP/1.0 400 Bad Request\r\n" "HTTP/1.0 400 Bad Request\r\n"
"Content-Type: text/html\r\n\r\n" "Content-Type: text/html\r\n\r\n"
"<b>%s</b>\r\n", message); "<b>%s</b>\r\n", message);
if(bytes > 0) client->con->sent_bytes = bytes;
client->respcode = 400; client->respcode = 400;
client_destroy(client); client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
} }
void client_send_404(client_t *client, char *message) { void client_send_404(client_t *client, char *message) {
int bytes; snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
bytes = sock_write(client->con->sock, "HTTP/1.0 404 File Not Found\r\n" "HTTP/1.0 404 File Not Found\r\n"
"Content-Type: text/html\r\n\r\n" "Content-Type: text/html\r\n\r\n"
"<b>%s</b>\r\n", message); "<b>%s</b>\r\n", message);
if(bytes > 0) client->con->sent_bytes = bytes;
client->respcode = 404; client->respcode = 404;
client_destroy(client); client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
} }
void client_send_504(client_t *client, char *message) {
int bytes;
client->respcode = 504;
bytes = sock_write(client->con->sock,
"HTTP/1.0 504 Server Full\r\n"
"Content-Type: text/html\r\n\r\n"
"<b>%s</b>\r\n", message);
if (bytes > 0) client->con->sent_bytes = bytes;
client_destroy(client);
}
void client_send_401(client_t *client) { void client_send_401(client_t *client) {
int bytes = sock_write(client->con->sock, snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
"HTTP/1.0 401 Authentication Required\r\n" "HTTP/1.0 401 Authentication Required\r\n"
"WWW-Authenticate: Basic realm=\"Icecast2 Server\"\r\n" "WWW-Authenticate: Basic realm=\"Icecast2 Server\"\r\n"
"\r\n" "\r\n"
"You need to authenticate\r\n"); "You need to authenticate\r\n");
if(bytes > 0) client->con->sent_bytes = bytes;
client->respcode = 401; client->respcode = 401;
client_destroy(client); client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client (client, NULL);
} }
void client_send_403(client_t *client) { void client_send_403(client_t *client) {
......
...@@ -764,8 +764,13 @@ static void _handle_source_request (client_t *client, char *uri, int auth_style) ...@@ -764,8 +764,13 @@ static void _handle_source_request (client_t *client, char *uri, int auth_style)
source_free_source (source); source_free_source (source);
} }
else else
thread_create ("Source Thread", source_client_thread, {
source, THREAD_DETACHED); client->respcode = 200;
snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
"HTTP/1.0 200 OK\r\n\r\n");
client->refbuf->len = strlen (client->refbuf->data);
fserve_add_client_callback (client, source_client_callback, source);
}
} }
else else
{ {
...@@ -787,14 +792,10 @@ static void _handle_stats_request (client_t *client, char *uri) ...@@ -787,14 +792,10 @@ static void _handle_stats_request (client_t *client, char *uri)
} }
client->respcode = 200; client->respcode = 200;
if (sock_write (client->con->sock, "HTTP/1.0 200 OK\r\n\r\n") < 19) snprintf (client->refbuf->data, PER_CLIENT_REFBUF_SIZE,
{ "HTTP/1.0 200 OK\r\n\r\n");
client_destroy (client); client->refbuf->len = strlen (client->refbuf->data);
ERROR0 ("failed to write header"); fserve_add_client_callback (client, stats_callback, NULL);
return;
}
thread_create("Stats Connection", stats_connection, (void *)client, THREAD_DETACHED);
} }
static void _handle_get_request (client_t *client, char *passed_uri) static void _handle_get_request (client_t *client, char *passed_uri)
......
...@@ -352,8 +352,11 @@ static void fserve_client_destroy(fserve_t *fclient) ...@@ -352,8 +352,11 @@ static void fserve_client_destroy(fserve_t *fclient)
if (fclient->file) if (fclient->file)
fclose (fclient->file); fclose (fclient->file);
if (fclient->client) if (fclient->callback)
client_destroy (fclient->client); fclient->callback (fclient->client, fclient->arg);
else
if (fclient->client)
client_destroy (fclient->client);
free (fclient); free (fclient);
} }
} }
...@@ -396,8 +399,7 @@ int fserve_client_create (client_t *httpclient, const char *path) ...@@ -396,8 +399,7 @@ int fserve_client_create (client_t *httpclient, const char *path)
m3u_file_available = 0; m3u_file_available = 0;
} }
client_set_queue (httpclient, NULL); httpclient->refbuf->len = PER_CLIENT_REFBUF_SIZE;
httpclient->refbuf = refbuf_new (BUFSIZE);
if (m3u_requested && m3u_file_available == 0) if (m3u_requested && m3u_file_available == 0)
{ {
...@@ -580,6 +582,32 @@ int fserve_add_client (client_t *client, FILE *file) ...@@ -580,6 +582,32 @@ int fserve_add_client (client_t *client, FILE *file)
} }
/* add client to file serving engine, but just write out the buffer contents,
* then pass the client to the callback with the provided arg
*/
void fserve_add_client_callback (client_t *client, fserve_callback_t callback, void *arg)
{
fserve_t *fclient = calloc (1, sizeof(fserve_t));
DEBUG0 ("Adding client to file serving engine");
if (fclient == NULL)
{
client_send_404 (client, "memory exhausted");
return;
}
fclient->file = NULL;
fclient->client = client;
fclient->ready = 0;
fclient->callback = callback;
fclient->arg = arg;
thread_mutex_lock (&pending_lock);
fclient->next = (fserve_t *)pending_list;
pending_list = fclient;
thread_mutex_unlock (&pending_lock);
}
static int _delete_mapping(void *mapping) { static int _delete_mapping(void *mapping) {
mime_type *map = mapping; mime_type *map = mapping;
free(map->ext); free(map->ext);
......
...@@ -15,12 +15,16 @@ ...@@ -15,12 +15,16 @@
#include <stdio.h> #include <stdio.h>
typedef void (*fserve_callback_t)(client_t *, void *);
typedef struct _fserve_t typedef struct _fserve_t
{ {
client_t *client; client_t *client;
FILE *file; FILE *file;
int ready; int ready;
void (*callback)(client_t *, void *);
void *arg;
struct _fserve_t *next; struct _fserve_t *next;
} fserve_t; } fserve_t;
...@@ -28,6 +32,7 @@ void fserve_initialize(void); ...@@ -28,6 +32,7 @@ void fserve_initialize(void);
void fserve_shutdown(void); void fserve_shutdown(void);
int fserve_client_create(client_t *httpclient, const char *path); int fserve_client_create(client_t *httpclient, const char *path);
int fserve_add_client (client_t *client, FILE *file); int fserve_add_client (client_t *client, FILE *file);
void fserve_add_client_callback (client_t *client, fserve_callback_t callback, void *arg);
char *fserve_content_type (const char *path); char *fserve_content_type (const char *path);
......
...@@ -1184,28 +1184,6 @@ void *source_client_thread (void *arg) ...@@ -1184,28 +1184,6 @@ void *source_client_thread (void *arg)
{ {
source_t *source = arg; source_t *source = arg;
if (source->client && source->client->con)
{
const char ok_msg[] = "HTTP/1.0 200 OK\r\n\r\n";
int bytes;
const char *agent;
source->client->respcode = 200;
bytes = sock_write_bytes (source->client->con->sock, ok_msg, sizeof (ok_msg)-1);
if (bytes < (int)(sizeof (ok_msg)-1))
{
global_lock();
global.sources--;
global_unlock();
WARN0 ("Error writing 200 OK message to source client");
source_free_source (source);
return NULL;
}
stats_event (source->mount, "source_ip", source->client->con->ip);
agent = httpp_getvar (source->client->parser, "user-agent");
if (agent)
stats_event (source->mount, "user_agent", agent);
}
stats_event_inc(NULL, "source_client_connections"); stats_event_inc(NULL, "source_client_connections");
stats_event (source->mount, "listeners", "0"); stats_event (source->mount, "listeners", "0");
...@@ -1218,6 +1196,30 @@ void *source_client_thread (void *arg) ...@@ -1218,6 +1196,30 @@ void *source_client_thread (void *arg)
} }
void source_client_callback (client_t *client, void *arg)
{
const char *agent;
source_t *source = arg;
if (client->con->error)
{
global_lock();
global.sources--;
global_unlock();
source_free_source (source);
client_destroy (client);
return;
}
stats_event (source->mount, "source_ip", source->client->con->ip);
agent = httpp_getvar (source->client->parser, "user-agent");
if (agent)
stats_event (source->mount, "user_agent", agent);
thread_create ("Source Thread", source_client_thread,
source, THREAD_DETACHED);
}
#ifndef _WIN32 #ifndef _WIN32
static void source_run_script (char *command, char *mountpoint) static void source_run_script (char *command, char *mountpoint)
{ {
......
...@@ -78,6 +78,7 @@ typedef struct source_tag ...@@ -78,6 +78,7 @@ typedef struct source_tag
source_t *source_reserve (const char *mount); source_t *source_reserve (const char *mount);
void *source_client_thread (void *arg); void *source_client_thread (void *arg);
void source_client_callback (client_t *client, void *source);
void source_update_settings (ice_config_t *config, source_t *source, mount_proxy *mountinfo); void source_update_settings (ice_config_t *config, source_t *source, mount_proxy *mountinfo);
void source_clear_source (source_t *source); void source_clear_source (source_t *source);
source_t *source_find_mount(const char *mount); source_t *source_find_mount(const char *mount);
......
...@@ -59,17 +59,17 @@ typedef struct _event_listener_tag ...@@ -59,17 +59,17 @@ typedef struct _event_listener_tag
struct _event_listener_tag *next; struct _event_listener_tag *next;
} event_listener_t; } event_listener_t;
volatile static int _stats_running = 0; static volatile int _stats_running = 0;
static thread_type *_stats_thread_id; static thread_type *_stats_thread_id;
volatile static int _stats_threads = 0; static volatile int _stats_threads = 0;
static stats_t _stats; static stats_t _stats;
static mutex_t _stats_mutex; static mutex_t _stats_mutex;
volatile static stats_event_t *_global_event_queue; static volatile stats_event_t *_global_event_queue;
mutex_t _global_event_mutex; mutex_t _global_event_mutex;
volatile static event_listener_t *_event_listeners; static volatile event_listener_t *_event_listeners;
static void *_stats_thread(void *arg); static void *_stats_thread(void *arg);
...@@ -842,6 +842,19 @@ void *stats_connection(void *arg) ...@@ -842,6 +842,19 @@ void *stats_connection(void *arg)
return NULL; return NULL;
} }
void stats_callback (client_t *client, void *notused)
{
if (client->con->error)
{
client_destroy (client);
return;
}
client_set_queue (client, NULL);
thread_create("Stats Connection", stats_connection, (void *)client, THREAD_DETACHED);
}
typedef struct _source_xml_tag { typedef struct _source_xml_tag {
char *mount; char *mount;
xmlNodePtr node; xmlNodePtr node;
......
...@@ -84,7 +84,7 @@ void stats_event_hidden (const char *source, const char *name, int hidden); ...@@ -84,7 +84,7 @@ void stats_event_hidden (const char *source, const char *name, int hidden);
void stats_event_time (const char *mount, const char *name); void stats_event_time (const char *mount, const char *name);
void *stats_connection(void *arg); void *stats_connection(void *arg);
void *stats_callback(void *arg); void stats_callback (client_t *client, void *notused);
void stats_transform_xslt(client_t *client, const char *uri); void stats_transform_xslt(client_t *client, const char *uri);
void stats_sendxml(client_t *client); void stats_sendxml(client_t *client);
......
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