1f2e74acca
- 完善 stream/bulk DataID 分配、预留和双向命名空间,修复并发打开及 dedicated/shared 回退时的 ID 冲突 - 将收发、回复、恢复任务和 sidecar 绑定原始会话与物理连接,防止重连后的旧消息误操作新连接 - 加强 close/reset 身份校验及实例移除检查,修复 dedicated attach 失败、通道引用和资源回收竞态 - 收紧批量发送器停止准入,确保在途入队完成后统一清理请求、缓冲区和等待者 - 修复 record 满队列死锁、取消时序号消耗及关闭竞态,确保关闭有界并返回真实错误 - 增加协商式 record 逻辑半关闭,保留反向 ACK;通过 reset 传递 RecordFailure,避免背压掩盖原始失败原因 - 补齐帧长度、批次数量、序号溢出和未确认窗口校验,提前拒绝超限数据并按字节预算拆批 - 为入站分发增加全局及单连接的条数、字节预算和阻塞背压,关闭时唤醒等待者,消除正常断连日志噪音 - 完善 bulk 窗口释放失败处理与传输诊断,补充并发、重连、背压、协议边界及真实 TCP 回归覆盖
306 lines
9.5 KiB
Go
306 lines
9.5 KiB
Go
package notify
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
)
|
|
|
|
func (s *ServerCommon) stopClientSession(client *ClientConn, reason string, err error) {
|
|
if client == nil {
|
|
return
|
|
}
|
|
if runtime := s.getStreamRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(client), streamRuntimeCloseError(err))
|
|
}
|
|
if runtime := s.getBulkRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(client), bulkRuntimeCloseError(err))
|
|
}
|
|
if transfers := s.getTransferState(); transfers != nil {
|
|
transfers.closeScope(serverFileScope(client), err)
|
|
}
|
|
client.stopServerOwnedSessionWith(s.removeClient, reason, err)
|
|
}
|
|
|
|
func (s *ServerCommon) stopLogicalSession(logical *LogicalConn, reason string, err error) {
|
|
if logical == nil {
|
|
return
|
|
}
|
|
if runtime := s.getStreamRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(logical), streamRuntimeCloseError(err))
|
|
}
|
|
if runtime := s.getBulkRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(logical), bulkRuntimeCloseError(err))
|
|
}
|
|
if transfers := s.getTransferState(); transfers != nil {
|
|
transfers.closeScope(serverFileScope(logical), err)
|
|
}
|
|
logical.stopServerOwnedSessionWith(s.removeLogical, reason, err)
|
|
}
|
|
|
|
func (s *ServerCommon) detachClientSessionTransport(client *ClientConn, reason string, err error) {
|
|
if s == nil || client == nil {
|
|
return
|
|
}
|
|
if !client.clientConnTransportAttachedSnapshot() {
|
|
return
|
|
}
|
|
client.markClientConnTransportDetached(reason, err)
|
|
s.getPendingWaitPool().closeScope(serverTransportScope(client))
|
|
s.getPendingWaitPool().closeScope(serverFileScope(client))
|
|
s.getFileAckPool().closeScope(serverTransportScope(client))
|
|
s.getFileAckPool().closeScope(serverFileScope(client))
|
|
s.getSignalAckPool().closeScope(serverTransportScope(client))
|
|
s.getSignalAckPool().closeScope(serverFileScope(client))
|
|
if runtime := s.getStreamRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(client), errTransportDetached)
|
|
}
|
|
if runtime := s.getBulkRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(client), errTransportDetached)
|
|
}
|
|
s.closeServerDedicatedSidecar(logicalConnFromClient(client))
|
|
client.detachServerOwnedTransport()
|
|
}
|
|
|
|
func (s *ServerCommon) detachLogicalSessionTransport(logical *LogicalConn, reason string, err error) {
|
|
if s == nil || logical == nil {
|
|
return
|
|
}
|
|
logical.transportLifecycleMu.Lock()
|
|
defer logical.transportLifecycleMu.Unlock()
|
|
s.detachLogicalSessionTransportLocked(logical, reason, err)
|
|
}
|
|
|
|
func (s *ServerCommon) detachLogicalSessionTransportLocked(logical *LogicalConn, reason string, err error) {
|
|
if s == nil || logical == nil {
|
|
return
|
|
}
|
|
if !logical.transportAttachedSnapshot() {
|
|
return
|
|
}
|
|
logical.markTransportDetached(reason, err)
|
|
s.getPendingWaitPool().closeScope(serverTransportScope(logical))
|
|
s.getPendingWaitPool().closeScope(serverFileScope(logical))
|
|
s.getFileAckPool().closeScope(serverTransportScope(logical))
|
|
s.getFileAckPool().closeScope(serverFileScope(logical))
|
|
s.getSignalAckPool().closeScope(serverTransportScope(logical))
|
|
s.getSignalAckPool().closeScope(serverFileScope(logical))
|
|
if runtime := s.getStreamRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(logical), errTransportDetached)
|
|
}
|
|
if runtime := s.getBulkRuntime(); runtime != nil {
|
|
runtime.closeScope(serverFileScope(logical), errTransportDetached)
|
|
}
|
|
s.closeServerDedicatedSidecar(logical)
|
|
logical.detachServerOwnedTransport()
|
|
}
|
|
|
|
func (s *ServerCommon) newAcceptedClient(id string, addr net.Addr) *ClientConn {
|
|
logical := s.newAcceptedLogical(id, addr)
|
|
if logical == nil {
|
|
return nil
|
|
}
|
|
return logical.compatClientConn()
|
|
}
|
|
|
|
func (s *ServerCommon) newAcceptedLogical(id string, addr net.Addr) *LogicalConn {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
return newServerLogicalConn(s, id, addr)
|
|
}
|
|
|
|
func (s *ServerCommon) registerAcceptedClient(client *ClientConn) *LogicalConn {
|
|
return s.registerAcceptedLogical(logicalConnFromClient(client))
|
|
}
|
|
|
|
func (s *ServerCommon) registerAcceptedLogical(logical *LogicalConn) *LogicalConn {
|
|
if s == nil || logical == nil {
|
|
return nil
|
|
}
|
|
logical.setServer(s)
|
|
logical.applyAttachmentProfile(s.maxReadTimeout, s.maxWriteTimeout, s.defaultMsgEn, s.defaultMsgDe, s.defaultFastStreamEncode, s.defaultFastBulkEncode, s.defaultFastPlainEncode, s.handshakeRsaKey, s.SecretKey)
|
|
logical.updateAttachmentState(func(state *clientConnAttachmentState) {
|
|
state.authMode = s.securityAuthMode
|
|
state.peerAttached = false
|
|
state.peerAttachFallback = false
|
|
state.peerAttachAt = 0
|
|
})
|
|
if s.securityConfigured {
|
|
logical.applyTransportProtectionProfile(s.securityBootstrap)
|
|
} else {
|
|
logical.setModernPSKRuntime(s.defaultModernPSKRuntime)
|
|
}
|
|
logical.markHeartbeatNow()
|
|
return s.getPeerRegistry().registerLogical(logical)
|
|
}
|
|
|
|
func (s *ServerCommon) renameAcceptedLogical(logical *LogicalConn, id string) error {
|
|
if s == nil {
|
|
return errors.New("server is nil")
|
|
}
|
|
if logical == nil {
|
|
return errors.New("logical conn is nil")
|
|
}
|
|
if id == "" {
|
|
return errors.New("client id is empty")
|
|
}
|
|
if logical.ID() == id {
|
|
return nil
|
|
}
|
|
return s.getPeerRegistry().renameLogical(logical, id)
|
|
}
|
|
|
|
func (s *ServerCommon) renameAcceptedClient(client *ClientConn, id string) error {
|
|
return s.renameAcceptedLogical(logicalConnFromClient(client), id)
|
|
}
|
|
|
|
func (c *LogicalConn) inheritAcceptedLogicalTransportState(src *LogicalConn) {
|
|
if c == nil || src == nil {
|
|
return
|
|
}
|
|
c.inheritAttachmentProfile(src)
|
|
if addr := src.RemoteAddr(); addr != nil {
|
|
c.setRemoteAddr(addr)
|
|
}
|
|
}
|
|
|
|
func (c *LogicalConn) attachAcceptedTransport(addr net.Addr, tuConn net.Conn) error {
|
|
if c == nil {
|
|
return errors.New("logical conn is nil")
|
|
}
|
|
if addr == nil && tuConn != nil {
|
|
addr = tuConn.RemoteAddr()
|
|
}
|
|
if addr != nil {
|
|
c.setRemoteAddr(addr)
|
|
}
|
|
if tuConn == nil {
|
|
return nil
|
|
}
|
|
c.markHeartbeatNow()
|
|
c.clearTransportDetachState()
|
|
if c.sessionRuntimeSnapshot() == nil {
|
|
c.startSessionTransport(tuConn, nil, nil)
|
|
return nil
|
|
}
|
|
return c.attachSessionTransport(tuConn)
|
|
}
|
|
|
|
func (s *ServerCommon) attachAcceptedLogicalTransport(logical *LogicalConn, addr net.Addr, tuConn net.Conn) error {
|
|
if s == nil {
|
|
return errors.New("server is nil")
|
|
}
|
|
if logical == nil {
|
|
return errors.New("logical conn is nil")
|
|
}
|
|
logical.setServer(s)
|
|
logical.transportLifecycleMu.Lock()
|
|
defer logical.transportLifecycleMu.Unlock()
|
|
if oldConn := logical.transportSnapshot(); tuConn != nil && oldConn != nil && oldConn != tuConn {
|
|
// Reusing a logical peer is a transport-generation boundary. Retire every
|
|
// operation pinned to the old connection before publishing the replacement;
|
|
// otherwise an in-flight dedicated attach can revive an old bulk.
|
|
s.detachLogicalSessionTransportLocked(logical, "server transport replaced", transportDetachedError("server transport replaced", nil))
|
|
}
|
|
return logical.attachAcceptedTransport(addr, tuConn)
|
|
}
|
|
|
|
func (s *ServerCommon) attachAcceptedClientTransport(client *ClientConn, addr net.Addr, tuConn net.Conn) error {
|
|
return s.attachAcceptedLogicalTransport(logicalConnFromClient(client), addr, tuConn)
|
|
}
|
|
|
|
func (s *ServerCommon) handoffAcceptedLogicalTransport(dst *LogicalConn, src *LogicalConn) error {
|
|
if s == nil {
|
|
return errors.New("server is nil")
|
|
}
|
|
if dst == nil {
|
|
return errors.New("destination logical conn is nil")
|
|
}
|
|
if src == nil {
|
|
return errors.New("source logical conn is nil")
|
|
}
|
|
if dst == src {
|
|
return nil
|
|
}
|
|
addr := src.RemoteAddr()
|
|
conn, err := src.detachTransportForTransfer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := s.attachAcceptedLogicalTransport(dst, addr, conn); err != nil {
|
|
if conn != nil {
|
|
_ = conn.Close()
|
|
}
|
|
return err
|
|
}
|
|
dst.inheritAcceptedLogicalTransportState(src)
|
|
src.markSessionStopped("peer transport handed off", nil)
|
|
s.removeLogical(src)
|
|
return nil
|
|
}
|
|
|
|
func (s *ServerCommon) handoffAcceptedClientTransport(dst *ClientConn, src *ClientConn) error {
|
|
return s.handoffAcceptedLogicalTransport(logicalConnFromClient(dst), logicalConnFromClient(src))
|
|
}
|
|
|
|
func (s *ServerCommon) upsertAcceptedLogical(id string, addr net.Addr, tuConn net.Conn) (*LogicalConn, bool, error) {
|
|
if s == nil {
|
|
return nil, false, errors.New("server is nil")
|
|
}
|
|
if id == "" {
|
|
return nil, false, errors.New("client id is empty")
|
|
}
|
|
if existing := s.GetLogicalConn(id); existing != nil {
|
|
if err := s.attachAcceptedLogicalTransport(existing, addr, tuConn); err != nil {
|
|
if tuConn != nil {
|
|
_ = tuConn.Close()
|
|
}
|
|
return nil, true, err
|
|
}
|
|
return existing, true, nil
|
|
}
|
|
logical := s.newAcceptedLogical(id, addr)
|
|
if logical == nil {
|
|
return nil, false, errors.New("accepted logical is nil")
|
|
}
|
|
logical = s.registerAcceptedLogical(logical)
|
|
if logical == nil {
|
|
return nil, false, errors.New("accepted logical is nil")
|
|
}
|
|
if err := s.attachAcceptedLogicalTransport(logical, addr, tuConn); err != nil {
|
|
if tuConn != nil {
|
|
_ = tuConn.Close()
|
|
}
|
|
s.removeLogical(logical)
|
|
return nil, false, err
|
|
}
|
|
if tuConn == nil {
|
|
logical.startSession(nil, nil, nil)
|
|
}
|
|
return logical, false, nil
|
|
}
|
|
|
|
func (s *ServerCommon) upsertAcceptedClient(id string, addr net.Addr, tuConn net.Conn) (*ClientConn, bool, error) {
|
|
logical, reused, err := s.upsertAcceptedLogical(id, addr, tuConn)
|
|
if logical == nil {
|
|
return nil, reused, err
|
|
}
|
|
return logical.compatClientConn(), reused, err
|
|
}
|
|
|
|
func (s *ServerCommon) bootstrapAcceptedLogical(id string, addr net.Addr, tuConn net.Conn) *LogicalConn {
|
|
logical, _, err := s.upsertAcceptedLogical(id, addr, tuConn)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return logical
|
|
}
|
|
|
|
func (s *ServerCommon) bootstrapAcceptedClient(id string, addr net.Addr, tuConn net.Conn) *ClientConn {
|
|
logical := s.bootstrapAcceptedLogical(id, addr, tuConn)
|
|
if logical == nil {
|
|
return nil
|
|
}
|
|
return logical.compatClientConn()
|
|
}
|