-
-
Notifications
You must be signed in to change notification settings - Fork 85
Expand file tree
/
Copy pathflow_control.go
More file actions
107 lines (90 loc) · 2.38 KB
/
Copy pathflow_control.go
File metadata and controls
107 lines (90 loc) · 2.38 KB
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
package webtransport
import (
"errors"
"fmt"
"sync"
)
var errMaxDataNotIncreased = errors.New("webtransport: WT_MAX_DATA capsule didn't increase data limit")
type outgoingDataFlowController struct {
mx sync.Mutex
maxData int64
bytesSent int64
lastBlockedAt int64
updated chan struct{}
}
func newOutgoingDataFlowController(maxData int64) *outgoingDataFlowController {
return &outgoingDataFlowController{
maxData: maxData,
lastBlockedAt: -1,
updated: make(chan struct{}),
}
}
func (f *outgoingDataFlowController) AddBytesSent(n int64) int64 {
f.mx.Lock()
defer f.mx.Unlock()
var added int64
if f.bytesSent < f.maxData {
added = min(n, f.maxData-f.bytesSent)
}
f.bytesSent += added
return added
}
func (f *outgoingDataFlowController) IsNewlyBlocked() (bool, int64) {
f.mx.Lock()
defer f.mx.Unlock()
if f.bytesSent < f.maxData || f.maxData == f.lastBlockedAt {
return false, 0
}
f.lastBlockedAt = f.maxData
return true, f.maxData
}
func (f *outgoingDataFlowController) UpdateMaxData(maxData int64) error {
f.mx.Lock()
defer f.mx.Unlock()
if maxData <= f.maxData {
return fmt.Errorf("%w: current limit: %d, received limit: %d", errMaxDataNotIncreased, f.maxData, maxData)
}
f.maxData = maxData
close(f.updated)
f.updated = make(chan struct{})
return nil
}
func (f *outgoingDataFlowController) NextUpdate() <-chan struct{} {
f.mx.Lock()
updated := f.updated
f.mx.Unlock()
return updated
}
type incomingDataFlowController struct {
mx sync.Mutex
bytesRead int64
maxData int64
receiveWindow int64
queueWindowUpdate func(int64)
}
func newIncomingDataFlowController(bytesRead, maxData int64, queueWindowUpdate func(int64)) *incomingDataFlowController {
return &incomingDataFlowController{
bytesRead: bytesRead,
maxData: maxData,
receiveWindow: maxData - bytesRead,
queueWindowUpdate: queueWindowUpdate,
}
}
func (f *incomingDataFlowController) AddBytesRead(n int64) error {
f.mx.Lock()
defer f.mx.Unlock()
if n > f.maxData-f.bytesRead {
return fmt.Errorf("webtransport: received more than %d bytes of stream data", f.maxData)
}
f.bytesRead += n
if f.maxData-f.bytesRead > f.receiveWindow-f.receiveWindow/4 {
return nil
}
maxData := f.bytesRead + f.receiveWindow
if maxData == f.maxData {
return nil
}
f.maxData = maxData
f.queueWindowUpdate(maxData)
return nil
}