mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 1.21.0
[FEATURE] Add qlog log module.
This commit is contained in:
parent
b4069a69ae
commit
55cd0b38b2
20 changed files with 603 additions and 13 deletions
|
@ -1,3 +1,7 @@
|
|||
2019-04-12
|
||||
- 1.21.0
|
||||
- [FEATURE] Add qlog log module.
|
||||
|
||||
2019-04-01
|
||||
- 1.20.0
|
||||
- [FEATURE] Add support for Q046.
|
||||
|
|
|
@ -24,7 +24,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define LSQUIC_MAJOR_VERSION 1
|
||||
#define LSQUIC_MINOR_VERSION 20
|
||||
#define LSQUIC_MINOR_VERSION 21
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,7 @@ SET(lsquic_STAT_SRCS
|
|||
lsquic_di_error.c
|
||||
lsquic_global.c
|
||||
lsquic_packet_common.c
|
||||
lsquic_qlog.c
|
||||
lsquic_ev_log.c
|
||||
lsquic_frame_common.c
|
||||
lsquic_packints.c
|
||||
|
|
|
@ -553,6 +553,8 @@ process_packet_in (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in,
|
|||
const struct sockaddr *sa_peer, void *peer_ctx)
|
||||
{
|
||||
lsquic_conn_t *conn;
|
||||
const unsigned char *packet_in_data;
|
||||
size_t packet_in_size;
|
||||
|
||||
if (lsquic_packet_in_is_gquic_prst(packet_in)
|
||||
&& !engine->pub.enp_settings.es_honor_prst)
|
||||
|
@ -577,8 +579,27 @@ process_packet_in (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in,
|
|||
}
|
||||
lsquic_conn_record_sockaddr(conn, sa_local, sa_peer);
|
||||
lsquic_packet_in_upref(packet_in);
|
||||
/* Note on QLog:
|
||||
* For the PACKET_RX QLog event, we are interested in logging these things:
|
||||
* - raw packet (however it comes in, encrypted or not)
|
||||
* - frames (list of frame names)
|
||||
* - packet type and number
|
||||
* - packet rx timestamp
|
||||
*
|
||||
* Since only some of these items are available at this code
|
||||
* juncture, we will wait until after the packet has been
|
||||
* decrypted (if necessary) and parsed to call the log functions.
|
||||
*
|
||||
* Once the PACKET_RX event is finally logged, the timestamp
|
||||
* will come from packet_in->pi_received. For correct sequential
|
||||
* ordering of QLog events, be sure to process the QLogs downstream.
|
||||
* (Hint: Use the qlog_parser.py tool in tools/ for full QLog processing.)
|
||||
*/
|
||||
conn->cn_peer_ctx = peer_ctx;
|
||||
packet_in_data = packet_in->pi_data;
|
||||
packet_in_size = packet_in->pi_data_sz;
|
||||
conn->cn_if->ci_packet_in(conn, packet_in);
|
||||
QLOG_PACKET_RX(conn->cn_cid, packet_in, packet_in_data, packet_in_size);
|
||||
lsquic_packet_in_put(&engine->pub.enp_mm, packet_in);
|
||||
return 0;
|
||||
}
|
||||
|
@ -700,6 +721,8 @@ lsquic_engine_connect (lsquic_engine_t *engine, const struct sockaddr *local_sa,
|
|||
zero_rtt, zero_rtt_len);
|
||||
if (!conn)
|
||||
goto err;
|
||||
EV_LOG_CREATE_CONN(conn->cn_cid, local_sa, peer_sa);
|
||||
EV_LOG_VER_NEG(conn->cn_cid, "proposed", lsquic_ver2str[conn->cn_version]);
|
||||
lsquic_conn_record_sockaddr(conn, local_sa, peer_sa);
|
||||
if (0 != conn_hash_add(&engine->conns_hash, conn))
|
||||
{
|
||||
|
|
|
@ -345,3 +345,42 @@ lsquic_ev_log_generated_http_push_promise (lsquic_cid_t cid,
|
|||
(int) extra_headers->headers[i].value.iov_len,
|
||||
(char *) extra_headers->headers[i].value.iov_base);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_ev_log_create_connection (lsquic_cid_t cid,
|
||||
const struct sockaddr *local_sa,
|
||||
const struct sockaddr *peer_sa)
|
||||
{
|
||||
LCID("connection created");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_ev_log_hsk_completed (lsquic_cid_t cid)
|
||||
{
|
||||
LCID("handshake completed");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_ev_log_zero_rtt (lsquic_cid_t cid)
|
||||
{
|
||||
LCID("zero_rtt successful");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_ev_log_check_certs (lsquic_cid_t cid, const lsquic_str_t **certs,
|
||||
size_t count)
|
||||
{
|
||||
LCID("check certs");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_ev_log_version_negotiation (lsquic_cid_t cid,
|
||||
const char *action, const char *ver)
|
||||
{
|
||||
LCID("version negotiation: %s version %s", action, ver);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define LSQUIC_EV_LOG_H 1
|
||||
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_qlog.h"
|
||||
|
||||
struct ack_info;
|
||||
struct http_prio_frame;
|
||||
|
@ -208,4 +209,56 @@ lsquic_ev_log_generated_http_push_promise (lsquic_cid_t, uint32_t stream_id,
|
|||
lsquic_ev_log_generated_http_push_promise(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
lsquic_ev_log_create_connection (lsquic_cid_t, const struct sockaddr *,
|
||||
const struct sockaddr *);
|
||||
|
||||
#define EV_LOG_CREATE_CONN(...) do { \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
|
||||
lsquic_ev_log_create_connection(__VA_ARGS__); \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
|
||||
lsquic_qlog_create_connection(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
lsquic_ev_log_hsk_completed (lsquic_cid_t);
|
||||
|
||||
#define EV_LOG_HSK_COMPLETED(...) do { \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
|
||||
lsquic_ev_log_hsk_completed(__VA_ARGS__); \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
|
||||
lsquic_qlog_hsk_completed(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
void
|
||||
lsquic_ev_log_zero_rtt (lsquic_cid_t);
|
||||
|
||||
#define EV_LOG_ZERO_RTT(...) do { \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
|
||||
lsquic_ev_log_zero_rtt(__VA_ARGS__); \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
|
||||
lsquic_qlog_zero_rtt(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
lsquic_ev_log_check_certs (lsquic_cid_t, const lsquic_str_t **, size_t);
|
||||
|
||||
#define EV_LOG_CHECK_CERTS(...) do { \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
|
||||
lsquic_ev_log_check_certs(__VA_ARGS__); \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
|
||||
lsquic_qlog_check_certs(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
lsquic_ev_log_version_negotiation (lsquic_cid_t, const char *, const char *);
|
||||
|
||||
#define EV_LOG_VER_NEG(...) do { \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_EVENT)) \
|
||||
lsquic_ev_log_version_negotiation(__VA_ARGS__); \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
|
||||
lsquic_qlog_version_negotiation(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1920,6 +1920,8 @@ process_ver_neg_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
|||
{
|
||||
versions |= 1 << version;
|
||||
LSQ_DEBUG("server supports version %s", lsquic_ver2str[version]);
|
||||
EV_LOG_VER_NEG(conn->fc_conn.cn_cid,
|
||||
"supports", lsquic_ver2str[version]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2111,6 +2113,8 @@ process_incoming_packet (struct full_conn *conn, lsquic_packet_in_t *packet_in)
|
|||
LSQ_DEBUG("end of version negotiation: agreed upon %s",
|
||||
lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
|
||||
lsquic_send_ctl_verneg_done(&conn->fc_send_ctl);
|
||||
EV_LOG_VER_NEG(conn->fc_conn.cn_cid,
|
||||
"agreed", lsquic_ver2str[conn->fc_ver_neg.vn_ver]);
|
||||
}
|
||||
return process_regular_packet(conn, packet_in);
|
||||
}
|
||||
|
|
|
@ -1185,6 +1185,7 @@ static int handle_chlo_reply_verify_prof(lsquic_enc_session_t *enc_session,
|
|||
LSQ_INFO("server certificate verification %ssuccessful",
|
||||
ret == 0 ? "" : "not ");
|
||||
}
|
||||
EV_LOG_CHECK_CERTS(enc_session->cid, (const lsquic_str_t **)out_certs, *out_certs_count);
|
||||
|
||||
cleanup:
|
||||
if (chain)
|
||||
|
@ -1423,6 +1424,9 @@ lsquic_enc_session_handle_chlo_reply (lsquic_enc_session_t *enc_session,
|
|||
else if(head_tag == QTAG_SHLO)
|
||||
{
|
||||
enc_session->hsk_state = HSK_COMPLETED;
|
||||
EV_LOG_HSK_COMPLETED(enc_session->cid);
|
||||
if (!(enc_session->es_flags & ES_RECV_REJ))
|
||||
EV_LOG_ZERO_RTT(enc_session->cid);
|
||||
}
|
||||
|
||||
if (info->scfg_flag == 1)
|
||||
|
|
|
@ -85,6 +85,7 @@ enum lsq_log_level lsq_log_levels[N_LSQUIC_LOGGER_MODULES] = {
|
|||
[LSQLM_PACER] = LSQ_LOG_WARN,
|
||||
[LSQLM_MIN_HEAP] = LSQ_LOG_WARN,
|
||||
[LSQLM_HTTP1X] = LSQ_LOG_WARN,
|
||||
[LSQLM_QLOG] = LSQ_LOG_WARN,
|
||||
};
|
||||
|
||||
const char *const lsqlm_to_str[N_LSQUIC_LOGGER_MODULES] = {
|
||||
|
@ -114,6 +115,7 @@ const char *const lsqlm_to_str[N_LSQUIC_LOGGER_MODULES] = {
|
|||
[LSQLM_PACER] = "pacer",
|
||||
[LSQLM_MIN_HEAP] = "min-heap",
|
||||
[LSQLM_HTTP1X] = "http1x",
|
||||
[LSQLM_QLOG] = "qlog",
|
||||
};
|
||||
|
||||
const char *const lsq_loglevel2str[N_LSQUIC_LOG_LEVELS] = {
|
||||
|
|
|
@ -72,6 +72,7 @@ enum lsquic_logger_module {
|
|||
LSQLM_PACER,
|
||||
LSQLM_MIN_HEAP,
|
||||
LSQLM_HTTP1X,
|
||||
LSQLM_QLOG,
|
||||
N_LSQUIC_LOGGER_MODULES
|
||||
};
|
||||
|
||||
|
|
|
@ -64,8 +64,9 @@ static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
|
|||
[QUIC_FRAME_PING] = "QUIC_FRAME_PING",
|
||||
};
|
||||
|
||||
|
||||
#define QUIC_FRAME_SLEN(x) (sizeof(#x) - sizeof("QUIC_FRAME_"))
|
||||
#define QUIC_FRAME_PRELEN (sizeof("QUIC_FRAME_"))
|
||||
#define QUIC_FRAME_SLEN(x) (sizeof(#x) - QUIC_FRAME_PRELEN)
|
||||
#define QUIC_FRAME_NAME(i) (frame_type_2_str[i] + QUIC_FRAME_PRELEN - 1)
|
||||
|
||||
|
||||
/* We don't need to include INVALID frame in this list because it is
|
||||
|
|
|
@ -72,10 +72,13 @@ write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits)
|
|||
{
|
||||
case IQUIC_PACKNO_LEN_4:
|
||||
*p++ = packno >> 24;
|
||||
/* fall-through */
|
||||
case IQUIC_PACKNO_LEN_3:
|
||||
*p++ = packno >> 16;
|
||||
/* fall-through */
|
||||
case IQUIC_PACKNO_LEN_2:
|
||||
*p++ = packno >> 8;
|
||||
/* fall-through */
|
||||
default:
|
||||
*p++ = packno;
|
||||
}
|
||||
|
|
|
@ -75,13 +75,7 @@ lsquic_iquic_parse_packet_in_long_begin (lsquic_packet_in_t *packet_in,
|
|||
header_type = bits2ht[ (first_byte >> 4) & 3 ];
|
||||
}
|
||||
else
|
||||
{
|
||||
header_type = HETY_VERNEG;
|
||||
#ifdef WIN32
|
||||
/* Useless initialization */
|
||||
version = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
packet_in->pi_header_type = header_type;
|
||||
|
||||
|
@ -131,10 +125,6 @@ lsquic_iquic_parse_packet_in_long_begin (lsquic_packet_in_t *packet_in,
|
|||
/* Need at least one version in the version array: add 4 */
|
||||
if (end - p < (ptrdiff_t) (dcil + scil + 4))
|
||||
return -1;
|
||||
#ifdef WIN32
|
||||
/* Useless initialization */
|
||||
packet_len = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
memcpy(&packet_in->pi_conn_id, p, cid_len);
|
||||
|
|
208
src/liblsquic/lsquic_qlog.c
Normal file
208
src/liblsquic/lsquic_qlog.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_packet_in.h"
|
||||
#include "lsquic_packet_out.h"
|
||||
#include "lsquic_util.h"
|
||||
#include "lsquic_qlog.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_QLOG
|
||||
#include "lsquic_logger.h"
|
||||
|
||||
#define LSQUIC_LOG_CONN_ID cid
|
||||
#define LCID(...) LSQ_LOG2(LSQ_LOG_DEBUG, __VA_ARGS__)
|
||||
|
||||
#define MAX_IP_LEN INET6_ADDRSTRLEN
|
||||
#define QLOG_PACKET_RAW_SZ 64
|
||||
|
||||
|
||||
void
|
||||
lsquic_qlog_create_connection (lsquic_cid_t cid,
|
||||
const struct sockaddr *local_sa,
|
||||
const struct sockaddr *peer_sa)
|
||||
{
|
||||
uint32_t ip_version, srcport, dstport;
|
||||
struct sockaddr_in *local4, *peer4;
|
||||
struct sockaddr_in6 *local6, *peer6;
|
||||
char srcip[MAX_IP_LEN], dstip[MAX_IP_LEN];
|
||||
|
||||
if (!local_sa || !peer_sa)
|
||||
return;
|
||||
|
||||
if (local_sa->sa_family == AF_INET)
|
||||
{
|
||||
ip_version = 4;
|
||||
local4 = (struct sockaddr_in *)local_sa;
|
||||
peer4 = (struct sockaddr_in *)peer_sa;
|
||||
srcport = ntohs(local4->sin_port);
|
||||
dstport = ntohs(peer4->sin_port);
|
||||
inet_ntop(local4->sin_family, &local4->sin_addr, srcip, MAX_IP_LEN);
|
||||
inet_ntop(peer4->sin_family, &peer4->sin_addr, dstip, MAX_IP_LEN);
|
||||
}
|
||||
else if (local_sa->sa_family == AF_INET6)
|
||||
{
|
||||
ip_version = 6;
|
||||
local6 = (struct sockaddr_in6 *)local_sa;
|
||||
peer6 = (struct sockaddr_in6 *)peer_sa;
|
||||
srcport = ntohs(local6->sin6_port);
|
||||
dstport = ntohs(peer6->sin6_port);
|
||||
inet_ntop(local6->sin6_family, &local6->sin6_addr, srcip, MAX_IP_LEN);
|
||||
inet_ntop(peer6->sin6_family, &peer6->sin6_addr, dstip, MAX_IP_LEN);
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"NEW_CONNECTION\",\"LINE\","
|
||||
"{"
|
||||
"\"ip_version\":\"%u\","
|
||||
"\"srcip\":\"%s\","
|
||||
"\"dstip\":\"%s\","
|
||||
"\"srcport\":\"%u\","
|
||||
"\"dstport\":\"%u\""
|
||||
"}]",
|
||||
lsquic_time_now(), ip_version, srcip, dstip, srcport, dstport);
|
||||
}
|
||||
|
||||
#define QLOG_FRAME_DICT_PREFIX ",{\"frame_type\":\""
|
||||
#define QLOG_FRAME_DICT_SUFFIX "\"}"
|
||||
#define QLOG_FRAME_LIST_PREFIX ",\"frames\":["
|
||||
#define QLOG_FRAME_LIST_SUFFIX "]"
|
||||
#define QLOG_FRAME_LIST_MAX \
|
||||
sizeof(QLOG_FRAME_LIST_PREFIX) + \
|
||||
sizeof(QLOG_FRAME_LIST_SUFFIX) + \
|
||||
lsquic_frame_types_str_sz + \
|
||||
(N_QUIC_FRAMES * \
|
||||
(sizeof(QLOG_FRAME_DICT_PREFIX) + \
|
||||
sizeof(QLOG_FRAME_DICT_SUFFIX)))
|
||||
|
||||
void
|
||||
lsquic_qlog_packet_rx (lsquic_cid_t cid,
|
||||
const struct lsquic_packet_in *packet_in,
|
||||
const unsigned char *packet_in_data,
|
||||
size_t packet_in_size)
|
||||
{
|
||||
int i, cur = 0, first = 0, ret = 0;
|
||||
size_t raw_bytes_written;
|
||||
char data[QLOG_PACKET_RAW_SZ];
|
||||
char frame_list[QLOG_FRAME_LIST_MAX + 1];
|
||||
|
||||
if (!packet_in || !packet_in_data)
|
||||
return;
|
||||
|
||||
frame_list[cur] = '\0';
|
||||
if (packet_in->pi_frame_types)
|
||||
{
|
||||
cur = sprintf(frame_list, "%s", QLOG_FRAME_LIST_PREFIX);
|
||||
for (i = 0; i < N_QUIC_FRAMES; i++)
|
||||
if (packet_in->pi_frame_types & (1 << i))
|
||||
{
|
||||
ret = snprintf(frame_list + cur,
|
||||
QLOG_FRAME_LIST_MAX - cur,
|
||||
/* prefix + FRAME_NAME + suffix */
|
||||
"%s%s%s",
|
||||
/* skip comma in prefix if first frame */
|
||||
QLOG_FRAME_DICT_PREFIX + (first++ ? 0 : 1),
|
||||
QUIC_FRAME_NAME(i),
|
||||
QLOG_FRAME_DICT_SUFFIX);
|
||||
if ((unsigned)ret > QLOG_FRAME_LIST_MAX - cur)
|
||||
break;
|
||||
cur += ret;
|
||||
}
|
||||
if ((unsigned)cur <= QLOG_FRAME_LIST_MAX)
|
||||
sprintf(frame_list + cur, "%s", QLOG_FRAME_LIST_SUFFIX);
|
||||
}
|
||||
|
||||
raw_bytes_written = lsquic_hex_encode(packet_in_data, packet_in_size,
|
||||
data, QLOG_PACKET_RAW_SZ);
|
||||
|
||||
LCID("[%" PRIu64 ",\"TRANSPORT\",\"PACKET_RX\",\"LINE\","
|
||||
"{"
|
||||
"\"raw\":\"%s%s\","
|
||||
"\"header\":{"
|
||||
"\"type\":\"%s\","
|
||||
"\"payload_length\":\"%d\","
|
||||
"\"packet_number\":\"%ld\""
|
||||
"}%s"
|
||||
"}]",
|
||||
packet_in->pi_received,
|
||||
data, (raw_bytes_written < packet_in_size) ? "..." : "",
|
||||
lsquic_hety2str[packet_in->pi_header_type],
|
||||
packet_in->pi_data_sz,
|
||||
packet_in->pi_packno,
|
||||
frame_list);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_qlog_hsk_completed (lsquic_cid_t cid)
|
||||
{
|
||||
LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"HANDSHAKE\",\"PACKET_RX\","
|
||||
"{\"status\":\"complete\"}]", lsquic_time_now());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_qlog_zero_rtt (lsquic_cid_t cid)
|
||||
{
|
||||
LCID("[%" PRIu64 ",\"RECOVERY\",\"RTT_UPDATE\",\"PACKET_RX\","
|
||||
"{\"zero_rtt\":\"successful\"}]", lsquic_time_now());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_qlog_check_certs (lsquic_cid_t cid, const lsquic_str_t **certs,
|
||||
size_t count)
|
||||
{
|
||||
size_t i;
|
||||
size_t buf_sz = 0;
|
||||
char *buf = NULL;
|
||||
char *new_buf;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (buf_sz < (lsquic_str_len(certs[i]) * 2) + 1)
|
||||
{
|
||||
buf_sz = (lsquic_str_len(certs[i]) * 2) + 1;
|
||||
new_buf = realloc(buf, buf_sz);
|
||||
if (!new_buf)
|
||||
break;
|
||||
buf = new_buf;
|
||||
}
|
||||
lsquic_hex_encode(lsquic_str_cstr(certs[i]), lsquic_str_len(certs[i]),
|
||||
buf, buf_sz);
|
||||
LCID("[%" PRIu64 ",\"SECURITY\",\"CHECK_CERT\",\"CERTLOG\","
|
||||
"{\"certificate\":\"%s\"}]", lsquic_time_now(), buf);
|
||||
}
|
||||
if (buf)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_qlog_version_negotiation (lsquic_cid_t cid,
|
||||
const char *action, const char *ver)
|
||||
{
|
||||
char *trig;
|
||||
|
||||
if (!action || !ver)
|
||||
return;
|
||||
if (strcmp(action, "proposed") == 0)
|
||||
trig = "LINE";
|
||||
else if (strcmp(action, "agreed") == 0)
|
||||
trig = "PACKET_RX";
|
||||
else
|
||||
return;
|
||||
LCID("[%" PRIu64 ",\"CONNECTIVITY\",\"VERNEG\",\"%s\","
|
||||
"{\"%s_version\":\"%s\"}]", lsquic_time_now(), trig, action, ver);
|
||||
}
|
89
src/liblsquic/lsquic_qlog.h
Normal file
89
src/liblsquic/lsquic_qlog.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/*
|
||||
* lsquic_qlog.h -- QLOG Event logger
|
||||
*/
|
||||
|
||||
#ifndef LSQUIC_QLOG_H
|
||||
#define LSQUIC_QLOG_H 1
|
||||
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_packet_common.h"
|
||||
#include "lsquic_str.h"
|
||||
|
||||
/*
|
||||
EventCategory
|
||||
CONNECTIVITY
|
||||
SECURITY
|
||||
TRANSPORT
|
||||
RECOVERY
|
||||
|
||||
EventType
|
||||
CONNECTIVITY
|
||||
NEW_CONNECTION
|
||||
+ VERNEG
|
||||
+ HANDSHAKE
|
||||
SECURITY
|
||||
+ CHECK_CERT
|
||||
KEY_UPDATE
|
||||
TRANSPORT
|
||||
+ PACKET_RX
|
||||
STREAM_NEW
|
||||
ACK_NEW
|
||||
MAXDATA_NEW
|
||||
MAXSTREAMDATA_NEW
|
||||
RECOVERY
|
||||
LOSS_DETECTION_ARMED
|
||||
LOSS_DETECTION_POSTPONED
|
||||
LOSS_DETECTION_TRIGGERED
|
||||
BYTES_IN_FLIGHT_UPDATE
|
||||
CWND_UPDATE
|
||||
RTT_UPDATE
|
||||
|
||||
EventTrigger
|
||||
CONNECTIVITY
|
||||
LINE
|
||||
+ PACKET_RX
|
||||
SECURITY
|
||||
+ CERTLOG
|
||||
KEYLOG
|
||||
TRANSPORT
|
||||
LINE
|
||||
PACKET_TX
|
||||
PACKET_RX
|
||||
RECOVERY
|
||||
ACK_RX
|
||||
PACKET_RX
|
||||
UNKNOWN
|
||||
|
||||
EventData
|
||||
EventNewConnection
|
||||
EventKeyUpdate
|
||||
EventPacketRX
|
||||
*/
|
||||
|
||||
void
|
||||
lsquic_qlog_create_connection (lsquic_cid_t, const struct sockaddr *,
|
||||
const struct sockaddr *);
|
||||
|
||||
void
|
||||
lsquic_qlog_packet_rx (lsquic_cid_t cid, const struct lsquic_packet_in *,
|
||||
const unsigned char *, size_t);
|
||||
|
||||
#define QLOG_PACKET_RX(...) do { \
|
||||
if (LSQ_LOG_ENABLED_EXT(LSQ_LOG_DEBUG, LSQLM_QLOG)) \
|
||||
lsquic_qlog_packet_rx(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
lsquic_qlog_hsk_completed (lsquic_cid_t);
|
||||
|
||||
void
|
||||
lsquic_qlog_zero_rtt (lsquic_cid_t);
|
||||
|
||||
void
|
||||
lsquic_qlog_check_certs (lsquic_cid_t, const lsquic_str_t **, size_t);
|
||||
|
||||
void
|
||||
lsquic_qlog_version_negotiation (lsquic_cid_t, const char *, const char *);
|
||||
|
||||
#endif
|
|
@ -128,6 +128,34 @@ char *get_bin_str(const void *s, size_t len, size_t max_display_len)
|
|||
}
|
||||
|
||||
|
||||
static char
|
||||
hex_digit(uint8_t n)
|
||||
{
|
||||
return (n < 10) ? (n + '0') : ((n - 10) + 'a');
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
lsquic_hex_encode (const void *src, size_t src_sz, void *dst, size_t dst_sz)
|
||||
{
|
||||
size_t src_cur, dst_cur;
|
||||
const uint8_t *src_hex;
|
||||
char *dst_char;
|
||||
|
||||
src_hex = (const uint8_t *)src;
|
||||
dst_char = (char *)dst;
|
||||
src_cur = dst_cur = 0;
|
||||
|
||||
while (src_cur < src_sz && dst_cur < (dst_sz - 2))
|
||||
{
|
||||
dst_char[dst_cur++] = hex_digit((src_hex[src_cur] & 0xf0) >> 4);
|
||||
dst_char[dst_cur++] = hex_digit(src_hex[src_cur++] & 0x0f);
|
||||
}
|
||||
dst_char[dst_cur++] = '\0';
|
||||
return dst_cur;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
hexdump (const void *src_void, size_t src_sz, char *out, size_t out_sz)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,8 @@ lsquic_is_zero (const void *buf, size_t bufsz);
|
|||
|
||||
char * get_bin_str(const void *s, size_t len, size_t max_display_len);
|
||||
|
||||
size_t
|
||||
lsquic_hex_encode (const void *src, size_t src_sz, void *dst, size_t dst_sz);
|
||||
|
||||
/* `out_sz' is assumed to be at least 1. `out' is always NUL-terminated. */
|
||||
size_t
|
||||
|
|
|
@ -38,6 +38,7 @@ SET(TESTS
|
|||
hkdf
|
||||
lsquic_hash
|
||||
malo
|
||||
qlog
|
||||
packet_out
|
||||
packno_len
|
||||
parse_packet_in
|
||||
|
|
54
test/unittests/test_qlog.c
Normal file
54
test/unittests/test_qlog.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_conn.h"
|
||||
|
||||
#include "lsquic_qlog.h"
|
||||
|
||||
#define LSQUIC_LOGGER_MODULE LSQLM_NOMODULE
|
||||
#include "lsquic_logger.h"
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
lsquic_log_to_fstream(stderr, LLTS_HHMMSSMS);
|
||||
lsquic_set_log_level("debug");
|
||||
|
||||
lsquic_qlog_create_connection(0, NULL, NULL);
|
||||
struct in_addr local_addr = {.s_addr = htonl(0x0a000001),};
|
||||
struct sockaddr_in local =
|
||||
{
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(12345),
|
||||
.sin_addr = local_addr,
|
||||
};
|
||||
struct in_addr peer_addr = {.s_addr = htonl(0x0a000002),};
|
||||
struct sockaddr_in peer =
|
||||
{
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(443),
|
||||
.sin_addr = peer_addr,
|
||||
};
|
||||
lsquic_qlog_create_connection(0, (const struct sockaddr *)&local,
|
||||
(const struct sockaddr *)&peer);
|
||||
|
||||
lsquic_qlog_packet_rx(0, NULL, NULL, 0);
|
||||
lsquic_qlog_hsk_completed(0);
|
||||
lsquic_qlog_zero_rtt(0);
|
||||
lsquic_qlog_check_certs(0, NULL, 0);
|
||||
|
||||
lsquic_qlog_version_negotiation(0, NULL, NULL);
|
||||
lsquic_qlog_version_negotiation(0, "proposed", NULL);
|
||||
lsquic_qlog_version_negotiation(0, "proposed", "Q035");
|
||||
lsquic_qlog_version_negotiation(0, "proposed", "Q046");
|
||||
lsquic_qlog_version_negotiation(0, "agreed", "Q044");
|
||||
lsquic_qlog_version_negotiation(0, "agreed", "Q098");
|
||||
lsquic_qlog_version_negotiation(0, "something else", "Q098");
|
||||
return 0;
|
||||
}
|
83
tools/qlog-parser.py
Normal file
83
tools/qlog-parser.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
import time
|
||||
import json
|
||||
import re
|
||||
import argparse
|
||||
|
||||
_ev_time = 0
|
||||
_ev_cate = 1
|
||||
_ev_type = 2
|
||||
_ev_trig = 3
|
||||
_ev_data = 4
|
||||
_conn_base = {
|
||||
'qlog_version': '0.1',
|
||||
'vantagepoint': 'NETWORK',
|
||||
'connectionid': '0',
|
||||
'starttime': '0',
|
||||
'fields': [
|
||||
'time',
|
||||
'category',
|
||||
'type',
|
||||
'trigger',
|
||||
'data',
|
||||
],
|
||||
'events': [],
|
||||
}
|
||||
|
||||
arg_parser = argparse.ArgumentParser(description='Test the ExploreParser.')
|
||||
arg_parser.add_argument('qlog_path', type=str, help='path to QLog file')
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
try:
|
||||
with open(args.qlog_path, 'r') as file:
|
||||
text = file.read()
|
||||
except IOError:
|
||||
print('ERROR: QLog not found at given path.')
|
||||
|
||||
events = {}
|
||||
event_times = {}
|
||||
start_time = {}
|
||||
|
||||
qlog = {
|
||||
'qlog_version': '0.1',
|
||||
'description': 'test with local log file',
|
||||
'connections': [],
|
||||
}
|
||||
|
||||
lines = text.split('\n')
|
||||
for line in lines:
|
||||
if 'qlog' in line:
|
||||
i = line.find('[QUIC:')
|
||||
j = line.find(']', i)
|
||||
k = line.find('qlog: ')
|
||||
|
||||
cid = line[i+6:j]
|
||||
try:
|
||||
event = json.loads(line[k+6:])
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
if not cid in events:
|
||||
events[cid] = [event]
|
||||
event_times[cid] = [event[_ev_time]]
|
||||
else:
|
||||
events[cid].append(event)
|
||||
event_times[cid].append(event[_ev_time])
|
||||
|
||||
for cid, times in event_times.items():
|
||||
new_events = []
|
||||
start_time[cid] = min(times)
|
||||
times = [t - min(times) for t in times]
|
||||
for t, i in sorted(((t, i) for i, t in enumerate(times))):
|
||||
events[cid][i][0] = t
|
||||
new_events.append(events[cid][i])
|
||||
events[cid] = new_events
|
||||
|
||||
for cid, event_list in events.items():
|
||||
conn = _conn_base.copy()
|
||||
conn['connectionid'] = cid
|
||||
conn['starttime'] = start_time[cid]
|
||||
conn['events'] = event_list
|
||||
qlog['connections'].append(conn)
|
||||
|
||||
print(json.dumps(qlog, indent=2))
|
||||
|
Loading…
Reference in a new issue