diff --git a/src/client.c b/src/client.c index f6e31cc..87b0a1a 100644 --- a/src/client.c +++ b/src/client.c @@ -106,7 +106,7 @@ static void client_reset(Client *client) { client->request_offset = 0; client->ts_start = 0; client->ts_end = 0; - client->status_200 = 0; + client->status_success = 0; client->success = 0; client->content_length = -1; client->bytes_received = 0; @@ -259,7 +259,7 @@ void client_state_machine(Client *client) { } } else { /* disconnect */ - if (client->parser_state == PARSER_BODY && !client->keepalive && client->status_200 + if (client->parser_state == PARSER_BODY && !client->keepalive && client->status_success && !client->chunked && client->content_length == -1) { client->success = 1; client->state = CLIENT_END; @@ -314,27 +314,50 @@ void client_state_machine(Client *client) { static uint8_t client_parse(Client *client, int size) { char *end, *str; + uint16_t status_code; switch (client->parser_state) { case PARSER_START: //printf("parse (START):\n%s\n", &client->buffer[client->parser_offset]); /* look for HTTP/1.1 200 OK */ - if (client->buffer_offset < sizeof("HTTP/1.1 200 OK\r\n")) + if (client->buffer_offset < sizeof("HTTP/1.1 200\r\n")) return 1; - if (strncmp(client->buffer, "HTTP/1.1 200 OK\r\n", sizeof("HTTP/1.1 200 OK\r\n")-1) == 0) { - client->status_200 = 1; - client->parser_offset = sizeof("HTTP/1.1 200 ok\r\n") - 1; - } else { - client->status_200 = 0; - end = strchr(client->buffer, '\r'); + if (strncmp(client->buffer, "HTTP/1.1 ", sizeof("HTTP/1.1 ")-1) != 0) + return 0; - if (!end || *(end+1) != '\n') + // now the status code + status_code = 0; + str = client->buffer + sizeof("HTTP/1.1 ")-1; + for (end = str + 3; str != end; str++) { + if (*str < '0' || *str > '9') return 0; - client->parser_offset = end + 2 - client->buffer; + status_code *= 10; + status_code += *str - '0'; } + if (status_code >= 200 && status_code < 300) { + client->worker->stats.req_2xx++; + client->status_success = 1; + } else if (status_code < 400) { + client->worker->stats.req_3xx++; + client->status_success = 1; + } else if (status_code < 500) { + client->worker->stats.req_4xx++; + } else if (status_code < 600) { + client->worker->stats.req_5xx++; + } else { + // invalid status code + return 0; + } + + // look for next \r\n + end = strchr(end, '\r'); + if (!end || *(end+1) != '\n') + return 0; + + client->parser_offset = end + 2 - client->buffer; client->parser_state = PARSER_HEADER; case PARSER_HEADER: //printf("parse (HEADER)\n"); @@ -441,7 +464,7 @@ static uint8_t client_parse(Client *client, int size) { if (client->chunk_size == 0) { /* chunk of size 0 marks end of content body */ client->state = CLIENT_END; - client->success = client->status_200 ? 1 : 0; + client->success = client->status_success ? 1 : 0; return 1; } @@ -490,7 +513,7 @@ static uint8_t client_parse(Client *client, int size) { if (client->bytes_received == (uint64_t) (client->header_size + client->content_length)) { /* full response received */ client->state = CLIENT_END; - client->success = client->status_200 ? 1 : 0; + client->success = client->status_success ? 1 : 0; } } diff --git a/src/client.h b/src/client.h index 54ee5a7..0e387d1 100644 --- a/src/client.h +++ b/src/client.h @@ -33,7 +33,7 @@ struct Client { ev_tstamp ts_end; uint8_t keepalive; uint8_t success; - uint8_t status_200; + uint8_t status_success; uint8_t chunked; int64_t chunk_size; int64_t chunk_received; diff --git a/src/weighttp.c b/src/weighttp.c index 370e9ec..56862ef 100644 --- a/src/weighttp.c +++ b/src/weighttp.c @@ -369,6 +369,10 @@ int main(int argc, char *argv[]) { stats.req_failed += worker->stats.req_failed; stats.bytes_total += worker->stats.bytes_total; stats.bytes_body += worker->stats.bytes_body; + stats.req_2xx += worker->stats.req_2xx; + stats.req_3xx += worker->stats.req_3xx; + stats.req_4xx += worker->stats.req_4xx; + stats.req_5xx += worker->stats.req_5xx; worker_free(worker); } @@ -387,6 +391,9 @@ int main(int argc, char *argv[]) { printf("requests: %"PRIu64" total, %"PRIu64" started, %"PRIu64" done, %"PRIu64" succeeded, %"PRIu64" failed, %"PRIu64" errored\n", config.req_count, stats.req_started, stats.req_done, stats.req_success, stats.req_failed, stats.req_error ); + printf("status codes: %"PRIu64" 2xx, %"PRIu64" 3xx, %"PRIu64" 4xx, %"PRIu64" 5xx\n", + stats.req_2xx, stats.req_3xx, stats.req_4xx, stats.req_5xx + ); printf("traffic: %"PRIu64" bytes total, %"PRIu64" bytes http, %"PRIu64" bytes data\n", stats.bytes_total, stats.bytes_total - stats.bytes_body, stats.bytes_body ); diff --git a/src/worker.c b/src/worker.c index 291981c..fea79a8 100644 --- a/src/worker.c +++ b/src/worker.c @@ -52,7 +52,8 @@ void *worker_thread(void* arg) { /* start all clients */ for (i = 0; i < worker->num_clients; i++) { - client_state_machine(worker->clients[i]); + if (worker->stats.req_started < worker->stats.req_todo) + client_state_machine(worker->clients[i]); } ev_loop(worker->loop, 0); diff --git a/src/worker.h b/src/worker.h index fd6f041..318d325 100644 --- a/src/worker.h +++ b/src/worker.h @@ -20,6 +20,11 @@ struct Stats { uint64_t req_error; /* total number of error'd requests */ uint64_t bytes_total; /* total number of bytes received (html+body) */ uint64_t bytes_body; /* total number of bytes received (body) */ + uint64_t req_1xx; + uint64_t req_2xx; + uint64_t req_3xx; + uint64_t req_4xx; + uint64_t req_5xx; }; struct Worker {