lsquic_qlog.c revision 7cf121d7
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <stdlib.h>
3#include <stdio.h>
4#include <errno.h>
5#include <inttypes.h>
6#include <string.h>
7#include <sys/queue.h>
8#ifdef WIN32
9#include <Ws2tcpip.h>
10#else
11#include <sys/types.h>
12#include <sys/socket.h>
13#include <netinet/in.h>
14#include <arpa/inet.h>
15#endif
16
17#include "lsquic.h"
18#include "lsquic_types.h"
19#include "lsquic_int_types.h"
20#include "lsquic_packet_common.h"
21#include "lsquic_packet_in.h"
22#include "lsquic_packet_out.h"
23#include "lsquic_util.h"
24#include "lsquic_qlog.h"
25
26#define LSQUIC_LOGGER_MODULE LSQLM_QLOG
27#include "lsquic_logger.h"
28
29#define LSQUIC_LOG_CONN_ID cid
30#define LCID(...) LSQ_LOG2(LSQ_LOG_DEBUG, __VA_ARGS__)
31
32#define MAX_IP_LEN INET6_ADDRSTRLEN
33#define QLOG_PACKET_RAW_SZ 64
34
35
36void
37lsquic_qlog_create_connection (lsquic_cid_t cid,
38                                const struct sockaddr *local_sa,
39                                const struct sockaddr *peer_sa)
40{
41    uint32_t ip_version, srcport, dstport;
42    struct sockaddr_in *local4, *peer4;
43    struct sockaddr_in6 *local6, *peer6;
44    char srcip[MAX_IP_LEN], dstip[MAX_IP_LEN];
45
46    if (!local_sa || !peer_sa)
47        return;
48
49    if (local_sa->sa_family == AF_INET)
50    {
51        ip_version = 4;
52        local4 = (struct sockaddr_in *)local_sa;
53        peer4 = (struct sockaddr_in *)peer_sa;
54        srcport = ntohs(local4->sin_port);
55        dstport = ntohs(peer4->sin_port);
56        inet_ntop(local4->sin_family, &local4->sin_addr, srcip, MAX_IP_LEN);
57        inet_ntop(peer4->sin_family, &peer4->sin_addr, dstip, MAX_IP_LEN);
58    }
59    else if (local_sa->sa_family == AF_INET6)
60    {
61        ip_version = 6;
62        local6 = (struct sockaddr_in6 *)local_sa;
63        peer6 = (struct sockaddr_in6 *)peer_sa;
64        srcport = ntohs(local6->sin6_port);
65        dstport = ntohs(peer6->sin6_port);
66        inet_ntop(local6->sin6_family, &local6->sin6_addr, srcip, MAX_IP_LEN);
67        inet_ntop(peer6->sin6_family, &peer6->sin6_addr, dstip, MAX_IP_LEN);
68    }
69    else
70        return;
71
72    LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"NEW_CONNECTION\",\"LINE\","
73            "{"
74                "\"ip_version\":\"%u\","
75                "\"srcip\":\"%s\","
76                "\"dstip\":\"%s\","
77                "\"srcport\":\"%u\","
78                "\"dstport\":\"%u\""
79            "}]",
80            lsquic_time_now(), ip_version, srcip, dstip, srcport, dstport);
81}
82
83#define QLOG_FRAME_DICT_PREFIX_COMMA ",{\"frame_type\":\""
84#define QLOG_FRAME_DICT_PREFIX "{\"frame_type\":\""
85#define QLOG_FRAME_DICT_SUFFIX "\"}"
86#define QLOG_FRAME_LIST_PREFIX ",\"frames\":["
87#define QLOG_FRAME_LIST_SUFFIX "]"
88#define QLOG_FRAME_LIST_MAX \
89    sizeof(QLOG_FRAME_LIST_PREFIX) + \
90    sizeof(QLOG_FRAME_LIST_SUFFIX) + \
91    lsquic_frame_types_str_sz + \
92    (N_QUIC_FRAMES * \
93    (sizeof(QLOG_FRAME_DICT_PREFIX_COMMA) + \
94     sizeof(QLOG_FRAME_DICT_SUFFIX)))
95
96void
97lsquic_qlog_packet_rx (lsquic_cid_t cid,
98                        const struct lsquic_packet_in *packet_in,
99                        const unsigned char *packet_in_data,
100                        size_t packet_in_size)
101{
102    int i, cur = 0, first = 0, ret = 0;
103    size_t raw_bytes_written;
104    char data[QLOG_PACKET_RAW_SZ];
105    char frame_list[QLOG_FRAME_LIST_MAX + 1];
106
107    if (!packet_in || !packet_in_data)
108        return;
109
110    frame_list[cur] = '\0';
111    if (packet_in->pi_frame_types)
112    {
113        cur = sprintf(frame_list, "%s", QLOG_FRAME_LIST_PREFIX);
114        for (i = 0; i < N_QUIC_FRAMES; i++)
115            if (packet_in->pi_frame_types & (1 << i))
116            {
117                ret = snprintf(frame_list + cur,
118                                QLOG_FRAME_LIST_MAX - cur,
119                                /* prefix + FRAME_NAME + suffix */
120                                "%s%s%s",
121                                /* skip comma in prefix if first frame */
122                                (first++ ?
123                                    QLOG_FRAME_DICT_PREFIX_COMMA :
124                                    QLOG_FRAME_DICT_PREFIX),
125                                QUIC_FRAME_NAME(i),
126                                QLOG_FRAME_DICT_SUFFIX);
127                if ((unsigned)ret > QLOG_FRAME_LIST_MAX - cur)
128                    break;
129                cur += ret;
130            }
131        if ((unsigned)cur <= QLOG_FRAME_LIST_MAX)
132            sprintf(frame_list + cur, "%s", QLOG_FRAME_LIST_SUFFIX);
133    }
134
135    raw_bytes_written = lsquic_hex_encode(packet_in_data, packet_in_size,
136                                                    data, QLOG_PACKET_RAW_SZ);
137
138    LCID("[%" PRIu64 ",\"TRANSPORT\",\"PACKET_RX\",\"LINE\","
139            "{"
140                "\"raw\":\"%s%s\","
141                "\"header\":{"
142                    "\"type\":\"%s\","
143                    "\"payload_length\":\"%d\","
144                    "\"packet_number\":\"%" PRIu64 "\""
145                "}%s"
146            "}]",
147            packet_in->pi_received,
148            data, (raw_bytes_written < packet_in_size) ? "..." : "",
149            lsquic_hety2str[packet_in->pi_header_type],
150            packet_in->pi_data_sz,
151            packet_in->pi_packno,
152            frame_list);
153}
154
155
156void
157lsquic_qlog_hsk_completed (lsquic_cid_t cid)
158{
159    LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"HANDSHAKE\",\"PACKET_RX\","
160            "{\"status\":\"complete\"}]", lsquic_time_now());
161}
162
163
164void
165lsquic_qlog_zero_rtt (lsquic_cid_t cid)
166{
167    LCID("[%" PRIu64 ",\"RECOVERY\",\"RTT_UPDATE\",\"PACKET_RX\","
168            "{\"zero_rtt\":\"successful\"}]", lsquic_time_now());
169}
170
171
172void
173lsquic_qlog_check_certs (lsquic_cid_t cid, const lsquic_str_t **certs,
174                                                                size_t count)
175{
176    size_t i;
177    size_t buf_sz = 0;
178    char *buf = NULL;
179    char *new_buf;
180
181    for (i = 0; i < count; i++)
182    {
183        if (buf_sz < (lsquic_str_len(certs[i]) * 2) + 1)
184        {
185            buf_sz = (lsquic_str_len(certs[i]) * 2) + 1;
186            new_buf = realloc(buf, buf_sz);
187            if (!new_buf)
188                break;
189            buf = new_buf;
190        }
191        lsquic_hex_encode(lsquic_str_cstr(certs[i]), lsquic_str_len(certs[i]),
192                                                                buf, buf_sz);
193        LCID("[%" PRIu64 ",\"SECURITY\",\"CHECK_CERT\",\"CERTLOG\","
194                "{\"certificate\":\"%s\"}]", lsquic_time_now(), buf);
195    }
196    if (buf)
197        free(buf);
198}
199
200
201void
202lsquic_qlog_version_negotiation (lsquic_cid_t cid,
203                                        const char *action, const char *ver)
204{
205    char *trig;
206
207    if (!action || !ver)
208        return;
209    if (strcmp(action, "proposed") == 0)
210        trig = "LINE";
211    else if (strcmp(action, "agreed") == 0)
212        trig = "PACKET_RX";
213    else
214        return;
215    LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"VERNEG\",\"%s\","
216            "{\"%s_version\":\"%s\"}]", lsquic_time_now(), trig, action, ver);
217}
218