1
2
3
4
5
6
7 package quic
8
9 import (
10 "context"
11 "crypto/tls"
12 "fmt"
13 "testing"
14 "time"
15 )
16
17 func TestHandshakeTimeoutExpiresServer(t *testing.T) {
18 const timeout = 5 * time.Second
19 tc := newTestConn(t, serverSide, func(c *Config) {
20 c.HandshakeTimeout = timeout
21 })
22 tc.ignoreFrame(frameTypeAck)
23 tc.ignoreFrame(frameTypeNewConnectionID)
24 tc.writeFrames(packetTypeInitial,
25 debugFrameCrypto{
26 data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
27 })
28
29
30 tc.wantFrameType("server sends Initial CRYPTO flight",
31 packetTypeInitial, debugFrameCrypto{})
32 tc.writeAckForAll()
33 tc.wantFrameType("server sends Handshake CRYPTO flight",
34 packetTypeHandshake, debugFrameCrypto{})
35 tc.writeAckForAll()
36
37 if got, want := tc.timerDelay(), timeout; got != want {
38 t.Errorf("connection timer = %v, want %v (handshake timeout)", got, want)
39 }
40
41
42 tc.advance(1 * time.Second)
43 tc.writeFrames(packetTypeHandshake, debugFrameCrypto{
44 data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake][:1],
45 })
46 tc.wantIdle("handshake is not complete")
47
48 tc.advance(timeout - 1*time.Second)
49 tc.wantFrame("server closes connection after handshake timeout",
50 packetTypeHandshake, debugFrameConnectionCloseTransport{
51 code: errConnectionRefused,
52 })
53 }
54
55 func TestHandshakeTimeoutExpiresClient(t *testing.T) {
56 const timeout = 5 * time.Second
57 tc := newTestConn(t, clientSide, func(c *Config) {
58 c.HandshakeTimeout = timeout
59 })
60 tc.ignoreFrame(frameTypeAck)
61 tc.ignoreFrame(frameTypeNewConnectionID)
62
63
64
65
66 tc.wantFrameType("client sends Initial CRYPTO flight",
67 packetTypeInitial, debugFrameCrypto{})
68 tc.writeAckForAll()
69 tc.writeFrames(packetTypeInitial,
70 debugFrameCrypto{
71 data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
72 })
73 tc.writeFrames(packetTypeHandshake,
74 debugFrameCrypto{
75 data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake],
76 })
77 tc.wantFrameType("client sends Handshake CRYPTO flight",
78 packetTypeHandshake, debugFrameCrypto{})
79 tc.writeAckForAll()
80 tc.wantIdle("client is waiting for end of handshake")
81
82 if got, want := tc.timerDelay(), timeout; got != want {
83 t.Errorf("connection timer = %v, want %v (handshake timeout)", got, want)
84 }
85 tc.advance(timeout)
86 tc.wantFrame("client closes connection after handshake timeout",
87 packetTypeHandshake, debugFrameConnectionCloseTransport{
88 code: errConnectionRefused,
89 })
90 }
91
92 func TestIdleTimeoutExpires(t *testing.T) {
93 for _, test := range []struct {
94 localMaxIdleTimeout time.Duration
95 peerMaxIdleTimeout time.Duration
96 wantTimeout time.Duration
97 }{{
98 localMaxIdleTimeout: 10 * time.Second,
99 peerMaxIdleTimeout: 20 * time.Second,
100 wantTimeout: 10 * time.Second,
101 }, {
102 localMaxIdleTimeout: 20 * time.Second,
103 peerMaxIdleTimeout: 10 * time.Second,
104 wantTimeout: 10 * time.Second,
105 }, {
106 localMaxIdleTimeout: 0,
107 peerMaxIdleTimeout: 10 * time.Second,
108 wantTimeout: 10 * time.Second,
109 }, {
110 localMaxIdleTimeout: 10 * time.Second,
111 peerMaxIdleTimeout: 0,
112 wantTimeout: 10 * time.Second,
113 }} {
114 name := fmt.Sprintf("local=%v/peer=%v", test.localMaxIdleTimeout, test.peerMaxIdleTimeout)
115 t.Run(name, func(t *testing.T) {
116 tc := newTestConn(t, serverSide, func(p *transportParameters) {
117 p.maxIdleTimeout = test.peerMaxIdleTimeout
118 }, func(c *Config) {
119 c.MaxIdleTimeout = test.localMaxIdleTimeout
120 })
121 tc.handshake()
122 if got, want := tc.timeUntilEvent(), test.wantTimeout; got != want {
123 t.Errorf("new conn timeout=%v, want %v (idle timeout)", got, want)
124 }
125 tc.advance(test.wantTimeout - 1)
126 tc.wantIdle("connection is idle and alive prior to timeout")
127 ctx := canceledContext()
128 if err := tc.conn.Wait(ctx); err != context.Canceled {
129 t.Fatalf("conn.Wait() = %v, want Canceled", err)
130 }
131 tc.advance(1)
132 tc.wantIdle("connection exits after timeout")
133 if err := tc.conn.Wait(ctx); err != errIdleTimeout {
134 t.Fatalf("conn.Wait() = %v, want errIdleTimeout", err)
135 }
136 })
137 }
138 }
139
140 func TestIdleTimeoutKeepAlive(t *testing.T) {
141 for _, test := range []struct {
142 idleTimeout time.Duration
143 keepAlive time.Duration
144 wantTimeout time.Duration
145 }{{
146 idleTimeout: 30 * time.Second,
147 keepAlive: 10 * time.Second,
148 wantTimeout: 10 * time.Second,
149 }, {
150 idleTimeout: 10 * time.Second,
151 keepAlive: 30 * time.Second,
152 wantTimeout: 5 * time.Second,
153 }, {
154 idleTimeout: -1,
155 keepAlive: 30 * time.Second,
156 wantTimeout: 30 * time.Second,
157 }} {
158 name := fmt.Sprintf("idle_timeout=%v/keepalive=%v", test.idleTimeout, test.keepAlive)
159 t.Run(name, func(t *testing.T) {
160 tc := newTestConn(t, serverSide, func(c *Config) {
161 c.MaxIdleTimeout = test.idleTimeout
162 c.KeepAlivePeriod = test.keepAlive
163 })
164 tc.handshake()
165 if got, want := tc.timeUntilEvent(), test.wantTimeout; got != want {
166 t.Errorf("new conn timeout=%v, want %v (keepalive timeout)", got, want)
167 }
168 tc.advance(test.wantTimeout - 1)
169 tc.wantIdle("connection is idle prior to timeout")
170 tc.advance(1)
171 tc.wantFrameType("keep-alive ping is sent", packetType1RTT,
172 debugFramePing{})
173 })
174 }
175 }
176
177 func TestIdleLongTermKeepAliveSent(t *testing.T) {
178
179 const keepAlivePeriod = 30 * time.Second
180 tc := newTestConn(t, clientSide, func(c *Config) {
181 c.KeepAlivePeriod = keepAlivePeriod
182 c.MaxIdleTimeout = -1
183 })
184 tc.handshake()
185
186
187
188 tc.writeFrames(packetType1RTT, debugFramePing{})
189 tc.writeFrames(packetType1RTT, debugFramePing{})
190 tc.wantFrameType("conn acks received pings", packetType1RTT, debugFrameAck{})
191 for i := 0; i < 10; i++ {
192 tc.wantIdle("conn has nothing more to send")
193 if got, want := tc.timeUntilEvent(), keepAlivePeriod; got != want {
194 t.Errorf("i=%v conn timeout=%v, want %v (keepalive timeout)", i, got, want)
195 }
196 tc.advance(keepAlivePeriod)
197 tc.wantFrameType("keep-alive ping is sent", packetType1RTT,
198 debugFramePing{})
199 tc.writeAckForAll()
200 }
201 }
202
203 func TestIdleLongTermKeepAliveReceived(t *testing.T) {
204
205
206 const idleTimeout = 30 * time.Second
207 tc := newTestConn(t, serverSide, func(c *Config) {
208 c.MaxIdleTimeout = idleTimeout
209 })
210 tc.handshake()
211 for i := 0; i < 10; i++ {
212 tc.advance(idleTimeout - 1*time.Second)
213 tc.writeFrames(packetType1RTT, debugFramePing{})
214 if got, want := tc.timeUntilEvent(), maxAckDelay-timerGranularity; got != want {
215 t.Errorf("i=%v conn timeout=%v, want %v (max_ack_delay)", i, got, want)
216 }
217 tc.advanceToTimer()
218 tc.wantFrameType("conn acks received ping", packetType1RTT, debugFrameAck{})
219 }
220
221 ctx := canceledContext()
222 if err := tc.conn.Wait(ctx); err != context.Canceled {
223 t.Fatalf("conn.Wait() = %v, want Canceled", err)
224 }
225 }
226
View as plain text