#include <stdlib.h>
#include <uv.h>
uv_loop_t* loop;
uv_tcp_t server;
struct sockaddr_in addr;
void on_new_connection(uv_stream_t* server, int status);
void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
void serve_client(uv_work_t* req);
void on_write(uv_write_t* req, int status);
int main() {
int r;
loop = uv_default_loop();
uv_tcp_init(loop, &server);
uv_ip4_addr("0.0.0.0", 8080, &addr);
uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);
if ((r = uv_listen((uv_stream_t*)&server, 100, on_new_connection))) {
fprintf(stderr, "Listen error %s\n", uv_strerror(r));
return 1;
}
return uv_run(loop, UV_RUN_DEFAULT);
}
void on_new_connection(uv_stream_t* server, int status) {
if (status < 0) {
fprintf(stderr, "New connection error %s\n", uv_strerror(status));
return;
}
uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
uv_tcp_init(loop, client);
if (uv_accept(server, (uv_stream_t*)client) == 0) {
uv_work_t* work_req = malloc(sizeof(uv_work_t));
work_req->data = client;
uv_queue_work(client->loop, work_req, serve_client, NULL);
}
}
void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
*buf = uv_buf_init((char*)malloc(suggested_size), suggested_size);
}
void serve_client(uv_work_t* req) {
uv_read_start((uv_stream_t*)req->data, alloc_buffer, read_cb);
}
void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
if (nread < 0) {
if (nread == UV_EOF) {
uv_close((uv_handle_t*)stream, NULL);
}
} else if (nread > 0) {
uv_write_t req;
uv_buf_t* tempBuf = malloc(sizeof(uv_buf_t));
*tempBuf = *buf;
req.data = tempBuf;
tempBuf->len = nread;
uv_write(&req, stream, tempBuf, 1, on_write);
} else {
uv_close((uv_handle_t*)stream, NULL);
}
}
void on_write(uv_write_t* req, int status) {
uv_buf_t* buf = (uv_buf_t*)req->data;
free(buf->base);
free(buf);
}