1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <uv.h>
5
6#ifdef _WIN32
7#define PIPENAME "\\\\?\\pipe\\echo.sock"
8#else
9#define PIPENAME "/tmp/echo.sock"
10#endif
11
12uv_loop_t *loop;
13
14typedef struct {
15    uv_write_t req;
16    uv_buf_t buf;
17} write_req_t;
18
19void free_write_req(uv_write_t *req) {
20    write_req_t *wr = (write_req_t*) req;
21    free(wr->buf.base);
22    free(wr);
23}
24
25void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
26  buf->base = malloc(suggested_size);
27  buf->len = suggested_size;
28}
29
30void echo_write(uv_write_t *req, int status) {
31    if (status < 0) {
32        fprintf(stderr, "Write error %s\n", uv_err_name(status));
33    }
34    free_write_req(req);
35}
36
37void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
38    if (nread > 0) {
39        write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
40        req->buf = uv_buf_init(buf->base, nread);
41        uv_write((uv_write_t*) req, client, &req->buf, 1, echo_write);
42        return;
43    }
44
45    if (nread < 0) {
46        if (nread != UV_EOF)
47            fprintf(stderr, "Read error %s\n", uv_err_name(nread));
48        uv_close((uv_handle_t*) client, NULL);
49    }
50
51    free(buf->base);
52}
53
54void on_new_connection(uv_stream_t *server, int status) {
55    if (status == -1) {
56        // error!
57        return;
58    }
59
60    uv_pipe_t *client = (uv_pipe_t*) malloc(sizeof(uv_pipe_t));
61    uv_pipe_init(loop, client, 0);
62    if (uv_accept(server, (uv_stream_t*) client) == 0) {
63        uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
64    }
65    else {
66        uv_close((uv_handle_t*) client, NULL);
67    }
68}
69
70void remove_sock(int sig) {
71    uv_fs_t req;
72    uv_fs_unlink(loop, &req, PIPENAME, NULL);
73    exit(0);
74}
75
76int main() {
77    loop = uv_default_loop();
78
79    uv_pipe_t server;
80    uv_pipe_init(loop, &server, 0);
81
82    signal(SIGINT, remove_sock);
83
84    int r;
85    if ((r = uv_pipe_bind(&server, PIPENAME))) {
86        fprintf(stderr, "Bind error %s\n", uv_err_name(r));
87        return 1;
88    }
89    if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) {
90        fprintf(stderr, "Listen error %s\n", uv_err_name(r));
91        return 2;
92    }
93    return uv_run(loop, UV_RUN_DEFAULT);
94}
95