Basic test infrastructure

This commit is contained in:
2025-04-20 14:11:52 +02:00
parent a4aafb1ee8
commit e1dca84a44
9 changed files with 1407 additions and 260 deletions
+107 -95
View File
@@ -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;
}