-
Notifications
You must be signed in to change notification settings - Fork 0
/
rawconn_settings.go
112 lines (101 loc) · 2.81 KB
/
rawconn_settings.go
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
package copper
import (
"fmt"
"time"
)
// rawConnSettings is used to keep track of settings
// It uses the connection lock for protecting its fields
type rawConnSettings struct {
conn *rawConn
callbacks []func(error)
localStreamWindowSize int
remoteStreamWindowSize int
localInactivityTimeout time.Duration
remoteInactivityTimeout time.Duration
}
func (s *rawConnSettings) init(conn *rawConn) {
s.conn = conn
s.localStreamWindowSize = InitialStreamWindow
s.remoteStreamWindowSize = InitialStreamWindow
s.localInactivityTimeout = InitialInactivityTimeout
s.remoteInactivityTimeout = InitialInactivityTimeout
}
// Fails all pending callbacks with err, called when closing the connection
func (s *rawConnSettings) failLocked(err error) {
callbacks := s.callbacks
s.callbacks = nil
for _, callback := range callbacks {
if callback != nil {
callback(err)
}
}
}
// Handles an incoming settings ack
// Find and call the callback that registered for the outgoing frame.
func (s *rawConnSettings) handleAck() {
var callback func(error)
s.conn.mu.Lock()
if len(s.callbacks) > 0 {
callback = s.callbacks[0]
copy(s.callbacks, s.callbacks[1:])
s.callbacks[len(s.callbacks)-1] = nil
s.callbacks = s.callbacks[:len(s.callbacks)-1]
}
s.conn.mu.Unlock()
if callback != nil {
callback(nil)
}
}
// Handles an incoming settings frame, updates to new settings
func (s *rawConnSettings) handleSettings(frame *SettingsFrame) error {
s.conn.mu.Lock()
if value, ok := frame.Value(SettingStreamWindow); ok {
if value < MinWindowSize || value > MaxWindowSize {
s.conn.mu.Unlock()
return copperError{
error: fmt.Errorf("cannot set stream window to %d bytes", value),
code: EINVALIDFRAME,
}
}
diff := int(value) - s.remoteStreamWindowSize
s.conn.streams.changeWriteWindowLocked(diff)
s.remoteStreamWindowSize = int(value)
}
if value, ok := frame.Value(SettingInactivityMilliseconds); ok {
if value < 1000 {
s.conn.mu.Unlock()
return copperError{
error: fmt.Errorf("cannot set inactivity timeout to %dms", value),
code: EINVALIDFRAME,
}
}
s.remoteInactivityTimeout = time.Duration(value) * time.Millisecond
}
s.conn.outgoing.addSettingsAck()
s.conn.mu.Unlock()
return nil
}
func (s *rawConnSettings) getLocalStreamWindowSize() int {
s.conn.mu.RLock()
window := s.localStreamWindowSize
s.conn.mu.RUnlock()
return window
}
func (s *rawConnSettings) getRemoteStreamWindowSize() int {
s.conn.mu.RLock()
window := s.remoteStreamWindowSize
s.conn.mu.RUnlock()
return window
}
func (s *rawConnSettings) getLocalInactivityTimeout() time.Duration {
s.conn.mu.RLock()
d := s.localInactivityTimeout
s.conn.mu.RUnlock()
return d
}
func (s *rawConnSettings) getRemoteInactivityTimeout() time.Duration {
s.conn.mu.RLock()
d := s.remoteInactivityTimeout
s.conn.mu.RUnlock()
return d
}