#include #include #include #include #include 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; }