summaryrefslogtreecommitdiffstats
path: root/examples/client_receiver_uv.c
blob: 0454ba2990dbf37487666b7265e1cd1303c56f7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <dnswire/reader.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#include <arpa/inet.h>
#include <time.h>
#include <errno.h>
#include <stdbool.h>

#include "print_dnstap.c"

#define BUF_SIZE 4096

uv_loop_t*   loop;
uv_tcp_t     sock;
uv_connect_t conn;
char         rbuf[BUF_SIZE];

struct dnswire_reader reader;

void client_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
    buf->base = rbuf;
    buf->len  = sizeof(rbuf);
}

void client_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
{
    if (nread > 0) {
        /*
         * We now push all the data we got to the reader.
         */
        size_t pushed = 0;

        while (pushed < nread) {
            enum dnswire_result res = dnswire_reader_push(&reader, (uint8_t*)&buf->base[pushed], nread - pushed, 0, 0);

            pushed += dnswire_reader_pushed(reader);

            switch (res) {
            case dnswire_have_dnstap:
                /*
                 * We got a DNSTAP message, lets print it!
                 */
                print_dnstap(dnswire_reader_dnstap(reader));
                break;
            case dnswire_again:
            case dnswire_need_more:
                break;
            case dnswire_endofdata:
                /*
                 * The remote end sent a control stop or finish.
                 */
                uv_close((uv_handle_t*)handle, 0);
                return;
            default:
                fprintf(stderr, "dnswire_reader_fread() error\n");
                uv_close((uv_handle_t*)handle, 0);
                return;
            }
        }
    }
    if (nread < 0) {
        if (nread != UV_EOF) {
            fprintf(stderr, "client_read() error: %s\n", uv_err_name(nread));
        } else {
            printf("disconnected\n");
        }
        uv_close((uv_handle_t*)handle, 0);
    }
}

void on_connect(uv_connect_t* req, int status)
{
    /*
     * We have connected to the sender, check that there was no errors
     * and start receiving incoming frames.
     */

    if (status < 0) {
        fprintf(stderr, "on_connect() error: %s\n", uv_strerror(status));
        return;
    }

    uv_read_start((uv_stream_t*)&sock, client_alloc_buffer, client_read);
}

int main(int argc, const char* argv[])
{
    if (argc < 3) {
        fprintf(stderr, "usage: client_receiver_uv <IP> <port>\n");
        return 1;
    }

    /*
     * We first initialize the reader and check that it can allocate the
     * buffers it needs.
     */

    if (dnswire_reader_init(&reader) != dnswire_ok) {
        fprintf(stderr, "Unable to initialize dnswire reader\n");
        return 1;
    }

    /*
     * We set this reader to reject bidirectional communication.
     */
    if (dnswire_reader_allow_bidirectional(&reader, false) != dnswire_ok) {
        fprintf(stderr, "Unable to deny bidirectional communication\n");
        return 1;
    }

    /*
     * We setup a TCP client using libuv and connect to the given server.
     */

    struct sockaddr_storage addr;
    int                     port = atoi(argv[2]);

    if (strchr(argv[1], ':')) {
        uv_ip6_addr(argv[1], port, (struct sockaddr_in6*)&addr);
    } else {
        uv_ip4_addr(argv[1], port, (struct sockaddr_in*)&addr);
    }

    loop = uv_default_loop();

    uv_tcp_init(loop, &sock);
    uv_tcp_connect(&conn, &sock, (const struct sockaddr*)&addr, on_connect);

    return uv_run(loop, UV_RUN_DEFAULT);
}