First batch of tests
This commit is contained in:
+81
-65
@@ -70,16 +70,46 @@
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// DEBUG UTILITIES //
|
||||
// UTILITIES //
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if DUMP_IO
|
||||
#include <stdio.h>
|
||||
static void
|
||||
print_bytes(char *prefix, char *src, int len)
|
||||
// TODO: Only allow this when not compiled in stand-alone mode
|
||||
static int print(const char *src, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen(src);
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
int num = 0;
|
||||
while (num < len) {
|
||||
DWORD cpy;
|
||||
if (!WriteFile(handle, src + num, len - num, &cpy, NULL))
|
||||
return -1;
|
||||
num += cpy;
|
||||
}
|
||||
return 0;
|
||||
#elif defined(__linux__)
|
||||
int fd = STDOUT_FILENO;
|
||||
int num = 0;
|
||||
while (num < len) {
|
||||
int ret = write(fd, src + num, len - num);
|
||||
if (ret < 0) {
|
||||
if (ret == EINTR)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
num += ret;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tinyhttp_printbytes(char *prefix, const char *src, int len)
|
||||
{
|
||||
if (src == NULL) {
|
||||
printf("%s (null)\n", prefix);
|
||||
print(prefix, -1);
|
||||
print(" (null)\n", -1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -90,64 +120,57 @@ print_bytes(char *prefix, char *src, int len)
|
||||
while (cur < len && src[cur] != '\n' && src[cur] != '\r')
|
||||
cur++;
|
||||
if (newline) {
|
||||
printf("%s", prefix);
|
||||
print(prefix, -1);
|
||||
newline = 0;
|
||||
}
|
||||
printf("%.*s", cur - start, src + start);
|
||||
print(src + start, cur - start);
|
||||
if (cur < len) {
|
||||
if (src[cur] == '\r')
|
||||
printf("\\r");
|
||||
print("\\r", -1);
|
||||
else {
|
||||
printf("\\n\n");
|
||||
print("\\n\n", -1);
|
||||
newline = 1;
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
if (cur > 0 && src[cur-1] != '\n')
|
||||
printf("\n");
|
||||
print("\n", -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DUMP_IO
|
||||
static void
|
||||
dump_state(int state, const char *file, int line)
|
||||
void tinyhttp_printstate_(int state, const char *file, const char *line)
|
||||
{
|
||||
printf("state = ");
|
||||
print("state = ", -1);
|
||||
if (state & TINYHTTP_STREAM_DIED)
|
||||
printf("DIED ");
|
||||
print("DIED ", -1);
|
||||
|
||||
if (state & TINYHTTP_STREAM_SEND)
|
||||
printf("SEND ");
|
||||
print("SEND ", -1);
|
||||
|
||||
if (state & TINYHTTP_STREAM_RECV)
|
||||
printf("RECV ");
|
||||
print("RECV ", -1);
|
||||
|
||||
if (state & TINYHTTP_STREAM_READY)
|
||||
printf("READY ");
|
||||
print("READY ", -1);
|
||||
|
||||
if (state & TINYHTTP_STREAM_CLOSE)
|
||||
printf("CLOSE ");
|
||||
print("CLOSE ", -1);
|
||||
|
||||
if (state & TINYHTTP_STREAM_REUSE)
|
||||
printf("REUSE ");
|
||||
print("REUSE ", -1);
|
||||
|
||||
if (state & TINYHTTP_STREAM_SEND_STARTED)
|
||||
printf("SEND_STARTED ");
|
||||
print("SEND_STARTED ", -1);
|
||||
|
||||
if (state & TINYHTTP_STREAM_RECV_STARTED)
|
||||
printf("RECV_STARTED ");
|
||||
print("RECV_STARTED ", -1);
|
||||
|
||||
printf(" (in %s:%d)\n", file, line);
|
||||
print(" (in ", -1);
|
||||
print(file, -1);
|
||||
print(":", -1);
|
||||
print(line, -1);
|
||||
print(")\n", -1);
|
||||
}
|
||||
#define DUMP_STATE(state) dump_state(state, __FILE__, __LINE__);
|
||||
#else
|
||||
#define DUMP_STATE(...)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// UTILITIES //
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static char
|
||||
to_lower(char c)
|
||||
@@ -177,6 +200,25 @@ int tinyhttp_streqcase(TinyHTTPString s1, TinyHTTPString s2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static TinyHTTPString trim(TinyHTTPString s)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < s.len && (s.ptr[i] == ' ' || s.ptr[i] == '\t'))
|
||||
i++;
|
||||
|
||||
if (i == s.len) {
|
||||
s.ptr = NULL;
|
||||
s.len = 0;
|
||||
} else {
|
||||
s.ptr += i;
|
||||
s.len -= i;
|
||||
while (s.ptr[s.len-1] == ' ' || s.ptr[s.len-1] == '\n')
|
||||
s.len--;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// HTTP REQUEST PARSER //
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -266,6 +308,7 @@ parse_request_head(char *src, ptrdiff_t len, TinyHTTPRequest *req)
|
||||
while (cur < len && src[cur] != ':') // TODO: robust
|
||||
cur++;
|
||||
TinyHTTPString name = { src + name_off, cur - name_off };
|
||||
name = trim(name);
|
||||
|
||||
if (cur == len)
|
||||
return -400;
|
||||
@@ -275,6 +318,7 @@ parse_request_head(char *src, ptrdiff_t len, TinyHTTPRequest *req)
|
||||
while (cur < len && src[cur] != '\r')
|
||||
cur++;
|
||||
TinyHTTPString value = { src + value_off, cur - value_off };
|
||||
value = trim(value);
|
||||
|
||||
if (cur == len)
|
||||
return -400;
|
||||
@@ -557,7 +601,7 @@ byte_queue_peek(TinyHTTPByteQueue *queue, ptrdiff_t *len)
|
||||
static char*
|
||||
byte_queue_read_buf(TinyHTTPByteQueue *queue, ptrdiff_t *len)
|
||||
{
|
||||
if ((queue->flags & (BYTE_QUEUE_ERROR)) || queue->data == NULL) {
|
||||
if (queue->flags & BYTE_QUEUE_ERROR) {
|
||||
*len = 0;
|
||||
return NULL;
|
||||
}
|
||||
@@ -568,6 +612,8 @@ byte_queue_read_buf(TinyHTTPByteQueue *queue, ptrdiff_t *len)
|
||||
queue->read_target_size = queue->size;
|
||||
|
||||
*len = queue->used;
|
||||
if (queue->data == NULL)
|
||||
return NULL;
|
||||
return queue->data + queue->head;
|
||||
}
|
||||
|
||||
@@ -1399,8 +1445,6 @@ void tinyhttp_stream_response_send(TinyHTTPStream *stream)
|
||||
stream->output_state = TINYHTTP_OUTPUT_STATE_BODY;
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (stream->output_state == TINYHTTP_OUTPUT_STATE_BODY) {
|
||||
if (stream->chunked)
|
||||
byte_queue_write(&stream->out, "0\r\n\r\n");
|
||||
@@ -1427,15 +1471,13 @@ void tinyhttp_stream_response_send(TinyHTTPStream *stream)
|
||||
tmp[9] = '0' + content_length;
|
||||
|
||||
int i = 0;
|
||||
while (i < 8 && tmp[i] == '0')
|
||||
while (i < 9 && tmp[i] == '0')
|
||||
i++;
|
||||
|
||||
byte_queue_patch(&stream->out, stream->content_length_value_offset, tmp + i, 10 - i);
|
||||
}
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (stream->output_state == TINYHTTP_OUTPUT_STATE_ERROR) {
|
||||
byte_queue_remove_after_lock(&stream->out);
|
||||
byte_queue_write(&stream->out,
|
||||
@@ -1446,15 +1488,11 @@ void tinyhttp_stream_response_send(TinyHTTPStream *stream)
|
||||
);
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (byte_queue_error(&stream->out)) {
|
||||
stream->state |= TINYHTTP_STREAM_DIED;
|
||||
return;
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
#if DUMP_IO
|
||||
ptrdiff_t ressize = (byte_queue_offset(&stream->out) - stream->out.lock);
|
||||
print_bytes("R << ", stream->out.data + stream->out.head, ressize);
|
||||
@@ -1464,11 +1502,7 @@ void tinyhttp_stream_response_send(TinyHTTPStream *stream)
|
||||
byte_queue_read_unlock(&stream->out);
|
||||
stream->reqsize = 0;
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
process_next_request(stream);
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
}
|
||||
|
||||
// See tinyhttp.h
|
||||
@@ -2000,8 +2034,6 @@ start_stream_operations(TinyHTTPStream *stream, SOCKET sock,
|
||||
{
|
||||
int state = tinyhttp_stream_state(stream);
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if ((state & TINYHTTP_STREAM_RECV) && !(state & TINYHTTP_STREAM_RECV_STARTED)) {
|
||||
ptrdiff_t cap;
|
||||
char *dst = tinyhttp_stream_recv_buf(stream, &cap);
|
||||
@@ -2014,8 +2046,6 @@ start_stream_operations(TinyHTTPStream *stream, SOCKET sock,
|
||||
#endif
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (state & TINYHTTP_STREAM_SEND && !(state & TINYHTTP_STREAM_SEND_STARTED)) {
|
||||
ptrdiff_t len;
|
||||
char *src = tinyhttp_stream_send_buf(stream, &len);
|
||||
@@ -2028,8 +2058,6 @@ start_stream_operations(TinyHTTPStream *stream, SOCKET sock,
|
||||
#endif
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2064,8 +2092,6 @@ intern_accepted_socket(TinyHTTPServer *server, SOCKET accepted_socket, int secur
|
||||
if (server->num_conns < TINYHTTP_SERVER_CONN_LIMIT * 0.7)
|
||||
tinyhttp_stream_setreuse(stream, 1);
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (CreateIoCompletionPort((HANDLE) accepted_socket, server->iocp, 0, 0) == NULL) {
|
||||
tinyhttp_stream_free(stream);
|
||||
server->stream_sockets[idx] = INVALID_SOCKET;
|
||||
@@ -2082,8 +2108,6 @@ intern_accepted_socket(TinyHTTPServer *server, SOCKET accepted_socket, int secur
|
||||
return;
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (secure) {
|
||||
// TODO
|
||||
}
|
||||
@@ -2186,8 +2210,6 @@ process_network_events(TinyHTTPServer *server, int timeout)
|
||||
|
||||
int old_state = tinyhttp_stream_state(stream);
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (!result) {
|
||||
// A read or write operation failed
|
||||
tinyhttp_stream_kill(stream);
|
||||
@@ -2214,8 +2236,6 @@ process_network_events(TinyHTTPServer *server, int timeout)
|
||||
tinyhttp_stream_kill(stream);
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
int state = tinyhttp_stream_state(stream);
|
||||
|
||||
if ((state & TINYHTTP_STREAM_READY) && (old_state & TINYHTTP_STREAM_READY) == 0) {
|
||||
@@ -2224,8 +2244,6 @@ process_network_events(TinyHTTPServer *server, int timeout)
|
||||
server->ready_count++;
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
if (state & TINYHTTP_STREAM_DIED) {
|
||||
tinyhttp_stream_free(stream);
|
||||
remove_from_ready_queue(server, idx);
|
||||
@@ -2235,8 +2253,6 @@ process_network_events(TinyHTTPServer *server, int timeout)
|
||||
server->num_conns--;
|
||||
}
|
||||
|
||||
DUMP_STATE(tinyhttp_stream_state(stream));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user