Basic test infrastructure
This commit is contained in:
+13
-31
@@ -1,7 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include "tinyhttp.h"
|
||||
#include "../tinyhttp.h"
|
||||
|
||||
sig_atomic_t should_exit = 0;
|
||||
|
||||
@@ -12,22 +12,6 @@ signal_handler(int sig)
|
||||
should_exit = 1;
|
||||
}
|
||||
|
||||
static void *memfunc(TinyHTTPMemoryFuncTag tag,
|
||||
void *ptr, int len, void *data)
|
||||
{
|
||||
(void) data;
|
||||
switch (tag) {
|
||||
|
||||
case TINYHTTP_MEM_MALLOC:
|
||||
return malloc(len);
|
||||
|
||||
case TINYHTTP_MEM_FREE:
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
signal(SIGINT, signal_handler);
|
||||
@@ -39,31 +23,29 @@ int main(void)
|
||||
.plain_backlog = 32,
|
||||
};
|
||||
|
||||
TinyHTTPServer *server = tinyhttp_server_init(config, memfunc, NULL);
|
||||
TinyHTTPServer *server = tinyhttp_server_init(config);
|
||||
if (server == NULL)
|
||||
return -1;
|
||||
|
||||
while (!should_exit) {
|
||||
|
||||
|
||||
int ret;
|
||||
TinyHTTPRequest *req;
|
||||
TinyHTTPResponse res;
|
||||
|
||||
int ret = tinyhttp_server_wait(server, &req, &res, 1000);
|
||||
|
||||
ret = tinyhttp_server_wait(server, &req, &res, 1000);
|
||||
if (ret < 0) return -1; // Error
|
||||
if (ret > 0) continue; // Timeout
|
||||
|
||||
|
||||
tinyhttp_response_status(res, 200);
|
||||
|
||||
tinyhttp_response_body_setmincap(res, 1<<10);
|
||||
ptrdiff_t cap;
|
||||
char *buf = tinyhttp_response_body_buf(res, &cap);
|
||||
int len = buf ? snprintf(buf, cap, "Hello, world!") : 0;
|
||||
if (len < 0 || len > cap) abort();
|
||||
tinyhttp_response_body_ack(res, len);
|
||||
|
||||
tinyhttp_response_body(res, "Hello, world!", -1);
|
||||
|
||||
//tinyhttp_response_undo(res);
|
||||
//tinyhttp_response_status(res, 500);
|
||||
|
||||
tinyhttp_response_send(res);
|
||||
}
|
||||
|
||||
tinyhttp_server_free(server);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +1,107 @@
|
||||
// A program using the stream interface may look like this:
|
||||
//
|
||||
// void respond(TinyHTTPStream *stream)
|
||||
// {
|
||||
// TinyHTTPRequest *req = tinyhttp_stream_request(stream);
|
||||
// if (req->method != TINYHTTP_METHOD_GET)
|
||||
// tinyhttp_stream_status(stream, 405);
|
||||
// else
|
||||
// tinyhttp_stream_status(stream, 200);
|
||||
// tinyhttp_stream_send(stream);
|
||||
// }
|
||||
//
|
||||
// int main(void)
|
||||
// {
|
||||
// int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
//
|
||||
// struct sockaddr_in buf;
|
||||
// buf.sin_family = AF_INET;
|
||||
// buf.sin_port = htons(port);
|
||||
// buf.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
// bind(listen_fd, (struct sockaddr*) &buf, sizeof(buf));
|
||||
//
|
||||
// listen(listen_fd, 32);
|
||||
//
|
||||
// int num_conns = 0;
|
||||
// int fds[1000];
|
||||
// TinyHTTPStream streams[1000];
|
||||
//
|
||||
// for (int i = 0; i < 1000; i++)
|
||||
// fds[i] = -1;
|
||||
//
|
||||
// for (;;) {
|
||||
// // TODO: timeouts
|
||||
//
|
||||
// fd_set readset;
|
||||
// fd_set writeset;
|
||||
// FD_ZERO(&readset);
|
||||
// FD_ZERO(&writeset);
|
||||
//
|
||||
// FD_SET(&readset);
|
||||
// int max_fd = listen_fd;
|
||||
// for (int i = 0; i < 1000; i++) {
|
||||
// if (fds[i] == -1) continue;
|
||||
// int state = tinyhttp_stream_state(&streams[i]);
|
||||
// if (state & TINYHTTP_STREAM_RECV)
|
||||
// FD_SET(fds[i], &readset);
|
||||
// if (state & TINYHTTP_STREAM_SEND)
|
||||
// FD_SET(fds[i], &writeset);
|
||||
// if (state & (TINYHTTP_STREAM_RECV | TINYHTTP_STREAM_SEND))
|
||||
// if (max_fd < fds[i]) max_fd = fds[i];
|
||||
// }
|
||||
//
|
||||
// int num = select(max_fd+1, &readset, &writeset, NULL, NULL);
|
||||
//
|
||||
// if (FD_ISSET(liste_fd, &readset)) {
|
||||
// // TODO
|
||||
// }
|
||||
//
|
||||
// int ready_queue[1000];
|
||||
// int ready_head = 0;
|
||||
// int ready_count = 0;
|
||||
// for (int i = 0; i < 1000; i++) {
|
||||
// // TODO
|
||||
// }
|
||||
//
|
||||
// while (ready_count > 0) {
|
||||
//
|
||||
// int idx = ready_queue[ready_head];
|
||||
// TinyHTTPStream *stream = &streams[idx];
|
||||
//
|
||||
// TinyHTTPRequest *req = tinyhttp_stream_request(stream);
|
||||
// assert(req);
|
||||
//
|
||||
// respond(stream);
|
||||
//
|
||||
// ready_head = (ready_head + 1) % 1000;
|
||||
// ready_count--;
|
||||
// if (tinyhttp_stream_request(stream)) {
|
||||
// ready_queue[(ready_head + ready_count) % 1000] = idx;
|
||||
// ready_count++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// close(listen_fd);
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// Note that this example does not keep track of timeouts.
|
||||
//
|
||||
// The recv_buf/recv_ack and send_buf/send_ack interface is very handy as it's
|
||||
// compatible both with readyness-based event loops (epoll, poll, select) and
|
||||
// completion-based event loops (iocp, io_uring). Since the stream object does
|
||||
// not read from the socket directly, you can easily implement HTTPS by providing
|
||||
// it with TLS-encoded data instead of data directly from the socket.
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <winsock2.h>
|
||||
#define CLOSESOCKET closesocket
|
||||
#elif defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <arpa/inet.h>
|
||||
#define CLOSESOCKET close
|
||||
#else
|
||||
#error "Only Windows and Linux are supported"
|
||||
#endif
|
||||
|
||||
#include "../tinyhttp.h"
|
||||
|
||||
#define PORT 8080
|
||||
#define ADDR "127.0.0.1"
|
||||
|
||||
// TODO: Complete this
|
||||
|
||||
void respond(TinyHTTPStream *stream)
|
||||
{
|
||||
TinyHTTPRequest *req = tinyhttp_stream_request(stream);
|
||||
if (req->method != TINYHTTP_METHOD_GET)
|
||||
tinyhttp_stream_response_status(stream, 405);
|
||||
else
|
||||
tinyhttp_stream_response_status(stream, 200);
|
||||
tinyhttp_stream_response_send(stream);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
struct sockaddr_in buf;
|
||||
buf.sin_family = AF_INET;
|
||||
buf.sin_port = htons(PORT);
|
||||
buf.sin_addr.s_addr = inet_addr(ADDR);
|
||||
bind(listen_fd, (struct sockaddr*) &buf, sizeof(buf));
|
||||
|
||||
listen(listen_fd, 32);
|
||||
|
||||
int num_conns = 0;
|
||||
int fds[1000];
|
||||
TinyHTTPStream streams[1000];
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
fds[i] = -1;
|
||||
|
||||
for (;;) {
|
||||
// TODO: timeouts
|
||||
|
||||
fd_set readset;
|
||||
fd_set writeset;
|
||||
FD_ZERO(&readset);
|
||||
FD_ZERO(&writeset);
|
||||
|
||||
FD_SET(listen_fd, &readset);
|
||||
int max_fd = listen_fd;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
if (fds[i] == -1) continue;
|
||||
int state = tinyhttp_stream_state(&streams[i]);
|
||||
if (state & TINYHTTP_STREAM_RECV)
|
||||
FD_SET(fds[i], &readset);
|
||||
if (state & TINYHTTP_STREAM_SEND)
|
||||
FD_SET(fds[i], &writeset);
|
||||
if (state & (TINYHTTP_STREAM_RECV | TINYHTTP_STREAM_SEND))
|
||||
if (max_fd < fds[i]) max_fd = fds[i];
|
||||
}
|
||||
|
||||
int num = select(max_fd+1, &readset, &writeset, NULL, NULL);
|
||||
|
||||
if (FD_ISSET(listen_fd, &readset)) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
int ready_queue[1000];
|
||||
int ready_head = 0;
|
||||
int ready_count = 0;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
while (ready_count > 0) {
|
||||
|
||||
int idx = ready_queue[ready_head];
|
||||
TinyHTTPStream *stream = &streams[idx];
|
||||
|
||||
TinyHTTPRequest *req = tinyhttp_stream_request(stream);
|
||||
assert(req);
|
||||
|
||||
respond(stream);
|
||||
|
||||
ready_head = (ready_head + 1) % 1000;
|
||||
ready_count--;
|
||||
if (tinyhttp_stream_request(stream)) {
|
||||
ready_queue[(ready_head + ready_count) % 1000] = idx;
|
||||
ready_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CLOSESOCKET(listen_fd);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user