[xiph-cvs] cvs commit: icecast/src client.c client.h connection.c util.c
Michael Smith
msmith at xiph.org
Mon Aug 12 07:48:31 PDT 2002
msmith 02/08/12 10:48:31
Modified: src client.c client.h connection.c util.c
Log:
_handle_connection() cleanup, major restructuring. No feature changes.
Revision Changes Path
1.2 +11 -0 icecast/src/client.c
Index: client.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/client.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- client.c 10 Sep 2001 02:21:49 -0000 1.1
+++ client.c 12 Aug 2002 14:48:31 -0000 1.2
@@ -44,3 +44,14 @@
free(client);
}
+
+void client_send_404(client_t *client, char *message) {
+
+ int bytes;
+ bytes = sock_write(client->con->sock, "HTTP/1.0 404 File Not Found\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);
+}
+
<p><p>1.2 +1 -0 icecast/src/client.h
Index: client.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/client.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- client.h 10 Sep 2001 02:21:49 -0000 1.1
+++ client.h 12 Aug 2002 14:48:31 -0000 1.2
@@ -24,5 +24,6 @@
client_t *client_create(connection_t *con, http_parser_t *parser);
void client_destroy(client_t *client);
+void client_send_404(client_t *client, char *message);
#endif /* __CLIENT_H__ */
<p><p>1.22 +270 -258 icecast/src/connection.c
Index: connection.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- connection.c 12 Aug 2002 10:11:44 -0000 1.21
+++ connection.c 12 Aug 2002 14:48:31 -0000 1.22
@@ -331,20 +331,267 @@
return 0;
}
-static void *_handle_connection(void *arg)
+static int _check_source_pass(http_parser_t *parser)
+{
+ char *password, *correctpass;
+
+ password = httpp_getvar(parser, "ice-password");
+ correctpass = config_get_config()->source_password;
+ if(!password)
+ password = "";
+ if(!correctpass)
+ correctpass = "";
+
+ if (strcmp(password, correctpass))
+ return 0;
+ else
+ return 1;
+}
+
+static void _handle_source_request(connection_t *con,
+ http_parser_t *parser, char *uri)
+{
+ INFO1("Source logging in at mountpoint \"%s\"", uri);
+ stats_event_inc(NULL, "source_connections");
+
+ if (!_check_source_pass(parser)) {
+ INFO1("Source (%s) attempted to login with bad password", uri);
+ connection_close(con);
+ httpp_destroy(parser);
+ return;
+ }
+
+ /* check to make sure this source has
+ ** a unique mountpoint
+ */
+
+ avl_tree_rlock(global.source_tree);
+ if (source_find_mount(uri) != NULL) {
+ INFO1("Source tried to log in as %s, but mountpoint is already used", uri);
+ connection_close(con);
+ httpp_destroy(parser);
+ avl_tree_unlock(global.source_tree);
+ return;
+ }
+ avl_tree_unlock(global.source_tree);
+
+ if (!connection_create_source(con, parser, uri)) {
+ connection_close(con);
+ httpp_destroy(parser);
+ }
+}
+
+static void _handle_stats_request(connection_t *con,
+ http_parser_t *parser, char *uri)
{
- char header[4096];
- connection_t *con;
- http_parser_t *parser;
- source_t *source;
stats_connection_t *stats;
+
+ stats_event_inc(NULL, "stats_connections");
+
+ if (!_check_source_pass(parser)) {
+ ERROR0("Bad password for stats connection");
+ connection_close(con);
+ httpp_destroy(parser);
+ return;
+ }
+
+ stats_event_inc(NULL, "stats");
+
+ /* create stats connection and create stats handler thread */
+ stats = (stats_connection_t *)malloc(sizeof(stats_connection_t));
+ stats->parser = parser;
+ stats->con = con;
+
+ thread_create("Stats Connection", stats_connection, (void *)stats, THREAD_DETACHED);
+}
+
+static void _handle_get_request(connection_t *con,
+ http_parser_t *parser, char *uri)
+{
+ char *fullpath;
+ client_t *client;
avl_node *node;
http_var_t *var;
- client_t *client;
- int bytes;
+ int bytes;
struct stat statbuf;
- char *fullpath;
+ source_t *source;
+
+ DEBUG0("Client connected");
+
+ /* make a client */
+ client = client_create(con, parser);
+ stats_event_inc(NULL, "client_connections");
+
+ /* there are several types of HTTP GET clients
+ ** media clients, which are looking for a source (eg, URI = /stream.ogg)
+ ** stats clients, which are looking for /stats.xml
+ ** and director server authorizers, which are looking for /GUID-xxxxxxxx
+ ** (where xxxxxx is the GUID in question) - this isn't implemented yet.
+ ** we need to handle the latter two before the former, as the latter two
+ ** aren't subject to the limits.
+ */
+ /* TODO: add GUID-xxxxxx */
+ if (strcmp(uri, "/stats.xml") == 0) {
+ DEBUG0("Stats request, sending xml stats");
+ stats_sendxml(client);
+ client_destroy(client);
+ return;
+ }
+
+ /* Here we are parsing the URI request to see
+ ** if the extension is .xsl, if so, then process
+ ** this request as an XSLT request
+ */
+ fullpath = util_get_path_from_normalised_uri(uri);
+ if (util_check_valid_extension(fullpath) == XSLT_CONTENT) {
+ /* If the file exists, then transform it, otherwise, write a 404 */
+ if (stat(fullpath, &statbuf) == 0) {
+ DEBUG0("Stats request, sending XSL transformed stats");
+ bytes = sock_write(client->con->sock,
+ "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
+ if(bytes > 0) client->con->sent_bytes = bytes;
+ stats_transform_xslt(client, fullpath);
+ client_destroy(client);
+ }
+ else {
+ client_send_404(client, "The file you requested could not be found");
+ }
+ free(fullpath);
+ return;
+ }
+ free(fullpath);
+
+ if(strcmp(util_get_extension(uri), "m3u") == 0) {
+ char *sourceuri = strdup(uri);
+ char *dot = strrchr(sourceuri, '.');
+ *dot = 0;
+ avl_tree_rlock(global.source_tree);
+ source = source_find_mount(sourceuri);
+ if (source) {
+ client->respcode = 200;
+ bytes = sock_write(client->con->sock,
+ "HTTP/1.0 200 OK\r\n"
+ "Content-Type: audio/x-mpegurl\r\n\r\n"
+ "http://%s:%d%s",
+ config_get_config()->hostname,
+ config_get_config()->port,
+ sourceuri
+ );
+ if(bytes > 0) client->con->sent_bytes = bytes;
+ client_destroy(client);
+ }
+ else {
+ client_send_404(client, "The file you requested could not be found");
+ }
+ avl_tree_unlock(global.source_tree);
+ free(sourceuri);
+ return;
+ }
+
+ if (strcmp(uri, "/allstreams.txt") == 0) {
+ if (!_check_source_pass(parser)) {
+ INFO0("Client attempted to fetch allstreams.txt with bad password");
+ client_send_404(client, "Bad ice-password");
+ } else {
+ avl_node *node;
+ source_t *s;
+ avl_tree_rlock(global.source_tree);
+ node = avl_get_first(global.source_tree);
+ while (node) {
+ s = (source_t *)node->key;
+ bytes = sock_write(client->con->sock, "%s\r\n", s->mount);
+ if(bytes > 0) client->con->sent_bytes += bytes;
+ else break;
+
+ node = avl_get_next(node);
+ }
+ avl_tree_unlock(global.source_tree);
+ client_destroy(client);
+ }
+ return;
+ }
+
+ global_lock();
+ if (global.clients >= config_get_config()->client_limit) {
+ 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>The server is already full. Try again later.</b>\r\n");
+ if (bytes > 0) client->con->sent_bytes = bytes;
+ client_destroy(client);
+ global_unlock();
+ return;
+ }
+ global_unlock();
+
+ avl_tree_rlock(global.source_tree);
+ source = source_find_mount(uri);
+ if (source) {
+ DEBUG0("Source found for client");
+
+ global_lock();
+ if (global.clients >= config_get_config()->client_limit) {
+ 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>The server is already full. Try again later.</b>\r\n");
+ if (bytes > 0) client->con->sent_bytes = bytes;
+ client_destroy(client);
+ global_unlock();
+ avl_tree_unlock(global.source_tree);
+ return;
+ }
+ global.clients++;
+ global_unlock();
+
+ client->respcode = 200;
+ bytes = sock_write(client->con->sock,
+ "HTTP/1.0 200 OK\r\n"
+ "Content-Type: %s\r\n",
+ format_get_mimetype(source->format->type));
+ if(bytes > 0) client->con->sent_bytes += bytes;
+ /* iterate through source http headers and send to client */
+ avl_tree_rlock(source->parser->vars);
+ node = avl_get_first(source->parser->vars);
+ while (node) {
+ var = (http_var_t *)node->key;
+ if (strcasecmp(var->name, "ice-password") &&
+ !strncasecmp("ice-", var->name, 4)) {
+ bytes = sock_write(client->con->sock,
+ "%s: %s\r\n", var->name, var->value);
+ if(bytes > 0) client->con->sent_bytes += bytes;
+ }
+ node = avl_get_next(node);
+ }
+ avl_tree_unlock(source->parser->vars);
+
+ bytes = sock_write(client->con->sock, "\r\n");
+ if(bytes > 0) client->con->sent_bytes += bytes;
+
+ sock_set_blocking(client->con->sock, SOCK_NONBLOCK);
+
+ avl_tree_wlock(source->pending_tree);
+ avl_insert(source->pending_tree, (void *)client);
+ avl_tree_unlock(source->pending_tree);
+ }
+
+ avl_tree_unlock(global.source_tree);
+
+ if (!source) {
+ DEBUG0("Source not found for client");
+ client_send_404(client, "The source you requested could not be found.");
+ }
+}
+
+static void *_handle_connection(void *arg)
+{
+ char header[4096];
+ connection_t *con;
+ http_parser_t *parser;
char *rawuri, *uri;
+ client_t *client;
while (global.running == ICE_RUNNING) {
memset(header, 0, 4096);
@@ -370,7 +617,8 @@
if (httpp_parse(parser, header, strlen(header))) {
/* handle the connection or something */
- if (strcmp("ICE", httpp_getvar(parser, HTTPP_VAR_PROTOCOL)) != 0 && strcmp("HTTP", httpp_getvar(parser, HTTPP_VAR_PROTOCOL)) != 0) {
+ if (strcmp("ICE", httpp_getvar(parser, HTTPP_VAR_PROTOCOL)) &&
+ strcmp("HTTP", httpp_getvar(parser, HTTPP_VAR_PROTOCOL))) {
ERROR0("Bad HTTP protocol detected");
connection_close(con);
httpp_destroy(parser);
@@ -382,262 +630,26 @@
if(!uri) {
client = client_create(con, parser);
- bytes = sock_write(client->con->sock, "HTTP/1.0 404 File Not Found\r\nContent-Type: text/html\r\n\r\n"\
- "<b>The path you requested was invalid.</b>\r\n");
- if(bytes > 0) client->con->sent_bytes = bytes;
- client_destroy(client);
+ client_send_404(client, "The path you requested was invalid");
continue;
}
if (parser->req_type == httpp_req_source) {
- INFO1("Source logging in at mountpoint \"%s\"", uri);
- stats_event_inc(NULL, "source_connections");
-
- if (strcmp((httpp_getvar(parser, "ice-password") != NULL) ? httpp_getvar(parser, "ice-password") : "", (config_get_config()->source_password != NULL) ? config_get_config()->source_password : "") != 0) {
- INFO1("Source (%s) attempted to login with bad password", uri);
- connection_close(con);
- httpp_destroy(parser);
- free(uri);
- continue;
- }
-
- /* check to make sure this source has
- ** a unique mountpoint
- */
-
- avl_tree_rlock(global.source_tree);
- if (source_find_mount(uri) != NULL) {
- INFO1("Source tried to log in as %s, but is already used", uri);
- connection_close(con);
- httpp_destroy(parser);
- free(uri);
- avl_tree_unlock(global.source_tree);
- continue;
- }
- avl_tree_unlock(global.source_tree);
-
- if (!connection_create_source(con, parser, uri)) {
- connection_close(con);
- httpp_destroy(parser);
- free(uri);
- }
-
- continue;
- } else if (parser->req_type == httpp_req_stats) {
- stats_event_inc(NULL, "stats_connections");
-
- if (strcmp((httpp_getvar(parser, "ice-password") != NULL) ? httpp_getvar(parser, "ice-password") : "", (config_get_config()->source_password != NULL) ? config_get_config()->source_password : "") != 0) {
- ERROR0("Bad password for stats connection");
- connection_close(con);
- httpp_destroy(parser);
- free(uri);
- continue;
- }
-
- stats_event_inc(NULL, "stats");
-
- /* create stats connection and create stats handler thread */
- stats = (stats_connection_t *)malloc(sizeof(stats_connection_t));
- stats->parser = parser;
- stats->con = con;
-
- thread_create("Stats Connection", stats_connection, (void *)stats, THREAD_DETACHED);
-
- free(uri);
- continue;
- } else if (parser->req_type == httpp_req_play || parser->req_type == httpp_req_get) {
- DEBUG0("Client connected");
-
- /* make a client */
- client = client_create(con, parser);
- stats_event_inc(NULL, "client_connections");
-
- /* there are several types of HTTP GET clients
- ** media clients, which are looking for a source (eg, URI = /stream.ogg)
- ** stats clients, which are looking for /stats.xml
- ** and director server authorizers, which are looking for /GUID-xxxxxxxx (where xxxxxx is the GUID in question
- ** we need to handle the latter two before the former, as the latter two
- ** aren't subject to the limits.
- */
- // TODO: add GUID-xxxxxx
- if (strcmp(uri, "/stats.xml") == 0) {
- DEBUG0("Stats request, sending xml stats");
- stats_sendxml(client);
- client_destroy(client);
- free(uri);
- continue;
- }
-
- /* Here we are parsing the URI request to see
- ** if the extension is .xsl, if so, then process
- ** this request as an XSLT request
- */
- fullpath = util_get_path_from_normalised_uri(uri);
- if (util_check_valid_extension(fullpath) == XSLT_CONTENT) {
- /* If the file exists, then transform it, otherwise, write a 404 error */
- if (stat(fullpath, &statbuf) == 0) {
- DEBUG0("Stats request, sending XSL transformed stats");
- bytes = sock_write(client->con->sock, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
- if(bytes > 0) client->con->sent_bytes = bytes;
- stats_transform_xslt(client, fullpath);
- }
- else {
- bytes = sock_write(client->con->sock, "HTTP/1.0 404 File Not Found\r\nContent-Type: text/html\r\n\r\n"\
- "<b>The file you requested could not be found.</b>\r\n");
- if(bytes > 0) client->con->sent_bytes = bytes;
- }
- free(fullpath);
- free(uri);
- client_destroy(client);
- continue;
- }
- free(fullpath);
-
- if(strcmp(util_get_extension(uri), "m3u") == 0) {
- char *sourceuri = strdup(uri);
- char *dot = strrchr(sourceuri, '.');
- *dot = 0;
- avl_tree_rlock(global.source_tree);
- source = source_find_mount(sourceuri);
- if (source) {
- client->respcode = 200;
- bytes = sock_write(client->con->sock,
- "HTTP/1.0 200 OK\r\nContent-Type: audio/x-mpegurl\r\n\r\nhttp://%s:%d%s",
- config_get_config()->hostname,
- config_get_config()->port,
- sourceuri
- );
- }
- else {
- client->respcode = 404;
- bytes = sock_write(client->con->sock,
- "HTTP/1.0 404 Not Found\r\nContent-Type: text/html\r\n\r\n<b>The file you requested could not be found</b>\r\n");
- }
- avl_tree_unlock(global.source_tree);
- if(bytes > 0) client->con->sent_bytes = bytes;
- free(sourceuri);
- free(uri);
- client_destroy(client);
- continue;
- }
-
- if (strcmp(uri, "/allstreams.txt") == 0) {
- if (strcmp((httpp_getvar(parser, "ice-password") != NULL) ? httpp_getvar(parser, "ice-password") : "", (config_get_config()->source_password != NULL) ? config_get_config()->source_password : "") != 0) {
- INFO0("Client attempted to fetch allstreams.txt with bad password");
- if (parser->req_type == httpp_req_get) {
- client->respcode = 404;
- bytes = sock_write(client->con->sock, "HTTP/1.0 404 Source Not Found\r\nContent-Type: text/html\r\n\r\n"\
- "<b>The source you requested could not be found.</b>\r\n");
- if (bytes > 0) client->con->sent_bytes = bytes;
- }
- } else {
- avl_node *node;
- source_t *s;
- avl_tree_rlock(global.source_tree);
- node = avl_get_first(global.source_tree);
- while (node) {
- s = (source_t *)node->key;
- bytes = sock_write(client->con->sock, "%s\r\n", s->mount);
- if(bytes > 0)
- client->con->sent_bytes += bytes;
- else
- break;
-
- node = avl_get_next(node);
- }
- avl_tree_unlock(global.source_tree);
- }
- free(uri);
- client_destroy(client);
- continue;
- }
-
- global_lock();
- if (global.clients >= config_get_config()->client_limit) {
- if (parser->req_type == httpp_req_get) {
- client->respcode = 504;
- bytes = sock_write(client->con->sock, "HTTP/1.0 504 Server Full\r\nContent-Type: text/html\r\n\r\n"\
- "<b>The server is already full. Try again later.</b>\r\n");
- if (bytes > 0) client->con->sent_bytes = bytes;
- }
- client_destroy(client);
- global_unlock();
- free(uri);
- continue;
- }
- global_unlock();
-
- avl_tree_rlock(global.source_tree);
- source = source_find_mount(uri);
- if (source) {
- DEBUG0("Source found for client");
-
- global_lock();
- if (global.clients >= config_get_config()->client_limit) {
- if (parser->req_type == httpp_req_get) {
- client->respcode = 504;
- bytes = sock_write(client->con->sock, "HTTP/1.0 504 Server Full\r\nContent-Type: text/html\r\n\r\n"\
- "<b>The server is already full. Try again later.</b>\r\n");
- if (bytes > 0) client->con->sent_bytes = bytes;
- }
- free(uri);
- client_destroy(client);
- global_unlock();
- continue;
- }
- global.clients++;
- global_unlock();
-
- if (parser->req_type == httpp_req_get) {
- client->respcode = 200;
- bytes = sock_write(client->con->sock, "HTTP/1.0 200 OK\r\nContent-Type: %s\r\n", format_get_mimetype(source->format->type));
- if(bytes > 0) client->con->sent_bytes += bytes;
- /* iterate through source http headers and send to client */
- avl_tree_rlock(source->parser->vars);
- node = avl_get_first(source->parser->vars);
- while (node) {
- var = (http_var_t *)node->key;
- if (strcasecmp(var->name, "ice-password") && !strncasecmp("ice-", var->name, 4)) {
- bytes = sock_write(client->con->sock, "%s: %s\r\n", var->name, var->value);
- if(bytes > 0) client->con->sent_bytes += bytes;
- }
- node = avl_get_next(node);
- }
- avl_tree_unlock(source->parser->vars);
-
- bytes = sock_write(client->con->sock, "\r\n");
- if(bytes > 0) client->con->sent_bytes += bytes;
-
- sock_set_blocking(client->con->sock, SOCK_NONBLOCK);
- }
-
- avl_tree_wlock(source->pending_tree);
- avl_insert(source->pending_tree, (void *)client);
- avl_tree_unlock(source->pending_tree);
- }
-
- avl_tree_unlock(global.source_tree);
-
- if (!source) {
- DEBUG0("Source not found for client");
- if (parser->req_type == httpp_req_get) {
- client->respcode = 404;
- bytes = sock_write(client->con->sock, "HTTP/1.0 404 Source Not Found\r\nContent-Type: text/html\r\n\r\n"\
- "<b>The source you requested could not be found.</b>\r\n");
- if (bytes > 0) client->con->sent_bytes = bytes;
- }
- client_destroy(client);
- }
-
- free(uri);
- continue;
- } else {
+ _handle_source_request(con, parser, uri);
+ }
+ else if (parser->req_type == httpp_req_stats) {
+ _handle_stats_request(con, parser, uri);
+ }
+ else if (parser->req_type == httpp_req_get) {
+ _handle_get_request(con, parser, uri);
+ }
+ else {
ERROR0("Wrong request type from client");
connection_close(con);
httpp_destroy(parser);
- free(uri);
- continue;
- }
+ }
+
+ free(uri);
} else {
ERROR0("HTTP request parsing failed");
connection_close(con);
<p><p>1.9 +0 -3 icecast/src/util.c
Index: util.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/util.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- util.c 11 Aug 2002 14:23:39 -0000 1.8
+++ util.c 12 Aug 2002 14:48:31 -0000 1.9
@@ -206,9 +206,6 @@
return fullpath;
}
-
-
-
/* Get an absolute path (from the webroot dir) from a URI. Return NULL if the
* path contains 'disallowed' sequences like foo/../ (which could be used to
* escape from the webroot) or if it cannot be URI-decoded.
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list