-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconnection_controller.go
More file actions
102 lines (91 loc) · 3.4 KB
/
Copy pathconnection_controller.go
File metadata and controls
102 lines (91 loc) · 3.4 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
package http2
import "gnalloy.org/gnalloy/channel"
// ConnectionControllerConfig 描述 HTTP/2 连接级协议控制边界。
type ConnectionControllerConfig struct {
// Server 表示本端是服务端;用于校验本端和对端 stream ID 奇偶性。
Server bool
// InitialConnectionWindow 是本端接收连接窗口,0 使用 RFC 默认值。
InitialConnectionWindow int32
// InitialStreamWindow 是本端接收 stream 窗口,0 使用 RFC 默认值。
InitialStreamWindow int32
// MaxConcurrentStreams 限制对端可同时打开的 stream 数,0 表示不额外限制。
MaxConcurrentStreams int
// DisablePush 禁用本端接收 server push。
DisablePush bool
}
// ConnectionController 维护 HTTP/2 SETTINGS、GOAWAY、并发 stream 和入站流控。
type ConnectionController struct {
cfg ConnectionControllerConfig
localSettings SettingsSnapshot
remoteSettings SettingsSnapshot
connectionReceiveWindow int32
initialStreamWindow int32
streams map[StreamID]*multiplexedStream
goAwayReceived bool
goAwayLastStream StreamID
}
// NewConnectionController 创建连接级协议控制 handler。
func NewConnectionController(cfg ConnectionControllerConfig) (*ConnectionController, error) {
if cfg.InitialConnectionWindow < 0 || cfg.InitialStreamWindow < 0 || cfg.MaxConcurrentStreams < 0 {
return nil, ErrFlowControl
}
connWindow := normalizedWindow(cfg.InitialConnectionWindow)
streamWindow := normalizedWindow(cfg.InitialStreamWindow)
return &ConnectionController{
cfg: cfg,
localSettings: defaultSettingsSnapshot(streamWindow, cfg.MaxConcurrentStreams, !cfg.DisablePush),
remoteSettings: defaultSettingsSnapshot(defaultInitialWindowSize, 0, true),
connectionReceiveWindow: connWindow,
initialStreamWindow: streamWindow,
streams: make(map[StreamID]*multiplexedStream, 16),
}, nil
}
// LocalSettings 返回本端设置快照。
func (c *ConnectionController) LocalSettings() SettingsSnapshot {
return c.localSettings
}
// RemoteSettings 返回对端已应用设置快照。
func (c *ConnectionController) RemoteSettings() SettingsSnapshot {
return c.remoteSettings
}
// ConnectionReceiveWindow 返回当前连接级接收窗口。
func (c *ConnectionController) ConnectionReceiveWindow() int32 {
return c.connectionReceiveWindow
}
// StreamReceiveWindow 返回指定 stream 接收窗口。
func (c *ConnectionController) StreamReceiveWindow(id StreamID) int32 {
if stream := c.streams[id]; stream != nil {
return stream.recvWindow
}
return c.initialStreamWindow
}
// ActiveStreams 返回连接控制器仍跟踪的 stream 数。
func (c *ConnectionController) ActiveStreams() int {
return len(c.streams)
}
// ChannelRead 校验并应用入站连接级语义后继续传播 frame。
func (c *ConnectionController) ChannelRead(ctx *channel.HandlerContext, msg any) {
frame, ok := msg.(TypedFrame)
if !ok {
ctx.FireChannelRead(msg)
return
}
if err := c.readFrame(frame); err != nil {
frame.Release()
ctx.FireExceptionCaught(err)
return
}
ctx.FireChannelRead(msg)
}
// Write 校验并应用出站连接级语义。
func (c *ConnectionController) Write(ctx *channel.HandlerContext, msg any) error {
frame, ok := msg.(TypedFrame)
if !ok {
return ctx.Write(msg)
}
if err := c.writeFrame(frame); err != nil {
frame.Release()
return err
}
return ctx.Write(msg)
}