From 03458817ccbf6d849dfd596e72f143a52f907ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Thu, 7 Aug 2008 14:12:51 +0200 Subject: [PATCH] Updated TODO hints --- src/condition.c | 40 +++++++++++++++++++++------------------- src/condition.h | 2 +- src/connection.c | 23 +++++++++++------------ src/connection.h | 3 ++- src/http_headers.c | 13 +++++++++++++ src/http_headers.h | 3 +++ src/plugin_core.c | 2 +- src/request.c | 42 ++++++++++++++++++++++++++++++++++++++++-- src/request.h | 6 +++++- src/server.c | 25 +++++++++++++++++++++++-- src/server.h | 2 +- 11 files changed, 121 insertions(+), 40 deletions(-) diff --git a/src/condition.c b/src/condition.c index c6f095c..9746570 100644 --- a/src/condition.c +++ b/src/condition.c @@ -47,6 +47,7 @@ static gboolean condition_ip_from_socket(condition_rvalue *val, sock_addr *addr) condition_lvalue* condition_lvalue_new(cond_lvalue_t type, GString *key) { condition_lvalue *lvalue = g_slice_new0(condition_lvalue); + if (type == COMP_REQUEST_HEADER) g_string_ascii_down(key); lvalue->type = type; lvalue->key = key; lvalue->refcount = 1; @@ -89,7 +90,7 @@ static condition* cond_new_string(comp_operator_t op, condition_lvalue *lvalue, static condition* cond_new_match(server *srv, comp_operator_t op, condition_lvalue *lvalue, GString *str) { UNUSED(op); UNUSED(lvalue); UNUSED(str); ERROR(srv, "%s", "pcre not supported for now"); - /* TODO */ + /* TODO: pcre */ return NULL; } #endif @@ -237,13 +238,11 @@ const char* cond_lvalue_to_string(cond_lvalue_t t) { /* COND_VALUE_STRING and COND_VALUE_REGEXP only */ static gboolean condition_check_eval_string(server *srv, connection *con, condition *cond) { const char *value = ""; - GString *tmp = NULL; gboolean result = FALSE; UNUSED(srv); UNUSED(con); switch (cond->lvalue->type) { - /* TODO: get values */ case COMP_REQUEST_LOCALIP: value = con->local_addr_str->str; break; @@ -266,21 +265,23 @@ static gboolean condition_check_eval_string(server *srv, connection *con, condit value = con->request.http_method_str->str; break; case COMP_PHYSICAL_PATH: + value = con->physical.path->str; + break; case COMP_PHYSICAL_PATH_EXISTS: - /* TODO */ + /* TODO: physical path exists */ break; case COMP_REQUEST_HEADER: - /* TODO */ + http_header_get_fast(srv->tmp_str, con->request.headers, GSTR_LEN(cond->lvalue->key)); + value = srv->tmp_str->str; break; case COMP_PHYSICAL_SIZE: - /* TODO */ - g_string_printf((tmp = g_string_sized_new(0)), "%"L_GOFFSET_FORMAT, (goffset) 0); - value = tmp->str; + /* TODO: physical size */ + g_string_printf(srv->tmp_str, "%"L_GOFFSET_FORMAT, (goffset) 0); + value = srv->tmp_str->str; break; case COMP_REQUEST_CONTENT_LENGTH: - /* TODO */ - g_string_printf((tmp = g_string_sized_new(0)), "%"L_GOFFSET_FORMAT, (goffset) 0); - value = tmp->str; + g_string_printf(srv->tmp_str, "%"L_GOFFSET_FORMAT, con->request.content_length); + value = srv->tmp_str->str; break; } @@ -310,7 +311,6 @@ static gboolean condition_check_eval_string(server *srv, connection *con, condit break; } - if (tmp) g_string_free(tmp, TRUE); return result; } @@ -327,6 +327,7 @@ static gboolean condition_check_eval_int(server *srv, connection *con, condition value = con->physical.size; break; default: + CON_ERROR(srv, con, "couldn't get int value for '%s', using -1", cond_lvalue_to_string(cond->lvalue->type)); value = -1; } @@ -349,8 +350,6 @@ static gboolean condition_check_eval_int(server *srv, connection *con, condition case CONFIG_COND_NOTIP: ERROR(srv, "cannot compare int with '%s'", comp_op_to_string(cond->op)); return FALSE; - } else { - ERROR(srv, "couldn't get int value for '%s'", cond_lvalue_to_string(cond->lvalue->type)); } return FALSE; @@ -408,7 +407,6 @@ static gboolean condition_check_eval_ip(server *srv, connection *con, condition ipval.type = COND_VALUE_INT; switch (cond->lvalue->type) { - /* TODO: get values */ case COMP_REQUEST_LOCALIP: if (!condition_ip_from_socket(&ipval, &con->local_addr)) return (cond->op == CONFIG_COND_NOTIP); @@ -418,7 +416,8 @@ static gboolean condition_check_eval_ip(server *srv, connection *con, condition return (cond->op == CONFIG_COND_NOTIP); break; case COMP_REQUEST_PATH: - value = con->request.uri.path->str; + ERROR(srv, "%s", "Cannot parse request.path as ip"); + return (cond->op == CONFIG_COND_NOTIP); break; case COMP_REQUEST_HOST: value = con->request.host->str; @@ -430,14 +429,17 @@ static gboolean condition_check_eval_ip(server *srv, connection *con, condition value = con->request.uri.query->str; break; case COMP_REQUEST_METHOD: - value = con->request.http_method_str->str; + ERROR(srv, "%s", "Cannot request.method as ip"); + return (cond->op == CONFIG_COND_NOTIP); break; case COMP_PHYSICAL_PATH: case COMP_PHYSICAL_PATH_EXISTS: - /* TODO */ + ERROR(srv, "%s", "Cannot physical.path(-exists) as ip"); + return (cond->op == CONFIG_COND_NOTIP); break; case COMP_REQUEST_HEADER: - /* TODO */ + http_header_get_fast(srv->tmp_str, con->request.headers, GSTR_LEN(cond->lvalue->key)); + value = srv->tmp_str->str; break; case COMP_PHYSICAL_SIZE: case COMP_REQUEST_CONTENT_LENGTH: diff --git a/src/condition.h b/src/condition.h index da16118..faaf622 100644 --- a/src/condition.h +++ b/src/condition.h @@ -51,7 +51,7 @@ typedef enum { COMP_PHYSICAL_SIZE, /* needs a key */ - COMP_REQUEST_HEADER + COMP_REQUEST_HEADER /**< needs lowercase key, enforced by condition_lvalue_new */ } cond_lvalue_t; #define COND_LVALUE_FIRST_WITH_KEY COMP_REQUEST_HEADER diff --git a/src/connection.c b/src/connection.c index 054195a..b1d7ddb 100644 --- a/src/connection.c +++ b/src/connection.c @@ -78,11 +78,11 @@ static void connection_cb(struct ev_loop *loop, ev_io *w, int revents) { case NETWORK_STATUS_WAIT_FOR_EVENT: break; case NETWORK_STATUS_WAIT_FOR_AIO_EVENT: - /* TODO ? */ + /* TODO: aio */ ev_io_rem_events(loop, w, EV_READ); break; case NETWORK_STATUS_WAIT_FOR_FD: - /* TODO */ + /* TODO: wait for fd */ ev_io_rem_events(loop, w, EV_READ); break; } @@ -106,11 +106,11 @@ static void connection_cb(struct ev_loop *loop, ev_io *w, int revents) { case NETWORK_STATUS_WAIT_FOR_EVENT: break; case NETWORK_STATUS_WAIT_FOR_AIO_EVENT: - /* TODO ? */ + /* TODO: aio */ ev_io_rem_events(loop, w, EV_WRITE); break; case NETWORK_STATUS_WAIT_FOR_FD: - /* TODO */ + /* TODO: wait for fd */ ev_io_rem_events(loop, w, EV_WRITE); break; } @@ -149,6 +149,7 @@ connection* connection_new(server *srv) { action_stack_init(&con->action_stack); request_init(&con->request, con->raw_in); + physical_init(&con->physical); response_init(&con->response); return con; @@ -177,6 +178,7 @@ void connection_reset(server *srv, connection *con) { action_stack_reset(srv, &con->action_stack); request_reset(&con->request); + physical_reset(&con->physical); response_reset(&con->response); } @@ -197,6 +199,7 @@ void connection_reset_keep_alive(server *srv, connection *con) { action_stack_reset(srv, &con->action_stack); request_reset(&con->request); + physical_reset(&con->physical); response_reset(&con->response); } @@ -223,6 +226,7 @@ void connection_free(server *srv, connection *con) { action_stack_clear(srv, &con->action_stack); request_clear(&con->request); + physical_clear(&con->physical); response_clear(&con->response); g_slice_free(connection, con); @@ -241,7 +245,6 @@ void connection_state_machine(server *srv, connection *con) { do { switch (con->state) { case CON_STATE_REQUEST_START: - /* TODO: reset some values after keep alive - or do it in CON_STATE_REQUEST_END */ connection_set_state(srv, con, CON_STATE_READ_REQUEST_HEADER); action_enter(con, srv->mainaction); break; @@ -253,7 +256,7 @@ void connection_state_machine(server *srv, connection *con) { connection_set_state(srv, con, CON_STATE_VALIDATE_REQUEST_HEADER); break; case HANDLER_WAIT_FOR_FD: - /* TODO */ + /* TODO: wait for fd */ done = TRUE; break; case HANDLER_WAIT_FOR_EVENT: @@ -285,9 +288,7 @@ void connection_state_machine(server *srv, connection *con) { connection_set_state(srv, con, CON_STATE_WRITE_RESPONSE); break; case ACTION_ERROR: - /* action return error */ - /* TODO: return 500 instead ? */ - connection_set_state(srv, con, CON_STATE_ERROR); + internal_error(srv, con); break; } break; @@ -305,9 +306,7 @@ void connection_state_machine(server *srv, connection *con) { connection_set_state(srv, con, CON_STATE_WRITE_RESPONSE); break; case ACTION_ERROR: - /* action return error */ - /* TODO: return 500 instead ? */ - connection_set_state(srv, con, CON_STATE_ERROR); + internal_error(srv, con); break; } break; diff --git a/src/connection.h b/src/connection.h index 06dbe4d..4e2abe0 100644 --- a/src/connection.h +++ b/src/connection.h @@ -67,6 +67,7 @@ struct connection { guint idx; /** index in connection table */ connection_state_t state; gboolean response_headers_sent, expect_100_cont; + /* TODO: implement expect_100 */ chunkqueue *raw_in, *raw_out; chunkqueue *in, *out; @@ -78,7 +79,7 @@ struct connection { action_stack action_stack; - gpointer *options; /* TODO */ + gpointer *options; /* TODO: options */ request request; physical physical; diff --git a/src/http_headers.c b/src/http_headers.c index ce7df35..7c20f51 100644 --- a/src/http_headers.c +++ b/src/http_headers.c @@ -1,4 +1,5 @@ +#include "base.h" #include "http_headers.h" static void _string_free(gpointer p) { @@ -154,3 +155,15 @@ gboolean http_header_is(http_headers *headers, const gchar *key, size_t keylen, } return FALSE; } + +void http_header_get_fast(GString *dest, http_headers *headers, const gchar *key, size_t keylen) { + http_header *h = http_header_lookup_fast(headers, key, keylen); + GList *iter; + + g_string_truncate(dest, 0); + if (!h) return; + for (iter = g_queue_peek_head_link(&h->values); NULL != iter; iter = g_list_next(iter)) { + if (dest->len) g_string_append_len(dest, CONST_STR_LEN(", ")); + g_string_append_len(dest, GSTR_LEN((GString*)iter->data)); + } +} diff --git a/src/http_headers.h b/src/http_headers.h index d4c75e7..839b93c 100644 --- a/src/http_headers.h +++ b/src/http_headers.h @@ -41,4 +41,7 @@ LI_API http_header* http_header_lookup_fast(http_headers *headers, const gchar * /** Use lowercase keys! values are compared case-insensitive */ LI_API gboolean http_header_is(http_headers *headers, const gchar *key, size_t keylen, const gchar *value, size_t valuelen); +/** concats all headers with key with ', ' - empty if no header exists - use lowercase key*/ +LI_API void http_header_get_fast(GString *dest, http_headers *headers, const gchar *key, size_t keylen); + #endif diff --git a/src/plugin_core.c b/src/plugin_core.c index ad8eb4b..5d2b1a5 100644 --- a/src/plugin_core.c +++ b/src/plugin_core.c @@ -65,7 +65,7 @@ static action* core_when(server *srv, plugin* p, option *opt) { static action_result core_handle_static(server *srv, connection *con, gpointer param) { UNUSED(param); - /* TODO */ + /* TODO: handle static files */ CON_ERROR(srv, con, "%s", "Not implemented yet"); return ACTION_ERROR; } diff --git a/src/request.c b/src/request.c index aa11862..4380d55 100644 --- a/src/request.c +++ b/src/request.c @@ -68,9 +68,15 @@ static void bad_request(server *srv, connection *con, int status) { connection_handle_direct(srv, con); } +gboolean request_parse_url(server *srv, connection *con) { + request *req = &con->request; + + /* TODO: parse url */ + return TRUE; +} + void request_validate_header(server *srv, connection *con) { request *req = &con->request; - response *resp = &con->response; http_header *hh; switch (req->http_version) { @@ -99,9 +105,12 @@ void request_validate_header(server *srv, connection *con) { return; } else if (hh) { g_string_append_len(req->host, GSTR_LEN((GString*) g_queue_peek_head(&hh->values))); -// CON_TRACE(srv, con, "hostname: '%s'", req->host->str); } + /* may override hostname */ + if (!request_parse_url(srv, con)) + return; + /* content-length */ hh = http_header_lookup_fast(req->headers, CONST_STR_LEN("content-length")); if (hh) { @@ -195,4 +204,33 @@ void request_validate_header(server *srv, connection *con) { /* the may have a content-length */ break; } + + /* TODO: check hostname */ +} + +void physical_init(physical *phys) { + phys->path = g_string_sized_new(512); + phys->basedir = g_string_sized_new(256); + phys->doc_root = g_string_sized_new(256); + phys->rel_path = g_string_sized_new(256); + phys->pathinfo = g_string_sized_new(256); + phys->size = -1; +} + +void physical_reset(physical *phys) { + g_string_truncate(phys->path, 0); + g_string_truncate(phys->basedir, 0); + g_string_truncate(phys->doc_root, 0); + g_string_truncate(phys->rel_path, 0); + g_string_truncate(phys->pathinfo, 0); + phys->size = -1; +} + +void physical_clear(physical *phys) { + g_string_free(phys->path, TRUE); + g_string_free(phys->basedir, TRUE); + g_string_free(phys->doc_root, TRUE); + g_string_free(phys->rel_path, TRUE); + g_string_free(phys->pathinfo, TRUE); + phys->size = -1; } diff --git a/src/request.h b/src/request.h index aaeffdf..92af159 100644 --- a/src/request.h +++ b/src/request.h @@ -63,7 +63,7 @@ struct physical { GString *pathinfo; - guint64 size; + gint64 size; }; struct request { @@ -87,4 +87,8 @@ LI_API void request_clear(request *req); LI_API void request_validate_header(server *srv, connection *con); +LI_API void physical_init(physical *phys); +LI_API void physical_reset(physical *phys); +LI_API void physical_clear(physical *phys); + #endif diff --git a/src/server.c b/src/server.c index 43bcd99..d801120 100644 --- a/src/server.c +++ b/src/server.c @@ -2,6 +2,8 @@ #include "base.h" #include "utils.h" +void con_put(server *srv, connection *con); + static void server_option_free(gpointer _so) { g_slice_free(server_option, _so); } @@ -48,12 +50,31 @@ server* server_new() { void server_free(server* srv) { if (!srv) return; - /* TODO */ + srv->exiting = TRUE; + server_stop(srv); + + { /* close connections */ + guint i; + if (srv->connections_active > 0) { + ERROR(srv, "Server shutdown with unclosed connections: %u", srv->connections_active); + for (i = srv->connections_active; i-- > 0;) { + connection *con = g_array_index(srv->connections, connection*, i); + connection_set_state(srv, con, CON_STATE_ERROR); + connection_state_machine(srv, con); /* cleanup plugins */ + con_put(srv, con); + } + } + for (i = 0; i < srv->connections->len; i++) { + connection_free(srv, g_array_index(srv->connections, connection*, i)); + } + g_array_free(srv->connections, TRUE); + } + + g_hash_table_destroy(srv->plugins); g_hash_table_destroy(srv->options); g_hash_table_destroy(srv->actions); g_hash_table_destroy(srv->setups); - g_hash_table_destroy(srv->plugins); action_release(srv, srv->mainaction); diff --git a/src/server.h b/src/server.h index aa74106..388a135 100644 --- a/src/server.h +++ b/src/server.h @@ -36,7 +36,7 @@ struct server { GHashTable *actions; /**< const gchar* => (server_action*) */ GHashTable *setups; /**< const gchar* => (server_setup*) */ - gpointer *option_def_values; /* TODO */ + gpointer *option_def_values; /* TODO: options */ struct action *mainaction; gboolean exiting;