minimart-benchmark-2017/uvserver.c

110 lines
2.8 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <uv.h>
static uv_tcp_t serversock;
static uv_timer_t stats;
static int connection_count = 0;
static void on_timer(uv_timer_t *timer) {
printf("%d connections\n", connection_count);
}
static void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = calloc(1, suggested_size);
buf->len = suggested_size;
}
static void on_write_complete(uv_write_t *req, int status) {
/* we could check status here, but we don't care; just free, and be done */
free(req->data);
free(req);
}
static void on_timer_closed(uv_handle_t *timer) {
printf("Exiting after timer shutdown.\n");
uv_stop(timer->loop);
}
static void on_serversock_closed(uv_handle_t *serversock) {
printf("Shutting down statistics timer after server socket shutdown.\n");
uv_timer_stop(&stats);
uv_close((uv_handle_t *) &stats, on_timer_closed);
}
static void on_conn_closed(uv_handle_t *conn) {
connection_count--;
if (connection_count == 0) {
printf("Shutting down server socket on zero connection count.\n");
uv_close((uv_handle_t *) &serversock, on_serversock_closed);
}
free(conn);
}
static void on_input(uv_stream_t *conn, ssize_t nread, uv_buf_t const *buf) {
if (nread < 0) {
/* here we could check uv_last_error(conn->loop).code to see whether it's UV_EOF or not */
/* but we don't care; just close, and be done */
uv_close((uv_handle_t *) conn, on_conn_closed);
if (buf->base != NULL) {
free(buf->base);
}
} else {
/* we just echo what came in. */
uv_write_t *req = calloc(1, sizeof(uv_write_t));
uv_buf_t outbuf = { .base = buf->base, .len = nread };
req->data = buf->base;
uv_write(req, conn, &outbuf, 1, on_write_complete);
}
}
static void on_connection(uv_stream_t *serversock, int status) {
uv_tcp_t *conn;
if (status == -1) {
/* error? */
return;
}
conn = calloc(1, sizeof(uv_tcp_t));
uv_tcp_init(serversock->loop, conn);
if (uv_accept(serversock, (uv_stream_t *) conn) == 0) {
connection_count++;
uv_read_start((uv_stream_t *) conn, alloc_buffer, on_input);
} else {
uv_close((uv_handle_t *) conn, NULL);
}
}
static int const PORTNUMBER = 5999;
int main(int argc, char const *argv[]) {
uv_loop_t uv;
struct sockaddr_in bind_addr;
printf("uvserver; libuv version %s\n", uv_version_string());
if (argc > 1) {
return 0;
}
uv_loop_init(&uv);
printf("Accepting connections on port %d.\n", PORTNUMBER);
uv_tcp_init(&uv, &serversock);
uv_ip4_addr("0.0.0.0", PORTNUMBER, &bind_addr);
uv_tcp_bind(&serversock, (struct sockaddr const *) &bind_addr, 0);
uv_listen((uv_stream_t *) &serversock, 4, on_connection);
uv_timer_init(&uv, &stats);
uv_timer_start(&stats, on_timer, 2000, 2000);
uv_run(&uv, UV_RUN_DEFAULT);
uv_loop_close(&uv);
return 0;
}