@@ -34,6 +34,10 @@ extern "C" {
34
34
#include <inttypes.h>
35
35
#include <string.h>
36
36
#include <sys/types.h>
37
+ #ifndef _WINDOWS
38
+ #include <netinet/in.h>
39
+ #include <arpa/inet.h>
40
+ #endif
37
41
38
42
#if __GNUC__ >= 3
39
43
#define PTLS_LIKELY (x ) __builtin_expect(!!(x), 1)
@@ -64,8 +68,15 @@ extern "C" {
64
68
#define PTLS_THREADLOCAL __declspec(thread)
65
69
#else
66
70
#define PTLS_THREADLOCAL __thread
71
+ #endif
72
+
73
+ #ifndef PTLS_HAVE_LOG
74
+ #ifdef _WINDOWS
75
+ #define PTLS_HAVE_LOG 0
76
+ #else
67
77
#define PTLS_HAVE_LOG 1
68
78
#endif
79
+ #endif
69
80
70
81
#ifndef PTLS_FUZZ_HANDSHAKE
71
82
#define PTLS_FUZZ_HANDSHAKE 0
@@ -1386,35 +1397,44 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end);
1386
1397
ptls_decode_assert_block_close((src), end); \
1387
1398
} while (0)
1388
1399
1389
- #define PTLS_LOG__DO_LOG (module , type , block ) \
1400
+ #define PTLS_LOG__DO_LOG (module , name , conn_state , get_sni , get_sni_arg , add_time , block ) \
1390
1401
do { \
1391
- int ptlslog_skip = 0; \
1392
- char smallbuf[128]; \
1393
- ptls_buffer_t ptlslogbuf; \
1394
- ptls_buffer_init(&ptlslogbuf, smallbuf, sizeof(smallbuf)); \
1395
- PTLS_LOG__DO_PUSH_SAFESTR("{\"module\":\"" PTLS_TO_STR(module) "\",\"type\":\"" PTLS_TO_STR(type) "\""); \
1402
+ int ptlslog_skip = 0, ptlslog_include_appdata = 0; \
1396
1403
do { \
1397
- block \
1398
- } while (0); \
1399
- PTLS_LOG__DO_PUSH_SAFESTR("}\n"); \
1400
- if (!ptlslog_skip) \
1401
- ptls_log__do_write(&ptlslogbuf); \
1402
- ptls_buffer_dispose(&ptlslogbuf); \
1404
+ char smallbuf[128]; \
1405
+ ptls_buffer_t ptlslogbuf; \
1406
+ ptls_log__do_write_start(&logpoint, &ptlslogbuf, smallbuf, sizeof(smallbuf), (add_time)); \
1407
+ do { \
1408
+ block \
1409
+ } while (0); \
1410
+ ptlslog_include_appdata = ptls_log__do_write_end(ptlslog_skip ? NULL : &logpoint, (conn_state), (get_sni), \
1411
+ (get_sni_arg), &ptlslogbuf, ptlslog_include_appdata); \
1412
+ } while (ptlslog_include_appdata); \
1403
1413
} while (0)
1404
1414
1405
- #define PTLS_LOG (module , type , block ) \
1415
+ #define PTLS_LOG_DEFINE_POINT (_module , _name , _var ) \
1416
+ static struct st_ptls_log_point_t _var = {.name = PTLS_TO_STR(_module) ":" PTLS_TO_STR(_name)}
1417
+
1418
+ #define PTLS_LOG (module , name , block ) \
1406
1419
do { \
1407
- if (!ptls_log.is_active) \
1420
+ PTLS_LOG_DEFINE_POINT(module, name, logpoint); \
1421
+ if (ptls_log_point_maybe_active(&logpoint) == 0) \
1408
1422
break; \
1409
- PTLS_LOG__DO_LOG(( module), (type), (block)); \
1423
+ PTLS_LOG__DO_LOG(module, name, NULL, NULL, NULL, 1, {block}); \
1410
1424
} while (0)
1411
1425
1412
- #define PTLS_LOG_CONN (type , tls , block ) \
1426
+ #define PTLS_LOG_CONN (name , tls , block ) \
1413
1427
do { \
1428
+ PTLS_LOG_DEFINE_POINT(picotls, name, logpoint); \
1429
+ uint32_t active = ptls_log_point_maybe_active(&logpoint); \
1430
+ if (active == 0) \
1431
+ break; \
1414
1432
ptls_t *_tls = (tls); \
1415
- if (!ptls_log.is_active || ptls_skip_tracing(_tls)) \
1433
+ ptls_log_conn_state_t *conn_state = ptls_get_log_state(_tls); \
1434
+ active &= ptls_log_conn_maybe_active(conn_state, (const char *(*)(void *))ptls_get_server_name, _tls); \
1435
+ if (active == 0) \
1416
1436
break; \
1417
- PTLS_LOG__DO_LOG(picotls, type, { \
1437
+ PTLS_LOG__DO_LOG(picotls, name, conn_state, (const char *(*)(void *))ptls_get_server_name, _tls, 1, { \
1418
1438
PTLS_LOG_ELEMENT_PTR(tls, _tls); \
1419
1439
do { \
1420
1440
block \
@@ -1461,14 +1481,14 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end);
1461
1481
#define PTLS_LOG_APPDATA_ELEMENT_UNSAFESTR (name , value , value_len ) \
1462
1482
do { \
1463
1483
size_t _len = (value_len); \
1464
- if (ptls_log.include_appdata) \
1484
+ if (ptlslog_include_appdata) \
1465
1485
PTLS_LOG_ELEMENT_UNSAFESTR(name, value, _len); \
1466
1486
PTLS_LOG_ELEMENT__DO_UNSIGNED(name, "_len", _len); \
1467
1487
} while (0)
1468
1488
#define PTLS_LOG_APPDATA_ELEMENT_HEXDUMP (name , value , value_len ) \
1469
1489
do { \
1470
1490
size_t _len = (value_len); \
1471
- if (ptls_log.include_appdata) \
1491
+ if (ptlslog_include_appdata) \
1472
1492
PTLS_LOG_ELEMENT_HEXDUMP(name, value, _len); \
1473
1493
PTLS_LOG_ELEMENT__DO_UNSIGNED(name, "_len", _len); \
1474
1494
} while (0)
@@ -1514,27 +1534,100 @@ uint64_t ptls_decode_quicint(const uint8_t **src, const uint8_t *end);
1514
1534
} while (0)
1515
1535
1516
1536
/**
1517
- * User API is exposed only when logging is supported by the platform.
1537
+ * retains a list of connections that are bound to the object
1538
+ */
1539
+ struct st_ptls_log_state_t {
1540
+ /**
1541
+ * bit array of connections (1 is active)
1542
+ */
1543
+ uint32_t active_conns ;
1544
+ /**
1545
+ * generation counter used for staleness check; see `ptls_log._generation`
1546
+ */
1547
+ uint64_t generation ;
1548
+ };
1549
+
1550
+ /**
1551
+ * represents a log point identified by name (`module:type`)
1552
+ */
1553
+ struct st_ptls_log_point_t {
1554
+ const char * name ;
1555
+ struct st_ptls_log_state_t state ;
1556
+ };
1557
+
1558
+ /**
1559
+ * represents a logging state of each connection
1560
+ */
1561
+ typedef struct st_ptls_log_conn_state_t {
1562
+ /**
1563
+ * random value between 0 (inclusive) and 1 (non-inclusive) used to determine the ratio of sampling-based logging; see
1564
+ * `ptls_add_fd'`. To disable logging entirely, use `ptls_log.dummy_conn_state`, or set the value exactly to 1.
1565
+ */
1566
+ float random_ ;
1567
+ /**
1568
+ * represents peer address; ipv4 addresses are stored using the mapped form (::ffff:192.0.2.1)
1569
+ */
1570
+ struct in6_addr address ;
1571
+ struct st_ptls_log_state_t state ;
1572
+ } ptls_log_conn_state_t ;
1573
+
1574
+ /**
1575
+ * see `ptls_get_log_state`
1576
+ */
1577
+ extern PTLS_THREADLOCAL ptls_log_conn_state_t * ptls_log_conn_state_override ;
1578
+
1579
+ /**
1580
+ * global variables exposed
1581
+ */
1582
+ extern struct st_ptls_log_t {
1583
+ /**
1584
+ * if application-data (e.g., payload) should be emitted as well
1585
+ */
1586
+ volatile unsigned may_include_appdata : 1 ;
1587
+ /**
1588
+ * endpoints that want to disable logging entirely can provide this value to the loggers
1589
+ */
1590
+ ptls_log_conn_state_t dummy_conn_state ;
1591
+ /**
1592
+ * generation counter that is incremented whenever the state of loggers change; see `st_ptls_log_state_t::generation`
1593
+ */
1594
+ volatile uint64_t _generation ;
1595
+ } ptls_log ;
1596
+
1597
+ /**
1598
+ * initializes a ptls_log_conn_state_t
1599
+ */
1600
+ void ptls_log_init_conn_state (ptls_log_conn_state_t * state , void (* random_bytes )(void * , size_t ));
1601
+ /**
1602
+ * forces recalculation of the log state (should be called when SNI is determined)
1518
1603
*/
1519
- typedef struct st_ptls_log_t {
1520
- unsigned is_active : 1 ;
1521
- unsigned include_appdata : 1 ;
1522
- } ptls_log_t ;
1604
+ static void ptls_log_recalc_conn_state (ptls_log_conn_state_t * state );
1605
+ /**
1606
+ * returns a bitmap indicating the loggers active for given log point
1607
+ */
1608
+ static uint32_t ptls_log_point_maybe_active (struct st_ptls_log_point_t * point );
1609
+ /**
1610
+ * returns a bitmap indicating the loggers active for given connection
1611
+ */
1612
+ static uint32_t ptls_log_conn_maybe_active (ptls_log_conn_state_t * conn , const char * (* get_sni )(void * ), void * get_sni_arg );
1523
1613
1524
- #if PTLS_HAVE_LOG
1525
- extern volatile ptls_log_t ptls_log ;
1526
1614
/**
1527
1615
* Returns the number of log events that were unable to be emitted.
1528
1616
*/
1529
1617
size_t ptls_log_num_lost (void );
1530
1618
/**
1531
- * Registers an fd to the logger. A registered fd is automatically closed and removed if it is invalidated.
1619
+ * Registers an fd to the logger. A registered fd is automatically closed and removed when it is closed by the peer.
1620
+ * @param sample_ratio sampling ratio between 0 and 1
1621
+ * @param points list of points to log, in the form of p1\0p2\0\0 (i.e., concatenated list of C strings with an empty string
1622
+ * marking the end). An empty list means attach to all.
1623
+ * @param snis list of SNIs to log, using the same form as points
1624
+ * @param addresses list of IPv4/v6 addresses to log, using the same form as points
1532
1625
*/
1533
- int ptls_log_add_fd (int fd );
1534
- #else
1535
- static const ptls_log_t ptls_log = {0 };
1536
- #endif
1626
+ int ptls_log_add_fd (int fd , float sample_ratio , const char * points , const char * snis , const char * addresses , int appdata );
1537
1627
1628
+ void ptls_log__recalc_point (int caller_locked , struct st_ptls_log_point_t * point );
1629
+ void ptls_log__recalc_conn (int caller_locked , struct st_ptls_log_conn_state_t * conn , const char * (* get_sni )(void * ),
1630
+ void * get_sni_arg );
1538
1631
static int ptls_log__do_push_safestr (ptls_buffer_t * buf , const char * s );
1539
1632
int ptls_log__do_push_unsafestr (ptls_buffer_t * buf , const char * s , size_t l );
1540
1633
int ptls_log__do_push_hexdump (ptls_buffer_t * buf , const void * s , size_t l );
@@ -1543,7 +1636,10 @@ int ptls_log__do_push_signed32(ptls_buffer_t *buf, int32_t v);
1543
1636
int ptls_log__do_push_signed64 (ptls_buffer_t * buf , int64_t v );
1544
1637
int ptls_log__do_push_unsigned32 (ptls_buffer_t * buf , uint32_t v );
1545
1638
int ptls_log__do_push_unsigned64 (ptls_buffer_t * buf , uint64_t v );
1546
- void ptls_log__do_write (const ptls_buffer_t * buf );
1639
+ void ptls_log__do_write_start (struct st_ptls_log_point_t * point , ptls_buffer_t * buf , void * smallbuf , size_t smallbufsize ,
1640
+ int add_time );
1641
+ int ptls_log__do_write_end (struct st_ptls_log_point_t * point , struct st_ptls_log_conn_state_t * conn , const char * (* get_sni )(void * ),
1642
+ void * get_sni_arg , ptls_buffer_t * buf , int includes_appdata );
1547
1643
1548
1644
/**
1549
1645
* create a client object to handle new TLS connection
@@ -1648,13 +1744,11 @@ int ptls_is_ech_handshake(ptls_t *tls, uint8_t *config_id, ptls_hpke_kem_t **kem
1648
1744
*/
1649
1745
void * * ptls_get_data_ptr (ptls_t * tls );
1650
1746
/**
1651
- *
1747
+ * Returns `ptls_log_conn_state_t` of `ptls_t`. By default, the state is initialized by calling `ptls_log_init_conn_state`, but the
1748
+ * behavior can be overidden by setting `ptls_log_conn_state_override`.
1749
+ * This value can be changed by setting `ptls_log_random_override` or by calling `ptls_set_log_random`.
1652
1750
*/
1653
- int ptls_skip_tracing (ptls_t * tls );
1654
- /**
1655
- *
1656
- */
1657
- void ptls_set_skip_tracing (ptls_t * tls , int skip_tracing );
1751
+ ptls_log_conn_state_t * ptls_get_log_state (ptls_t * tls );
1658
1752
/**
1659
1753
* proceeds with the handshake, optionally taking some input from peer. The function returns zero in case the handshake completed
1660
1754
* successfully. PTLS_ERROR_IN_PROGRESS is returned in case the handshake is incomplete. Otherwise, an error value is returned. The
@@ -1890,6 +1984,11 @@ char *ptls_hexdump(char *dst, const void *src, size_t len);
1890
1984
* Builds a JSON-safe string without double quotes. Supplied buffer MUST be at least 6x + 1 bytes larger than the input.
1891
1985
*/
1892
1986
char * ptls_jsonescape (char * buf , const char * s , size_t len );
1987
+ /**
1988
+ * builds a v4-mapped address (i.e., ::ffff:192.0.2.1)
1989
+ */
1990
+ void ptls_build_v4_mapped_v6_address (struct in6_addr * v6 , const struct in_addr * v4 );
1991
+
1893
1992
/**
1894
1993
* the default get_time callback
1895
1994
*/
@@ -1898,17 +1997,32 @@ extern ptls_get_time_t ptls_get_time;
1898
1997
* default hash clone function that calls memcpy
1899
1998
*/
1900
1999
static void ptls_hash_clone_memcpy (void * dst , const void * src , size_t size );
1901
- #if defined(PICOTLS_USE_DTRACE ) && PICOTLS_USE_DTRACE
1902
- /**
1903
- *
1904
- */
1905
- extern PTLS_THREADLOCAL unsigned ptls_default_skip_tracing ;
1906
- #else
1907
- #define ptls_default_skip_tracing 0
1908
- #endif
1909
2000
1910
2001
/* inline functions */
1911
2002
2003
+ inline uint32_t ptls_log_point_maybe_active (struct st_ptls_log_point_t * point )
2004
+ {
2005
+ if (!PTLS_HAVE_LOG )
2006
+ return 0 ;
2007
+ if (PTLS_UNLIKELY (point -> state .generation != ptls_log ._generation ))
2008
+ ptls_log__recalc_point (0 , point );
2009
+ return point -> state .active_conns ;
2010
+ }
2011
+
2012
+ inline void ptls_log_recalc_conn_state (ptls_log_conn_state_t * state )
2013
+ {
2014
+ state -> state .generation = 0 ;
2015
+ }
2016
+
2017
+ inline uint32_t ptls_log_conn_maybe_active (ptls_log_conn_state_t * conn , const char * (* get_sni )(void * ), void * get_sni_arg )
2018
+ {
2019
+ if (!PTLS_HAVE_LOG )
2020
+ return 0 ;
2021
+ if (PTLS_UNLIKELY (conn -> state .generation != ptls_log ._generation ))
2022
+ ptls_log__recalc_conn (0 , conn , get_sni , get_sni_arg );
2023
+ return conn -> state .active_conns ;
2024
+ }
2025
+
1912
2026
inline int ptls_log__do_push_safestr (ptls_buffer_t * buf , const char * s )
1913
2027
{
1914
2028
return ptls_log__do_pushv (buf , s , strlen (s ));
0 commit comments