From 5ff5a02bb9eedf6a372fe7bc791b5288294e9874 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Fri, 25 Oct 2013 23:57:23 +1030 Subject: [PATCH] Fix a couple more bugs in new HTTP server code --- http_server.c | 26 ++++++++++++++++++++------ http_server.h | 7 +++++-- rhizome_direct_http.c | 4 ++-- rhizome_http.c | 15 +++++++-------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/http_server.c b/http_server.c index 4786ecd2..60877899 100644 --- a/http_server.c +++ b/http_server.c @@ -1590,18 +1590,18 @@ static void http_request_start_response(struct http_request *r) watch(&r->alarm); } -/* Start sending a response back to the client. The response's Content-Type is set by the - * 'mime_type' parameter (in the standard format "type/subtype"). The response's content is set - * from the 'body' and 'bytes' parameters, which need not point to static data, ie, is no longer - * used once this function returns. +/* Start sending a static (pre-computed) response back to the client. The response's Content-Type + * is set by the 'mime_type' parameter (in the standard format "type/subtype"). The response's + * content is set from the 'body' and 'bytes' parameters, which need not point to persistent data, + * ie, the memory pointed to by 'body' is no longer referenced once this function returns. * * @author Andrew Bettison */ -void http_request_response(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes) +void http_request_response_static(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes) { assert(r->phase == RECEIVE); assert(result >= 100); - assert(result < 600); + assert(result < 300); assert(mime_type != NULL); assert(mime_type[0]); r->response.result_code = result; @@ -1613,6 +1613,20 @@ void http_request_response(struct http_request *r, int result, const char *mime_ http_request_start_response(r); } +void http_request_response_generated(struct http_request *r, int result, const char *mime_type, HTTP_CONTENT_GENERATOR generator) +{ + assert(r->phase == RECEIVE); + assert(result >= 100); + assert(result < 300); + assert(mime_type != NULL); + assert(mime_type[0]); + r->response.result_code = result; + r->response.header.content_type = mime_type; + r->response.content = NULL; + r->response.content_generator = generator; + http_request_start_response(r); +} + /* Start sending a short redirection or error response back to the client. The result code must be * either a redirection (3xx) or client error (4xx) or server error (5xx) code. The 'body' argument * may be a bare message which is enclosed in an HTML envelope to form the response content, so it diff --git a/http_server.h b/http_server.h index 5a73e6ce..ebedb0ad 100644 --- a/http_server.h +++ b/http_server.h @@ -73,11 +73,13 @@ struct http_response_headers { const char *boundary; }; +typedef int (*HTTP_CONTENT_GENERATOR)(struct http_request *); + struct http_response { uint16_t result_code; struct http_response_headers header; const char *content; - int (*content_generator)(struct http_request *); // callback to produce more content + HTTP_CONTENT_GENERATOR content_generator; // callback to produce more content }; #define MIME_FILENAME_MAXLEN 127 @@ -108,7 +110,8 @@ void http_request_init(struct http_request *r, int sockfd); void http_request_free_response_buffer(struct http_request *r); int http_request_set_response_bufsize(struct http_request *r, size_t bufsiz); void http_request_finalise(struct http_request *r); -void http_request_response(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes); +void http_request_response_static(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes); +void http_request_response_generated(struct http_request *r, int result, const char *mime_type, HTTP_CONTENT_GENERATOR); void http_request_simple_response(struct http_request *r, uint16_t result, const char *body); typedef int (*HTTP_REQUEST_PARSER)(struct http_request *); diff --git a/rhizome_direct_http.c b/rhizome_direct_http.c index b8d6125a..90bce08a 100644 --- a/rhizome_direct_http.c +++ b/rhizome_direct_http.c @@ -160,7 +160,7 @@ int rhizome_direct_enquiry_end(struct http_request *hr) if (http_request_set_response_bufsize(&r->http, bytes) == -1) http_request_simple_response(&r->http, 500, "Internal Error: Out of memory"); else - http_request_response(&r->http, 200, "binary/octet-stream", (const char *)c->buffer, bytes); + http_request_response_static(&r->http, 200, "binary/octet-stream", (const char *)c->buffer, bytes); rhizome_direct_bundle_iterator_free(&c); } else http_request_simple_response(&r->http, 500, "Internal Error: No response to enquiry"); @@ -258,7 +258,7 @@ int rhizome_direct_addfile_end(struct http_request *hr) if (config.debug.rhizome) DEBUGF("Import sans-manifest appeared to succeed"); /* Respond with the manifest that was added. */ - http_request_response(&r->http, 200, "text/plain", (const char *)m->manifestdata, m->manifest_bytes); + http_request_response_static(&r->http, 200, "text/plain", (const char *)m->manifestdata, m->manifest_bytes); /* clean up after ourselves */ if (mout && mout != m) rhizome_manifest_free(mout); diff --git a/rhizome_http.c b/rhizome_http.c index 6807d45b..b0c04668 100644 --- a/rhizome_http.c +++ b/rhizome_http.c @@ -331,7 +331,7 @@ static int neighbour_page(rhizome_http_request *r, const char *remainder) strbuf_puts(b, ""); if (strbuf_overrun(b)) return -1; - http_request_response(&r->http, 200, "text/html", buf, strbuf_len(b)); + http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b)); return 0; } @@ -351,7 +351,7 @@ static int interface_page(rhizome_http_request *r, const char *remainder) strbuf_puts(b, ""); if (strbuf_overrun(b)) return -1; - http_request_response(&r->http, 200, "text/html", buf, strbuf_len(b)); + http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b)); return 0; } @@ -374,7 +374,7 @@ static int rhizome_status_page(rhizome_http_request *r, const char *remainder) strbuf_puts(b, ""); if (strbuf_overrun(b)) return -1; - http_request_response(&r->http, 200, "text/html", buf, strbuf_len(b)); + http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b)); return 0; } @@ -455,8 +455,7 @@ static int rhizome_file_page(rhizome_http_request *r, const char *remainder) r->http.response.header.resource_length = closed.last; r->http.response.header.content_length = closed.last - closed.first; r->read_state.offset = closed.first; - r->http.response.content_generator = rhizome_file_content; - http_request_response(&r->http, result_code, "application/binary", NULL, 0); + http_request_response_generated(&r->http, result_code, "application/binary", rhizome_file_content); return 0; } @@ -478,7 +477,7 @@ static int manifest_by_prefix_page(rhizome_http_request *r, const char *remainde if (ret == -1) http_request_simple_response(&r->http, 500, NULL); else if (ret == 0) - http_request_response(&r->http, 200, "application/binary", (const char *)m->manifestdata, m->manifest_all_bytes); + http_request_response_static(&r->http, 200, "application/binary", (const char *)m->manifestdata, m->manifest_all_bytes); rhizome_manifest_free(m); return ret <= 0 ? 0 : 1; } @@ -487,7 +486,7 @@ static int fav_icon_header(rhizome_http_request *r, const char *remainder) { if (*remainder) return 1; - http_request_response(&r->http, 200, "image/vnd.microsoft.icon", (const char *)favicon_bytes, favicon_len); + http_request_response_static(&r->http, 200, "image/vnd.microsoft.icon", (const char *)favicon_bytes, favicon_len); return 0; } @@ -521,6 +520,6 @@ static int root_page(rhizome_http_request *r, const char *remainder) WHY("HTTP Root page buffer overrun"); http_request_simple_response(&r->http, 500, NULL); } else - http_request_response(&r->http, 200, "text/html", temp, strbuf_len(b)); + http_request_response_static(&r->http, 200, "text/html", temp, strbuf_len(b)); return 0; }