X-Git-Url: http://git.archive.openwrt.org/?a=blobdiff_plain;f=client.c;h=483a1a400f8f38afea6acee1edd53ae414f9f33d;hb=e32b386174cc387d932800145383435083cf948a;hp=9e387c7f4a27b104f2d881ae568a554a564dccaa;hpb=30fff08a44094df9b775f2e4bf9f5abceb847415;p=project%2Fuhttpd.git diff --git a/client.c b/client.c index 9e387c7..483a1a4 100644 --- a/client.c +++ b/client.c @@ -27,12 +27,18 @@ static LIST_HEAD(clients); int n_clients = 0; struct config conf = {}; -static const char *http_versions[] = { +const char * const http_versions[] = { [UH_HTTP_VER_0_9] = "HTTP/0.9", [UH_HTTP_VER_1_0] = "HTTP/1.0", [UH_HTTP_VER_1_1] = "HTTP/1.1", }; +const char * const http_methods[] = { + [UH_HTTP_MSG_GET] = "GET", + [UH_HTTP_MSG_POST] = "POST", + [UH_HTTP_MSG_HEAD] = "HEAD", +}; + void uh_http_header(struct client *cl, int code, const char *summary) { const char *enc = "Transfer-Encoding: chunked\r\n"; @@ -51,12 +57,6 @@ void uh_http_header(struct client *cl, int code, const char *summary) code, summary, conn, enc); } -static void uh_client_error_header(struct client *cl, int code, const char *summary) -{ - uh_http_header(cl, code, summary); - ustream_printf(cl->us, "Content-Type: text/plain\r\n\r\n"); -} - static void uh_connection_close(struct client *cl) { cl->state = CLIENT_STATE_DONE; @@ -66,9 +66,8 @@ static void uh_connection_close(struct client *cl) static void uh_dispatch_done(struct client *cl) { - if (cl->dispatch_free) - cl->dispatch_free(cl); - cl->dispatch_free = NULL; + if (cl->dispatch.free) + cl->dispatch.free(cl); } void uh_request_done(struct client *cl) @@ -76,7 +75,7 @@ void uh_request_done(struct client *cl) uh_chunk_eof(cl); uh_dispatch_done(cl); cl->us->notify_write = NULL; - memset(&cl->data, 0, sizeof(cl->data)); + memset(&cl->dispatch, 0, sizeof(cl->dispatch)); if (cl->request.version != UH_HTTP_VER_1_1 || !conf.http_keepalive) { uh_connection_close(cl); @@ -92,18 +91,23 @@ uh_client_error(struct client *cl, int code, const char *summary, const char *fm { va_list arg; - uh_client_error_header(cl, code, summary); + uh_http_header(cl, code, summary); + ustream_printf(cl->us, "Content-Type: text/html\r\n\r\n"); + + uh_chunk_printf(cl, "

%s

", summary); - va_start(arg, fmt); - uh_chunk_vprintf(cl, fmt, arg); - va_end(arg); + if (fmt) { + va_start(arg, fmt); + uh_chunk_vprintf(cl, fmt, arg); + va_end(arg); + } uh_request_done(cl); } static void uh_header_error(struct client *cl, int code, const char *summary) { - uh_client_error(cl, code, summary, "%s", summary); + uh_client_error(cl, code, summary, NULL); uh_connection_close(cl); } @@ -115,11 +119,21 @@ static void client_timeout(struct uloop_timeout *timeout) uh_connection_close(cl); } +static int find_idx(const char * const *list, int max, const char *str) +{ + int i; + + for (i = 0; i < max; i++) + if (!strcmp(list[i], str)) + return i; + + return -1; +} + static int client_parse_request(struct client *cl, char *data) { struct http_request *req = &cl->request; char *type, *path, *version; - int i; type = strtok(data, " "); path = strtok(NULL, " "); @@ -128,23 +142,11 @@ static int client_parse_request(struct client *cl, char *data) return CLIENT_STATE_DONE; req->url = path; - if (!strcmp(type, "GET")) - req->method = UH_HTTP_MSG_GET; - else if (!strcmp(type, "POST")) - req->method = UH_HTTP_MSG_POST; - else if (!strcmp(type, "HEAD")) - req->method = UH_HTTP_MSG_HEAD; - else + req->method = find_idx(http_methods, ARRAY_SIZE(http_methods), type); + if (req->method < 0) return CLIENT_STATE_DONE; - cl->request.version = -1; - i = array_size(http_versions); - while (i--) { - if (!strcmp(version, http_versions[i])) { - cl->request.version = i; - break; - } - } + req->version = find_idx(http_versions, ARRAY_SIZE(http_versions), version); if (cl->request.version < 0) return CLIENT_STATE_DONE; @@ -172,7 +174,7 @@ static bool client_init_cb(struct client *cl, char *buf, int len) static void client_header_complete(struct client *cl) { - uh_handle_file_request(cl); + uh_handle_request(cl); } static int client_parse_header(struct client *cl, char *data) @@ -186,16 +188,10 @@ static int client_parse_header(struct client *cl, char *data) return CLIENT_STATE_DATA; } - val = strchr(data, ':'); + val = uh_split_header(data); if (!val) return CLIENT_STATE_DONE; - *val = 0; - val++; - - while (isspace(*val)) - val++; - for (name = data; *name; name++) if (isupper(*name)) *name = tolower(*name); @@ -265,6 +261,7 @@ static void client_close(struct client *cl) ustream_free(&cl->sfd.stream); close(cl->sfd.fd.fd); list_del(&cl->list); + blob_buf_free(&cl->hdr); free(cl); uh_unblock_listeners(); @@ -281,8 +278,8 @@ static void client_ustream_write_cb(struct ustream *s, int bytes) { struct client *cl = container_of(s, struct client, sfd); - if (cl->dispatch_write_cb) - cl->dispatch_write_cb(cl); + if (cl->dispatch.write_cb) + cl->dispatch.write_cb(cl); } static void client_notify_state(struct ustream *s) @@ -330,3 +327,16 @@ void uh_accept_client(int fd) n_clients++; cl->id = client_id++; } + +void uh_close_fds(void) +{ + struct client *cl; + + uloop_done(); + uh_close_listen_fds(); + list_for_each_entry(cl, &clients, list) { + close(cl->sfd.fd.fd); + if (cl->dispatch.close_fds) + cl->dispatch.close_fds(cl); + } +}