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
//! # Heartbeat Policy -- Spec §21
//!
//! This module defines the heartbeat configuration that the server sends
//! to the client during the **Ready** phase of the handshake (spec §5.5).
//! The heartbeat mechanism ensures both sides can detect unresponsive
//! peers promptly.
//!
//! ## How It Works
//!
//! 1. The client sends a **Ping** frame at least every `ping_interval`.
//! 2. The server must reply with a **Pong** frame within `pong_timeout`.
//! 3. If `max_missed_pongs` consecutive Pongs are not received, the
//! connection is considered dead and will be closed.
//! 4. Any frame received from the remote peer also acts as a heartbeat
//! (liveness signal), resetting the idle timer.
//!
//! ## Jitter
//!
//! To prevent a "thundering herd" of simultaneous heartbeats from many
//! clients, a random jitter of up to `jitter` milliseconds is added to
//! the effective ping interval on the client side (spec §27.1).
//!
//! ## Default Values
//!
//! The [`Default`] implementation provides sensible defaults for ordinary
//! web applications, as specified in §27.1:
//!
//! | Field | Default |
//! |-------------------|-----------|
//! | `ping_interval` | 25 000 ms |
//! | `pong_timeout` | 10 000 ms |
//! | `max_missed_pongs`| 2 |
//! | `idle_timeout` | 300 s |
//! | `jitter` | 2 500 ms |
//!
//! ## Relationship to Other Modules
//!
//! The `Ready` frame in [`hello`](super::hello) carries the effective
//! heartbeat parameters for a given connection. The close code
//! [`CloseCode::IdleTimeout`](super::close::CloseCode::IdleTimeout) is
//! used when the idle timeout fires.
use Duration;
/// Heartbeat configuration sent to the client during the Ready phase.
///
/// The server includes this policy in its `Ready` frame so the client
/// knows how frequently to send Ping frames and how long to wait for
/// Pong replies before considering the connection degraded.
///
/// ## Effective Ping Interval
///
/// The actual interval between Ping frames on the client side is:
///
/// ```text
/// effective = ping_interval + random(0 ..= jitter)
/// ```
///
/// This prevents many clients from sending heartbeats at the exact same
/// instant, which could cause a "thundering herd" spike in frame traffic.
///
/// ## Dead Connection Detection
///
/// A connection is deemed dead when `max_missed_pongs` consecutive Ping
/// frames have been sent without receiving a Pong (or any other frame)
/// back. At that point the connection is closed with an appropriate
/// close code.