Improve testing program
This commit is contained in:
@@ -13,7 +13,7 @@ SUFFIX_DEBUG = _debug
|
|||||||
|
|
||||||
# ------------------------------------------------------ #
|
# ------------------------------------------------------ #
|
||||||
|
|
||||||
TEST_CFILES = tinyhttp.c tests/picohttpparser.c tests/test.c tests/test_reuse.c tests/test_chunking.c
|
TEST_CFILES = tinyhttp.c tests/picohttpparser.c tests/test.c tests/test_reuse.c tests/test_chunking.c tests/test_parse_request.c
|
||||||
TEST_HFILES = tinyhttp.h tests/picohttpparser.h
|
TEST_HFILES = tinyhttp.h tests/picohttpparser.h
|
||||||
|
|
||||||
TEST_FLAGS = -Wall -Wextra
|
TEST_FLAGS = -Wall -Wextra
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ TinyHTTP is a C library for implementing web servers. It offers two interfaces:
|
|||||||
1. stream interface
|
1. stream interface
|
||||||
1. server interface
|
1. server interface
|
||||||
|
|
||||||
The stream interface is a lower level interface to TinyHTTP's HTTP state machine. It's completely stand-alone and performs no internal I/O, making it ideal for embedding in applications with custom constraints.
|
The stream interface is a lower level interface to TinyHTTP's HTTP state machine. It's completely stand-alone and performs no internal I/O, making it ideal for embedding in applications with custom constraints. The only dependency are freestanding libc headers.
|
||||||
|
|
||||||
The server interface is based on the stream interface and adds to it a platform-dependant I/O system. It uses the most performant I/O model the platform it's compiled for, but is single-threaded. The design goal of the server interface is ease of use and reasonable performance.
|
The server interface is based on the stream interface and adds to it a platform-dependant I/O system. It uses the most performant I/O model available on the platform it's compiled for, but is single-threaded. The design goal of the server interface is ease of use and reasonable performance. It does also depend on libc.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,271 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "../tinyhttp.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// CONFIGURATION
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Network stuff
|
||||||
|
#define ADDR "127.0.0.1"
|
||||||
|
#define PORT 8080
|
||||||
|
#define REUSE 1
|
||||||
|
#define BACKLOG 32
|
||||||
|
|
||||||
|
// Social stuff
|
||||||
|
#define MAX_USERS 32
|
||||||
|
#define MAX_POSTS 32
|
||||||
|
#define MAX_USERNAME 128
|
||||||
|
#define MAX_PASSWORD 256
|
||||||
|
#define MAX_BIO 512
|
||||||
|
#define MAX_CONTENT 512
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// UTILITIES
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *ptr;
|
||||||
|
ptrdiff_t len;
|
||||||
|
} string;
|
||||||
|
|
||||||
|
#define S(X) ((string) {(X), sizeof(X)-1})
|
||||||
|
|
||||||
|
static string trim(string 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int copy(string src, string *dst, char *mem, int cap)
|
||||||
|
{
|
||||||
|
if (src.len > cap)
|
||||||
|
return -1;
|
||||||
|
memcpy(mem, src.ptr, src.len);
|
||||||
|
dst->ptr = mem;
|
||||||
|
dst->len = src.len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// BUSINESS LOGIC
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
string name;
|
||||||
|
string pass;
|
||||||
|
string bio;
|
||||||
|
char name_mem[MAX_USERNAME];
|
||||||
|
char pass_mem[MAX_PASSWORD];
|
||||||
|
char bio_mem[MAX_BIO];
|
||||||
|
} User;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int id;
|
||||||
|
string author;
|
||||||
|
string content;
|
||||||
|
char author_mem[MAX_USERNAME];
|
||||||
|
char content_mem[MAX_CONTENT];
|
||||||
|
} Post;
|
||||||
|
|
||||||
|
static User users[MAX_USERS];
|
||||||
|
static int user_count = 0;
|
||||||
|
|
||||||
|
static Post posts[MAX_POSTS];
|
||||||
|
static int posts_head = 0;
|
||||||
|
static int posts_count = 0;
|
||||||
|
|
||||||
|
static void init_users_and_posts(void)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_user(string name)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < user_count; i++)
|
||||||
|
if (streq(name, users[i].name))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_user(string name, string pass)
|
||||||
|
{
|
||||||
|
name = trim(name);
|
||||||
|
pass = trim(pass);
|
||||||
|
|
||||||
|
if (name.len == 0 || pass.len == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (find_user(name) != -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (user_count == MAX_USERS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
User *user = &users[user_count];
|
||||||
|
|
||||||
|
if (copy(name, &user->name, user->name_mem, sizeof(user->name_mem)) < 0 &&
|
||||||
|
copy(pass, &user->pass, user->pass_mem, sizeof(user->pass_mem)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
user_count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int delete_user(string name)
|
||||||
|
{
|
||||||
|
int i = find_user(name);
|
||||||
|
if (i == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_post(string author, string content)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static int delete_post(int id)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static int modify_post(int id, string new_content)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// ENDPOINTS
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define MAX_SESSIONS 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int id;
|
||||||
|
string name;
|
||||||
|
char name_mem[MAX_USERNAME];
|
||||||
|
} Session;
|
||||||
|
|
||||||
|
static Session sessions[MAX_SESSIONS];
|
||||||
|
static int session_count = 0;
|
||||||
|
|
||||||
|
static void init_sessions(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_SESSIONS; i++)
|
||||||
|
sessions[i].id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_session(int id)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_SESSIONS; i++)
|
||||||
|
if (sessions[i].id == id)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_session(string name)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
static int delete_session(string name)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// ENTRY POINT
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static sig_atomic_t should_exit = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler(int sig)
|
||||||
|
{
|
||||||
|
if (sig == SIGINT)
|
||||||
|
should_exit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
signal(SIGINT, signal_handler);
|
||||||
|
|
||||||
|
init_users_and_posts();
|
||||||
|
init_sessions();
|
||||||
|
|
||||||
|
TinyHTTPServerConfig config = {
|
||||||
|
.reuse = REUSE,
|
||||||
|
.plain_addr = ADDR,
|
||||||
|
.plain_port = PORT,
|
||||||
|
.plain_backlog = BACKLOG,
|
||||||
|
};
|
||||||
|
|
||||||
|
TinyHTTPServer *server = tinyhttp_server_init(config);
|
||||||
|
if (server == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (!should_exit) {
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
TinyHTTPRequest *req;
|
||||||
|
TinyHTTPResponse res;
|
||||||
|
|
||||||
|
ret = tinyhttp_server_wait(server, &req, &res, 1000);
|
||||||
|
if (ret < 0) return -1; // Error
|
||||||
|
if (ret > 0) continue; // Timeout
|
||||||
|
|
||||||
|
char path_mem[1<<10];
|
||||||
|
TinyHTTPString path;
|
||||||
|
if (tinyhttp_normalizepath(req->path, &path, path_mem, sizeof(path_mem)) < 0) {
|
||||||
|
tinyhttp_response_status(res, 200);
|
||||||
|
tinyhttp_response_send(res);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TinyHTTPString sessid = tinyhttp_getcookie(req, TINYHTTP_STRING("sessid"));
|
||||||
|
|
||||||
|
if (tinyhttp_streq(path, TINYHTTP_STRING("/users"))) {
|
||||||
|
tinyhttp_response_status(res, 200);
|
||||||
|
tinyhttp_response_body(res, "<html><head><title>Users</title></head><body><ul>", -1);
|
||||||
|
for (int i = 0; i < user_count; i++)
|
||||||
|
tinyhttp_response_body(res, "<li><a href=\"/users/???\">???</a></li>", -1);
|
||||||
|
tinyhttp_response_body(res, "</ul></body></html>", -1);
|
||||||
|
tinyhttp_response_send(res);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tinyhttp_streq(path, TINYHTTP_STRING("/posts"))) {
|
||||||
|
tinyhttp_response_status(res, 200);
|
||||||
|
tinyhttp_response_body(res, "<html><head><title>Posts</title></head><body><ul>", -1);
|
||||||
|
for (int i = 0; i < user_count; i++)
|
||||||
|
tinyhttp_response_body(res, "<li><a href=\"/posts/???\">???</a></li>", -1);
|
||||||
|
tinyhttp_response_body(res, "</ul></body></html>", -1);
|
||||||
|
tinyhttp_response_send(res);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyhttp_response_status(res, 404);
|
||||||
|
tinyhttp_response_body(res, "<html><head><title>Not Found</title></head><body>Nothing here!</body></html>", -1);
|
||||||
|
tinyhttp_response_send(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyhttp_server_free(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
table = [
|
||||||
|
(1<<6, "DIED"),
|
||||||
|
(1<<5, "RECV"),
|
||||||
|
(1<<4, "SEND"),
|
||||||
|
(1<<3, "RECV_STARTED"),
|
||||||
|
(1<<2, "SEND_STARTED"),
|
||||||
|
(1<<1, "READY"),
|
||||||
|
(1<<0, "CLOSE"),
|
||||||
|
]
|
||||||
|
|
||||||
|
outstates = [
|
||||||
|
"STATUS",
|
||||||
|
"HEADER",
|
||||||
|
"BODY",
|
||||||
|
]
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
k = 0
|
||||||
|
while i < 2**len(table):
|
||||||
|
|
||||||
|
tags = []
|
||||||
|
for entry in table:
|
||||||
|
if i & entry[0]:
|
||||||
|
tags.append(entry[1])
|
||||||
|
|
||||||
|
statestr = "|".join(tags)
|
||||||
|
|
||||||
|
if ("DIED" in tags) and ("READY" in tags):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ("READY" not in tags) and ("DIED" not in tags) and ("SEND" not in tags) and ("RECV" not in tags):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ("READY" in tags) and ("CLOSE" in tags):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ("CLOSE" in tags) and ("SEND" not in tags):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (("CLOSE" in tags) or ("READY" in tags)) and (("RECV" in tags)):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ("DIED" in tags) and (("RECV" in tags) or ("SEND" in tags)):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ("SEND_STARTED" in tags) and ("SEND" not in tags) and ("DIED" not in tags):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ("RECV_STARTED" in tags) and ("RECV" not in tags) and ("DIED" not in tags):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if "READY" in tags:
|
||||||
|
for outstate in outstates:
|
||||||
|
print(k, statestr + "|" + outstate)
|
||||||
|
k += 1
|
||||||
|
else:
|
||||||
|
print(k, statestr)
|
||||||
|
k += 1
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
"""
|
||||||
|
Constraints:
|
||||||
|
- STATUS/HEADER/BODY only when READY
|
||||||
|
"""
|
||||||
+38
-18
@@ -144,6 +144,7 @@ int main(void)
|
|||||||
test_basic_exchange();
|
test_basic_exchange();
|
||||||
test_reuse();
|
test_reuse();
|
||||||
test_chunking();
|
test_chunking();
|
||||||
|
test_parse_request();
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -227,6 +228,41 @@ stream_into_buffer(TinyHTTPStream *stream, char *dst, int cap)
|
|||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int match_request(TinyHTTPRequest *r1, TinyHTTPRequest *r2)
|
||||||
|
{
|
||||||
|
if (r1->method != r2->method)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (r1->minor != r2->minor)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!tinyhttp_streq(r1->path, r2->path))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (r1->num_headers != r2->num_headers)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < r2->num_headers; i++) {
|
||||||
|
if (!tinyhttp_streq(r1->headers[i].name, r2->headers[i].name))
|
||||||
|
return 0;
|
||||||
|
if (!tinyhttp_streq(r1->headers[i].value, r2->headers[i].value))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r1->body_len != r2->body_len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (r2->body_len == 0) {
|
||||||
|
if (r1->body != NULL)
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (memcmp(r1->body, r2->body, r2->body_len))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expect_request(TinyHTTPStream *stream, TinyHTTPRequest expreq)
|
expect_request(TinyHTTPStream *stream, TinyHTTPRequest expreq)
|
||||||
{
|
{
|
||||||
@@ -235,26 +271,10 @@ expect_request(TinyHTTPStream *stream, TinyHTTPRequest expreq)
|
|||||||
|
|
||||||
TinyHTTPRequest *req = tinyhttp_stream_request(stream);
|
TinyHTTPRequest *req = tinyhttp_stream_request(stream);
|
||||||
TEST(req);
|
TEST(req);
|
||||||
|
TEST(match_request(req, &expreq));
|
||||||
TEST(req->method == expreq.method);
|
|
||||||
TEST(req->minor == expreq.minor);
|
|
||||||
TEST(tinyhttp_streq(req->path, expreq.path));
|
|
||||||
TEST(req->num_headers == expreq.num_headers);
|
|
||||||
for (int i = 0; i < expreq.num_headers; i++) {
|
|
||||||
TEST(tinyhttp_streq(req->headers[i].name, expreq.headers[i].name));
|
|
||||||
TEST(tinyhttp_streq(req->headers[i].value, expreq.headers[i].value));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(req->body_len == expreq.body_len);
|
|
||||||
if (expreq.body_len == 0) {
|
|
||||||
TEST(req->body == NULL);
|
|
||||||
} else {
|
|
||||||
TEST(!memcmp(req->body, expreq.body, expreq.body_len));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int parse_request(TinyHTTPString txt, TinyHTTPRequest *req, char *buf, int max)
|
||||||
parse_request(TinyHTTPString txt, TinyHTTPRequest *req, char *buf, int max)
|
|
||||||
{
|
{
|
||||||
const char *method;
|
const char *method;
|
||||||
size_t method_len;
|
size_t method_len;
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ void send_request(TinyHTTPStream *stream, const char *str);
|
|||||||
// "res".
|
// "res".
|
||||||
void recv_response(TinyHTTPStream *stream, Response *res, char *dst, int cap);
|
void recv_response(TinyHTTPStream *stream, Response *res, char *dst, int cap);
|
||||||
|
|
||||||
|
int parse_request(TinyHTTPString txt, TinyHTTPRequest *req, char *buf, int max);
|
||||||
|
|
||||||
|
int match_request(TinyHTTPRequest *r1, TinyHTTPRequest *r2);
|
||||||
|
|
||||||
int header_exists(Response *res, TinyHTTPString name);
|
int header_exists(Response *res, TinyHTTPString name);
|
||||||
int header_exists_with_value(Response *res, TinyHTTPString name, TinyHTTPString value);
|
int header_exists_with_value(Response *res, TinyHTTPString name, TinyHTTPString value);
|
||||||
|
|
||||||
@@ -40,3 +44,4 @@ int header_exists_with_value(Response *res, TinyHTTPString name, TinyHTTPString
|
|||||||
|
|
||||||
void test_reuse(void);
|
void test_reuse(void);
|
||||||
void test_chunking(void);
|
void test_chunking(void);
|
||||||
|
void test_parse_request(void);
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
static void test_helper(char *src, int len, int expret, TinyHTTPRequest *expreq)
|
||||||
|
{
|
||||||
|
if (len < 0) len = strlen(src);
|
||||||
|
TinyHTTPRequest req;
|
||||||
|
int ret = tinyhttp_parserequest(src, len, -1ULL, &req);
|
||||||
|
TEST(ret == expret);
|
||||||
|
if (expret > 0) {
|
||||||
|
TEST(match_request(&req, expreq));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_parse_request(void)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
char src[] =
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: 127.0.0.1:8080\r\n"
|
||||||
|
"Connection: Keep-Alive\r\n"
|
||||||
|
"\r\n";
|
||||||
|
TinyHTTPRequest req;
|
||||||
|
req.method = TINYHTTP_METHOD_GET;
|
||||||
|
req.minor = 1;
|
||||||
|
req.path = TINYHTTP_STRING("/");
|
||||||
|
req.num_headers = 2;
|
||||||
|
req.headers[0].name = TINYHTTP_STRING("Host");
|
||||||
|
req.headers[0].value = TINYHTTP_STRING("127.0.0.1:8080");
|
||||||
|
req.headers[1].name = TINYHTTP_STRING("Connection");
|
||||||
|
req.headers[1].value = TINYHTTP_STRING("Keep-Alive");
|
||||||
|
req.body = NULL;
|
||||||
|
req.body_len = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < strlen(src)-1; i++)
|
||||||
|
test_helper(src, i, 0, &req);
|
||||||
|
|
||||||
|
test_helper(src, strlen(src), strlen(src), &req);
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-4
@@ -471,8 +471,7 @@ parse_content_length(const char *src, ptrdiff_t len, unsigned long long *out)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int tinyhttp_parserequest(char *src, ptrdiff_t len,
|
||||||
parse_request(char *src, ptrdiff_t len,
|
|
||||||
unsigned long long body_limit, TinyHTTPRequest *req)
|
unsigned long long body_limit, TinyHTTPRequest *req)
|
||||||
{
|
{
|
||||||
ptrdiff_t ret = parse_request_head(src, len, req);
|
ptrdiff_t ret = parse_request_head(src, len, req);
|
||||||
@@ -1174,7 +1173,7 @@ char *tinyhttp_stream_recv_buf(TinyHTTPStream *stream, ptrdiff_t *cap)
|
|||||||
|
|
||||||
// Parse again. We assume everything will go
|
// Parse again. We assume everything will go
|
||||||
// well as it did the first time.
|
// well as it did the first time.
|
||||||
parse_request(src, len, stream->bodylimit, &stream->req);
|
tinyhttp_parserequest(src, len, stream->bodylimit, &stream->req);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward the write region from the input buffer
|
// Forward the write region from the input buffer
|
||||||
@@ -1217,7 +1216,7 @@ process_next_request(TinyHTTPStream *stream)
|
|||||||
|
|
||||||
ptrdiff_t len;
|
ptrdiff_t len;
|
||||||
char *src = byte_queue_read_buf(&stream->in, &len); // TODO: What if this returns NULL?
|
char *src = byte_queue_read_buf(&stream->in, &len); // TODO: What if this returns NULL?
|
||||||
int ret = parse_request(src, len, stream->bodylimit, &stream->req);
|
int ret = tinyhttp_parserequest(src, len, stream->bodylimit, &stream->req);
|
||||||
|
|
||||||
// Request is incomplete
|
// Request is incomplete
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
|||||||
@@ -190,6 +190,9 @@ void tinyhttp_printstate_(int state, const char *file, const char *line);
|
|||||||
|
|
||||||
int tinyhttp_findheader(TinyHTTPRequest *req, TinyHTTPString name);
|
int tinyhttp_findheader(TinyHTTPRequest *req, TinyHTTPString name);
|
||||||
|
|
||||||
|
int tinyhttp_parserequest(char *src, ptrdiff_t len,
|
||||||
|
unsigned long long body_limit, TinyHTTPRequest *req);
|
||||||
|
|
||||||
// Initializes an HTTP stream
|
// Initializes an HTTP stream
|
||||||
//
|
//
|
||||||
// TODO: Comment on memfunc
|
// TODO: Comment on memfunc
|
||||||
|
|||||||
Reference in New Issue
Block a user