156 lines
4.5 KiB
C
156 lines
4.5 KiB
C
|
|
#ifdef _WIN32
|
|
#include <winsock2.h>
|
|
#define POLL WSAPoll
|
|
#else
|
|
#include <poll.h>
|
|
#define POLL poll
|
|
#endif
|
|
|
|
#include "../chttp.h"
|
|
|
|
static int pick_timeout(int t1, int t2)
|
|
{
|
|
if (t1 < 0) return t2;
|
|
if (t2 < 0) return t1;
|
|
return (t1 < t2) ? t1 : t2;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int ret;
|
|
|
|
CHTTP_String remote = CHTTP_STR("http://coz.is");
|
|
|
|
CHTTP_Client client;
|
|
ret = chttp_client_init(&client);
|
|
if (ret < 0) {
|
|
printf("Couldn't initialize client (%s)\n", chttp_strerror(ret));
|
|
return -1;
|
|
}
|
|
|
|
CHTTP_Server server;
|
|
ret = chttp_server_init(&server);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "Couldn't initialize server (%s)\n", chttp_strerror(ret));
|
|
return -1;
|
|
}
|
|
|
|
chttp_server_set_reuse_addr(&server, true);
|
|
chttp_server_set_trace_bytes(&server, true);
|
|
|
|
ret = chttp_server_listen_tcp(&server, CHTTP_STR("127.0.0.1"), 8080);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "Couldn't start listening (%s)\n", chttp_strerror(ret));
|
|
return -1;
|
|
}
|
|
|
|
bool used[CHTTP_SERVER_CAPACITY];
|
|
for (int i = 0; i < CHTTP_SERVER_CAPACITY; i++)
|
|
used[i] = false;
|
|
|
|
CHTTP_ResponseBuilder pending[CHTTP_SERVER_CAPACITY];
|
|
int num_pending = 0;
|
|
|
|
for (;;) {
|
|
|
|
#define POLL_CAPACITY (CHTTP_CLIENT_POLL_CAPACITY + CHTTP_SERVER_POLL_CAPACITY)
|
|
|
|
void *ptrs[POLL_CAPACITY];
|
|
struct pollfd polled[POLL_CAPACITY];
|
|
|
|
EventRegister server_reg = {
|
|
ptrs,
|
|
polled,
|
|
0,
|
|
-1
|
|
};
|
|
chttp_server_register_events(&server, &server_reg);
|
|
|
|
EventRegister client_reg = {
|
|
ptrs + server_reg.num_polled,
|
|
polled + server_reg.num_polled,
|
|
0,
|
|
-1
|
|
};
|
|
chttp_client_register_events(&client, &client_reg);
|
|
|
|
int num_polled = server_reg.num_polled
|
|
+ client_reg.num_polled;
|
|
|
|
int timeout = pick_timeout(server_reg.timeout, client_reg.timeout);
|
|
|
|
POLL(polled, num_polled, timeout);
|
|
|
|
int result;
|
|
void *user;
|
|
CHTTP_Response *response;
|
|
chttp_client_process_events(&client, client_reg);
|
|
while (chttp_client_next_response(&client, &result, &user, &response)) {
|
|
|
|
CHTTP_ResponseBuilder *builder = (CHTTP_ResponseBuilder*) user;
|
|
|
|
int i = builder - pending;
|
|
assert(i > -1);
|
|
assert(i < CHTTP_SERVER_CAPACITY);
|
|
|
|
if (result == CHTTP_OK) {
|
|
chttp_response_builder_status(*builder, response->status);
|
|
chttp_response_builder_body(*builder, response->body);
|
|
chttp_response_builder_send(*builder);
|
|
} else {
|
|
chttp_response_builder_status(*builder, 500);
|
|
chttp_response_builder_send(*builder);
|
|
}
|
|
|
|
used[i] = false;
|
|
num_pending--;
|
|
}
|
|
|
|
CHTTP_Request *request;
|
|
CHTTP_ResponseBuilder response_builder;
|
|
chttp_server_process_events(&server, server_reg);
|
|
while (chttp_server_next_request(&server, &request, &response_builder)) {
|
|
|
|
int i = 0;
|
|
while (used[i]) {
|
|
i++;
|
|
assert(i < CHTTP_SERVER_CAPACITY);
|
|
}
|
|
|
|
CHTTP_String path = request->url.path;
|
|
if (path.len == 0)
|
|
path = CHTTP_STR("/");
|
|
|
|
char target[1<<10];
|
|
int target_len = snprintf(target, sizeof(target),
|
|
"%.*s%.*s", CHTTP_UNPACK(remote), CHTTP_UNPACK(path));
|
|
if (target_len < 0 || target_len >= (int) sizeof(target)) {
|
|
chttp_response_builder_status(response_builder, 500);
|
|
chttp_response_builder_send(response_builder);
|
|
continue;
|
|
}
|
|
|
|
CHTTP_RequestBuilder request_builder = chttp_client_get_builder(&client);
|
|
chttp_request_builder_set_user(request_builder, &pending[i]);
|
|
chttp_request_builder_trace(request_builder, true);
|
|
chttp_request_builder_method(request_builder, request->method);
|
|
chttp_request_builder_target(request_builder, (CHTTP_String) { target, target_len });
|
|
ret = chttp_request_builder_send(request_builder);
|
|
if (ret < 0) {
|
|
chttp_response_builder_status(response_builder, 500);
|
|
chttp_response_builder_send(response_builder);
|
|
continue;
|
|
}
|
|
|
|
used[i] = true;
|
|
pending[i] = response_builder;
|
|
num_pending++;
|
|
}
|
|
}
|
|
|
|
chttp_server_free(&server);
|
|
chttp_client_free(&client);
|
|
return 0;
|
|
}
|