mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-06 19:19:16 +00:00
Add performance timing to http server functions
This commit is contained in:
parent
081f7ab8c8
commit
6bf4cf0735
@ -176,8 +176,9 @@ int http_request_set_response_bufsize(struct http_request *r, size_t bufsiz)
|
|||||||
|
|
||||||
void http_request_finalise(struct http_request *r)
|
void http_request_finalise(struct http_request *r)
|
||||||
{
|
{
|
||||||
|
IN();
|
||||||
if (r->phase == DONE)
|
if (r->phase == DONE)
|
||||||
return;
|
RETURNVOID;
|
||||||
assert(r->phase == RECEIVE || r->phase == TRANSMIT || r->phase == PAUSE);
|
assert(r->phase == RECEIVE || r->phase == TRANSMIT || r->phase == PAUSE);
|
||||||
unschedule(&r->alarm);
|
unschedule(&r->alarm);
|
||||||
if (r->phase != PAUSE)
|
if (r->phase != PAUSE)
|
||||||
@ -189,6 +190,7 @@ void http_request_finalise(struct http_request *r)
|
|||||||
r->finalise = NULL;
|
r->finalise = NULL;
|
||||||
http_request_free_response_buffer(r);
|
http_request_free_response_buffer(r);
|
||||||
r->phase = DONE;
|
r->phase = DONE;
|
||||||
|
OUT();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct substring {
|
struct substring {
|
||||||
@ -1506,6 +1508,7 @@ static ssize_t http_request_read(struct http_request *r, char *buf, size_t len)
|
|||||||
|
|
||||||
static void http_request_receive(struct http_request *r)
|
static void http_request_receive(struct http_request *r)
|
||||||
{
|
{
|
||||||
|
IN();
|
||||||
assert(r->phase == RECEIVE);
|
assert(r->phase == RECEIVE);
|
||||||
const char *const bufend = r->buffer + sizeof r->buffer;
|
const char *const bufend = r->buffer + sizeof r->buffer;
|
||||||
assert(r->end <= bufend);
|
assert(r->end <= bufend);
|
||||||
@ -1534,7 +1537,7 @@ static void http_request_receive(struct http_request *r)
|
|||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
DEBUG("Buffer size reached, reporting overflow");
|
DEBUG("Buffer size reached, reporting overflow");
|
||||||
http_request_simple_response(r, 431, NULL);
|
http_request_simple_response(r, 431, NULL);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
// Read up to the end of available buffer space or the end of content, whichever is first. Read
|
// Read up to the end of available buffer space or the end of content, whichever is first. Read
|
||||||
// as many bytes as possible into the unused buffer space. Any read error closes the connection
|
// as many bytes as possible into the unused buffer space. Any read error closes the connection
|
||||||
@ -1544,13 +1547,13 @@ static void http_request_receive(struct http_request *r)
|
|||||||
assert(room <= r->request_content_remaining);
|
assert(room <= r->request_content_remaining);
|
||||||
ssize_t bytes = http_request_read(r, (char *)r->end, room);
|
ssize_t bytes = http_request_read(r, (char *)r->end, room);
|
||||||
if (bytes == -1)
|
if (bytes == -1)
|
||||||
return;
|
RETURNVOID;
|
||||||
assert((size_t) bytes <= room);
|
assert((size_t) bytes <= room);
|
||||||
// If no data was read, then just return to polling. Don't drop the connection on an empty read,
|
// If no data was read, then just return to polling. Don't drop the connection on an empty read,
|
||||||
// because that drops connections when they shouldn't, including during testing. The inactivity
|
// because that drops connections when they shouldn't, including during testing. The inactivity
|
||||||
// timeout will drop inactive connections.
|
// timeout will drop inactive connections.
|
||||||
if (bytes == 0)
|
if (bytes == 0)
|
||||||
return;
|
RETURNVOID;
|
||||||
r->end += (size_t) bytes;
|
r->end += (size_t) bytes;
|
||||||
if (r->request_content_remaining != CONTENT_LENGTH_UNKNOWN)
|
if (r->request_content_remaining != CONTENT_LENGTH_UNKNOWN)
|
||||||
r->request_content_remaining -= (size_t) bytes;
|
r->request_content_remaining -= (size_t) bytes;
|
||||||
@ -1586,7 +1589,7 @@ static void http_request_receive(struct http_request *r)
|
|||||||
if (r->phase != RECEIVE)
|
if (r->phase != RECEIVE)
|
||||||
break;
|
break;
|
||||||
if (result == 100)
|
if (result == 100)
|
||||||
return; // needs more data; poll again
|
RETURNVOID; // needs more data; poll again
|
||||||
if (result == 0 && r->parsed == oldparsed && r->parser == oldparser) {
|
if (result == 0 && r->parsed == oldparsed && r->parser == oldparser) {
|
||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
DEBUG("Internal failure parsing HTTP request: parser function did not advance");
|
DEBUG("Internal failure parsing HTTP request: parser function did not advance");
|
||||||
@ -1608,18 +1611,19 @@ static void http_request_receive(struct http_request *r)
|
|||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
DEBUG("Unrecoverable error parsing HTTP request, closing connection");
|
DEBUG("Unrecoverable error parsing HTTP request, closing connection");
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r->phase != RECEIVE) {
|
if (r->phase != RECEIVE) {
|
||||||
assert(r->response.result_code != 0);
|
assert(r->response.result_code != 0);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
if (r->response.result_code == 0) {
|
if (r->response.result_code == 0) {
|
||||||
WHY("No HTTP response set, using 500 Server Error");
|
WHY("No HTTP response set, using 500 Server Error");
|
||||||
r->response.result_code = 500;
|
r->response.result_code = 500;
|
||||||
}
|
}
|
||||||
http_request_start_response(r);
|
http_request_start_response(r);
|
||||||
|
OUT();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the current contents of the response buffer to the HTTP socket. When no more bytes can be
|
/* Write the current contents of the response buffer to the HTTP socket. When no more bytes can be
|
||||||
@ -1631,6 +1635,7 @@ static void http_request_receive(struct http_request *r)
|
|||||||
*/
|
*/
|
||||||
static void http_request_send_response(struct http_request *r)
|
static void http_request_send_response(struct http_request *r)
|
||||||
{
|
{
|
||||||
|
IN();
|
||||||
assert(r->phase == TRANSMIT);
|
assert(r->phase == TRANSMIT);
|
||||||
while (1) {
|
while (1) {
|
||||||
if (r->response_length != CONTENT_LENGTH_UNKNOWN)
|
if (r->response_length != CONTENT_LENGTH_UNKNOWN)
|
||||||
@ -1651,7 +1656,7 @@ static void http_request_send_response(struct http_request *r)
|
|||||||
r->response_buffer_sent = r->response_buffer_length = 0;
|
r->response_buffer_sent = r->response_buffer_length = 0;
|
||||||
if (r->phase == PAUSE) {
|
if (r->phase == PAUSE) {
|
||||||
if (unsent == 0)
|
if (unsent == 0)
|
||||||
return; // nothing to send
|
RETURNVOID; // nothing to send
|
||||||
} else if (r->response.content_generator) {
|
} else if (r->response.content_generator) {
|
||||||
// If the buffer is smaller than the content generator needs, and it contains no unsent
|
// If the buffer is smaller than the content generator needs, and it contains no unsent
|
||||||
// content, then allocate a larger buffer.
|
// content, then allocate a larger buffer.
|
||||||
@ -1660,7 +1665,7 @@ static void http_request_send_response(struct http_request *r)
|
|||||||
WHYF("HTTP response truncated at offset=%"PRIhttp_size_t" due to insufficient buffer space",
|
WHYF("HTTP response truncated at offset=%"PRIhttp_size_t" due to insufficient buffer space",
|
||||||
r->response_sent);
|
r->response_sent);
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If there are some sent bytes at the start of the buffer and only a few unsent bytes, then
|
// If there are some sent bytes at the start of the buffer and only a few unsent bytes, then
|
||||||
@ -1687,7 +1692,7 @@ static void http_request_send_response(struct http_request *r)
|
|||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
WHY("Content generation error, closing connection");
|
WHY("Content generation error, closing connection");
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
assert(result.generated <= unfilled);
|
assert(result.generated <= unfilled);
|
||||||
r->response_buffer_length += result.generated;
|
r->response_buffer_length += result.generated;
|
||||||
@ -1695,7 +1700,7 @@ static void http_request_send_response(struct http_request *r)
|
|||||||
if (result.generated == 0 && result.need <= unfilled && r->phase != PAUSE) {
|
if (result.generated == 0 && result.need <= unfilled && r->phase != PAUSE) {
|
||||||
WHYF("HTTP response generator produced no content at offset %"PRIhttp_size_t" (ret=%d)", r->response_sent, ret);
|
WHYF("HTTP response generator produced no content at offset %"PRIhttp_size_t" (ret=%d)", r->response_sent, ret);
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
DEBUGF("Generated HTTP %zu bytes of content, need %zu bytes of buffer (ret=%d)", result.generated, result.need, ret);
|
DEBUGF("Generated HTTP %zu bytes of content, need %zu bytes of buffer (ret=%d)", result.generated, result.need, ret);
|
||||||
@ -1707,7 +1712,7 @@ static void http_request_send_response(struct http_request *r)
|
|||||||
WHYF("HTTP response generator finished prematurely at offset %"PRIhttp_size_t"/%"PRIhttp_size_t" (%"PRIhttp_size_t" bytes remaining)",
|
WHYF("HTTP response generator finished prematurely at offset %"PRIhttp_size_t"/%"PRIhttp_size_t" (%"PRIhttp_size_t" bytes remaining)",
|
||||||
r->response_sent, r->response_length, remaining);
|
r->response_sent, r->response_length, remaining);
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
} else if (unsent == 0)
|
} else if (unsent == 0)
|
||||||
break;
|
break;
|
||||||
assert(unsent > 0);
|
assert(unsent > 0);
|
||||||
@ -1722,17 +1727,17 @@ static void http_request_send_response(struct http_request *r)
|
|||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
DEBUG("HTTP socket write error, closing connection");
|
DEBUG("HTTP socket write error, closing connection");
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
if (sigPipeFlag) {
|
if (sigPipeFlag) {
|
||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
DEBUG("Received SIGPIPE on HTTP socket write, closing connection");
|
DEBUG("Received SIGPIPE on HTTP socket write, closing connection");
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
// If we wrote nothing, go back to polling.
|
// If we wrote nothing, go back to polling.
|
||||||
if (written == 0)
|
if (written == 0)
|
||||||
return;
|
RETURNVOID;
|
||||||
r->response_sent += (size_t) written;
|
r->response_sent += (size_t) written;
|
||||||
r->response_buffer_sent += (size_t) written;
|
r->response_buffer_sent += (size_t) written;
|
||||||
assert(r->response_sent <= r->response_length);
|
assert(r->response_sent <= r->response_length);
|
||||||
@ -1745,11 +1750,12 @@ static void http_request_send_response(struct http_request *r)
|
|||||||
http_request_set_idle_timeout(r);
|
http_request_set_idle_timeout(r);
|
||||||
// If we wrote less than we tried, then go back to polling, otherwise keep generating content.
|
// If we wrote less than we tried, then go back to polling, otherwise keep generating content.
|
||||||
if ((size_t) written < (size_t) unsent)
|
if ((size_t) written < (size_t) unsent)
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
if (r->debug_flag && *r->debug_flag)
|
if (r->debug_flag && *r->debug_flag)
|
||||||
DEBUG("Done, closing connection");
|
DEBUG("Done, closing connection");
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
|
OUT();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void http_server_poll(struct sched_ent *alarm)
|
static void http_server_poll(struct sched_ent *alarm)
|
||||||
@ -2084,6 +2090,7 @@ static size_t http_request_drain(struct http_request *r)
|
|||||||
|
|
||||||
static void http_request_start_response(struct http_request *r)
|
static void http_request_start_response(struct http_request *r)
|
||||||
{
|
{
|
||||||
|
IN();
|
||||||
assert(r->phase == RECEIVE);
|
assert(r->phase == RECEIVE);
|
||||||
_release_reserved(r);
|
_release_reserved(r);
|
||||||
if (r->response.content || r->response.content_generator) {
|
if (r->response.content || r->response.content_generator) {
|
||||||
@ -2095,14 +2102,14 @@ static void http_request_start_response(struct http_request *r)
|
|||||||
if (r->disable_tx_flag && *r->disable_tx_flag) {
|
if (r->disable_tx_flag && *r->disable_tx_flag) {
|
||||||
INFO("HTTP transmit disabled, closing connection");
|
INFO("HTTP transmit disabled, closing connection");
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
// Drain the rest of the request that has not been received yet (eg, if sending an error response
|
// Drain the rest of the request that has not been received yet (eg, if sending an error response
|
||||||
// provoked while parsing the early part of a partially-received request). If a read error
|
// provoked while parsing the early part of a partially-received request). If a read error
|
||||||
// occurs, the connection is closed so the phase changes to DONE.
|
// occurs, the connection is closed so the phase changes to DONE.
|
||||||
http_request_drain(r);
|
http_request_drain(r);
|
||||||
if (r->phase != RECEIVE)
|
if (r->phase != RECEIVE)
|
||||||
return;
|
RETURNVOID;
|
||||||
// Ensure conformance to HTTP standards.
|
// Ensure conformance to HTTP standards.
|
||||||
if (r->response.result_code == 401 && r->response.header.www_authenticate.scheme == NOAUTH) {
|
if (r->response.result_code == 401 && r->response.header.www_authenticate.scheme == NOAUTH) {
|
||||||
WHY("HTTP 401 response missing WWW-Authenticate header, sending 500 Server Error instead");
|
WHY("HTTP 401 response missing WWW-Authenticate header, sending 500 Server Error instead");
|
||||||
@ -2122,7 +2129,7 @@ static void http_request_start_response(struct http_request *r)
|
|||||||
if (r->response_buffer == NULL) {
|
if (r->response_buffer == NULL) {
|
||||||
WHY("Cannot render HTTP 500 Server Error response, closing connection");
|
WHY("Cannot render HTTP 500 Server Error response, closing connection");
|
||||||
http_request_finalise(r);
|
http_request_finalise(r);
|
||||||
return;
|
RETURNVOID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r->response_buffer_need = 0;
|
r->response_buffer_need = 0;
|
||||||
@ -2132,6 +2139,7 @@ static void http_request_start_response(struct http_request *r)
|
|||||||
r->phase = TRANSMIT;
|
r->phase = TRANSMIT;
|
||||||
r->alarm.poll.events = POLLOUT;
|
r->alarm.poll.events = POLLOUT;
|
||||||
watch(&r->alarm);
|
watch(&r->alarm);
|
||||||
|
OUT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_request_pause_response(struct http_request *r, time_ms_t until)
|
void http_request_pause_response(struct http_request *r, time_ms_t until)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user