1
2
3
4
5 package http3
6
7 import (
8 "context"
9 "io"
10 "os"
11 "sync"
12 "time"
13
14 "golang.org/x/net/quic"
15 )
16
17
18 type stream struct {
19 stream *quic.Stream
20
21
22
23
24
25
26 lim int64
27
28 readDeadline deadline
29 writeDeadline deadline
30 }
31
32
33
34
35
36
37
38 func newConnStream(ctx context.Context, qconn *quic.Conn, stype streamType) (*stream, error) {
39 var qs *quic.Stream
40 var err error
41 if stype == streamTypeRequest {
42
43 qs, err = qconn.NewStream(ctx)
44 } else {
45
46 qs, err = qconn.NewSendOnlyStream(ctx)
47 }
48 if err != nil {
49 return nil, err
50 }
51 st := newStream(qs)
52 if stype != streamTypeRequest {
53
54 st.writeVarint(int64(stype))
55 }
56 return st, err
57 }
58
59 func newStream(qs *quic.Stream) *stream {
60 readCtx, readCancel := context.WithCancelCause(context.Background())
61 writeCtx, writeCancel := context.WithCancelCause(context.Background())
62 st := &stream{
63 stream: qs,
64 lim: -1,
65 readDeadline: deadline{
66 ctx: readCtx,
67 cancel: readCancel,
68 },
69 writeDeadline: deadline{
70 ctx: writeCtx,
71 cancel: writeCancel,
72 },
73 }
74 qs.SetReadContext(readCtx)
75 qs.SetWriteContext(writeCtx)
76 return st
77 }
78
79 func (st *stream) Close() error {
80 st.readDeadline.stop()
81 st.writeDeadline.stop()
82 return st.stream.Close()
83 }
84
85 func (st *stream) CloseRead() {
86 st.readDeadline.stop()
87 st.stream.CloseRead()
88 }
89
90 func (st *stream) CloseWrite() {
91 st.writeDeadline.stop()
92 st.stream.CloseWrite()
93 }
94
95 func (st *stream) Reset(code uint64) {
96 st.readDeadline.stop()
97 st.writeDeadline.stop()
98 st.stream.Reset(code)
99 }
100
101
102
103
104
105
106
107
108 type deadline struct {
109 ctx context.Context
110 cancel context.CancelCauseFunc
111
112 mu sync.Mutex
113 timer *time.Timer
114 }
115
116
117
118 func (d *deadline) stopTimerLocked() {
119 if d.timer != nil {
120 d.timer.Stop()
121 d.timer = nil
122 }
123 }
124
125
126
127 func (d *deadline) stop() {
128 d.mu.Lock()
129 d.stopTimerLocked()
130 d.mu.Unlock()
131 d.cancel(context.Canceled)
132 }
133
134
135 func (d *deadline) err() error {
136 return context.Cause(d.ctx)
137 }
138
139
140
141
142 func (d *deadline) errOf(err error) error {
143 if dErr := d.err(); err != nil && dErr != nil {
144 return dErr
145 }
146 return err
147 }
148
149
150
151
152 func (d *deadline) set(deadlineTime time.Time) {
153 d.mu.Lock()
154 defer d.mu.Unlock()
155
156 if d.ctx.Err() != nil {
157 return
158 }
159 if deadlineTime.IsZero() {
160 d.stopTimerLocked()
161 return
162 }
163 dur := time.Until(deadlineTime)
164 if dur <= 0 {
165 d.stopTimerLocked()
166 d.cancel(os.ErrDeadlineExceeded)
167 return
168 }
169 if d.timer == nil {
170 d.timer = time.AfterFunc(dur, func() {
171 d.cancel(os.ErrDeadlineExceeded)
172 })
173 } else {
174 d.timer.Reset(dur)
175 }
176 }
177
178
179
180
181
182 func (st *stream) readFrameHeader() (ftype frameType, err error) {
183 if st.lim >= 0 {
184
185 return 0, errH3FrameError
186 }
187 ftype, err = readVarint[frameType](st)
188 if err != nil {
189 return 0, err
190 }
191 size, err := st.readVarint()
192 if err != nil {
193 return 0, err
194 }
195 st.lim = size
196 return ftype, nil
197 }
198
199
200
201 func (st *stream) endFrame() error {
202 if st.lim != 0 {
203 return &connectionError{
204 code: errH3FrameError,
205 message: "invalid HTTP/3 frame",
206 }
207 }
208 st.lim = -1
209 return nil
210 }
211
212
213 func (st *stream) readFrameData() ([]byte, error) {
214 if st.lim < 0 {
215 return nil, errH3FrameError
216 }
217
218 b := make([]byte, st.lim)
219 _, err := io.ReadFull(st, b)
220 if err != nil {
221 return nil, err
222 }
223 return b, nil
224 }
225
226
227 func (st *stream) ReadByte() (b byte, err error) {
228
229
230
231
232
233
234 if err := st.readDeadline.err(); err != nil {
235 return 0, err
236 }
237 if err := st.recordBytesRead(1); err != nil {
238 return 0, err
239 }
240 b, err = st.stream.ReadByte()
241 if err == io.EOF && st.lim >= 0 {
242 return 0, errH3FrameError
243 }
244 return b, st.readDeadline.errOf(err)
245 }
246
247
248 func (st *stream) Read(b []byte) (int, error) {
249
250
251
252
253
254
255 if err := st.readDeadline.err(); err != nil {
256 return 0, err
257 }
258 n, err := st.stream.Read(b)
259 if e2 := st.recordBytesRead(n); e2 != nil {
260 return 0, e2
261 }
262 if err == io.EOF {
263 if st.lim == 0 {
264
265 return n, nil
266 } else if st.lim > 0 {
267
268 return 0, errH3FrameError
269 } else {
270
271 return n, io.EOF
272 }
273 }
274 return n, st.readDeadline.errOf(err)
275 }
276
277
278
279
280
281
282 func (st *stream) discardUnknownFrame(ftype frameType) error {
283 switch ftype {
284 case frameTypeData,
285 frameTypeHeaders,
286 frameTypeCancelPush,
287 frameTypeSettings,
288 frameTypePushPromise,
289 frameTypeGoaway,
290 frameTypeMaxPushID:
291 return &connectionError{
292 code: errH3FrameUnexpected,
293 message: "unexpected " + ftype.String() + " frame",
294 }
295 }
296 return st.discardFrame()
297 }
298
299
300 func (st *stream) discardFrame() error {
301
302 for range st.lim {
303 _, err := st.ReadByte()
304 if err != nil {
305 return &streamError{errH3FrameError, err.Error()}
306 }
307 }
308 st.lim = -1
309 return nil
310 }
311
312
313 func (st *stream) Write(b []byte) (int, error) {
314
315
316
317
318
319
320 if err := st.writeDeadline.err(); err != nil {
321 return 0, err
322 }
323 n, err := st.stream.Write(b)
324 return n, st.writeDeadline.errOf(err)
325 }
326
327
328 func (st *stream) Flush() error {
329
330
331
332
333
334
335 if err := st.writeDeadline.err(); err != nil {
336 return err
337 }
338 return st.writeDeadline.errOf(st.stream.Flush())
339 }
340
341
342 func (st *stream) WriteByte(c byte) error {
343
344
345
346
347
348
349 if err := st.writeDeadline.err(); err != nil {
350 return err
351 }
352 return st.writeDeadline.errOf(st.stream.WriteByte(c))
353 }
354
355
356 func (st *stream) readVarint() (v int64, err error) {
357 b, err := st.ReadByte()
358 if err != nil {
359 return 0, err
360 }
361 v = int64(b & 0x3f)
362 n := 1 << (b >> 6)
363 for i := 1; i < n; i++ {
364 b, err := st.ReadByte()
365 if err != nil {
366 if err == io.EOF {
367 return 0, errH3FrameError
368 }
369 return 0, err
370 }
371 v = (v << 8) | int64(b)
372 }
373 return v, nil
374 }
375
376
377 func readVarint[T ~int64 | ~uint64](st *stream) (T, error) {
378 v, err := st.readVarint()
379 return T(v), err
380 }
381
382
383 func (st *stream) writeVarint(v int64) {
384 switch {
385 case v <= (1<<6)-1:
386 st.WriteByte(byte(v))
387 case v <= (1<<14)-1:
388 st.WriteByte((1 << 6) | byte(v>>8))
389 st.WriteByte(byte(v))
390 case v <= (1<<30)-1:
391 st.WriteByte((2 << 6) | byte(v>>24))
392 st.WriteByte(byte(v >> 16))
393 st.WriteByte(byte(v >> 8))
394 st.WriteByte(byte(v))
395 case v <= (1<<62)-1:
396 st.WriteByte((3 << 6) | byte(v>>56))
397 st.WriteByte(byte(v >> 48))
398 st.WriteByte(byte(v >> 40))
399 st.WriteByte(byte(v >> 32))
400 st.WriteByte(byte(v >> 24))
401 st.WriteByte(byte(v >> 16))
402 st.WriteByte(byte(v >> 8))
403 st.WriteByte(byte(v))
404 default:
405 panic("varint too large")
406 }
407 }
408
409
410
411 func (st *stream) recordBytesRead(n int) error {
412 if st.lim < 0 {
413 return nil
414 }
415 st.lim -= int64(n)
416 if st.lim < 0 {
417 st.stream = nil
418 return &connectionError{
419 code: errH3FrameError,
420 message: "invalid HTTP/3 frame",
421 }
422 }
423 return nil
424 }
425
View as plain text