233 lines
5.0 KiB
Go
233 lines
5.0 KiB
Go
|
|
package notify
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"net"
|
||
|
|
)
|
||
|
|
|
||
|
|
type clientConnSessionRuntime struct {
|
||
|
|
transport *transportBinding
|
||
|
|
transportAttached bool
|
||
|
|
transportGeneration uint64
|
||
|
|
tuConn net.Conn
|
||
|
|
stopCtx context.Context
|
||
|
|
stopFn context.CancelFunc
|
||
|
|
transportStopCtx context.Context
|
||
|
|
transportStopFn context.CancelFunc
|
||
|
|
transportDone chan struct{}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) setClientConnSessionRuntime(rt *clientConnSessionRuntime) {
|
||
|
|
if c == nil || rt == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
if rt.transport == nil && rt.tuConn != nil {
|
||
|
|
rt.transport = newTransportBinding(rt.tuConn, nil)
|
||
|
|
}
|
||
|
|
normalizeClientConnSessionRuntimeTransportState(rt)
|
||
|
|
ensureClientConnSessionRuntimeTransportLifecycle(rt)
|
||
|
|
ensureClientConnSessionRuntimeTransportDone(rt)
|
||
|
|
c.sessionRuntime.Store(rt)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
logical.setSessionRuntime(rt)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clientConnSessionRuntimeSnapshot() *clientConnSessionRuntime {
|
||
|
|
if c == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
state := c.ensureLogicalConnRuntimeState()
|
||
|
|
if state == nil {
|
||
|
|
return c.sessionRuntime.Load()
|
||
|
|
}
|
||
|
|
rt := state.sessionRuntimeSnapshot()
|
||
|
|
if rt != c.sessionRuntime.Load() {
|
||
|
|
c.sessionRuntime.Store(rt)
|
||
|
|
}
|
||
|
|
return rt
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clearClientConnSessionRuntimeTransport() {
|
||
|
|
if c == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
rt := c.clientConnSessionRuntimeSnapshot()
|
||
|
|
if rt == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if rt.transportStopFn != nil {
|
||
|
|
rt.transportStopFn()
|
||
|
|
}
|
||
|
|
next := *rt
|
||
|
|
next.transport = nil
|
||
|
|
next.transportAttached = false
|
||
|
|
next.transportGeneration = 0
|
||
|
|
next.tuConn = nil
|
||
|
|
next.transportStopCtx = nil
|
||
|
|
next.transportStopFn = nil
|
||
|
|
next.transportDone = nil
|
||
|
|
c.setClientConnSessionRuntime(&next)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
logical.clearSessionRuntimeTransport()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clientConnTransportSnapshot() net.Conn {
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
rt := c.clientConnSessionRuntimeSnapshot()
|
||
|
|
if rt == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
if rt.transport != nil {
|
||
|
|
return rt.transport.connSnapshot()
|
||
|
|
}
|
||
|
|
return rt.tuConn
|
||
|
|
}
|
||
|
|
return logical.transportSnapshot()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clientConnStopContextSnapshot() context.Context {
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
rt := c.clientConnSessionRuntimeSnapshot()
|
||
|
|
if rt == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
return rt.stopCtx
|
||
|
|
}
|
||
|
|
return logical.stopContextSnapshot()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clientConnStopFuncSnapshot() context.CancelFunc {
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
rt := c.clientConnSessionRuntimeSnapshot()
|
||
|
|
if rt == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
return rt.stopFn
|
||
|
|
}
|
||
|
|
return logical.stopFuncSnapshot()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) closeClientConnTransport() {
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
conn := c.clientConnTransportSnapshot()
|
||
|
|
if conn == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
_ = conn.Close()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
logical.closeTransport()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clientConnTransportBindingSnapshot() *transportBinding {
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
rt := c.clientConnSessionRuntimeSnapshot()
|
||
|
|
if rt == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
if rt.transport != nil {
|
||
|
|
return rt.transport
|
||
|
|
}
|
||
|
|
if rt.tuConn == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
return newTransportBinding(rt.tuConn, nil)
|
||
|
|
}
|
||
|
|
return logical.transportBindingSnapshot()
|
||
|
|
}
|
||
|
|
|
||
|
|
func normalizeClientConnSessionRuntimeTransportState(rt *clientConnSessionRuntime) {
|
||
|
|
if rt == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if rt.transport != nil {
|
||
|
|
rt.transportAttached = rt.transport.connSnapshot() != nil
|
||
|
|
return
|
||
|
|
}
|
||
|
|
rt.transportAttached = rt.tuConn != nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func ensureClientConnSessionRuntimeTransportLifecycle(rt *clientConnSessionRuntime) {
|
||
|
|
if rt == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if rt.tuConn == nil {
|
||
|
|
rt.transportStopCtx = nil
|
||
|
|
rt.transportStopFn = nil
|
||
|
|
rt.transportDone = nil
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if rt.transportStopCtx != nil && rt.transportStopFn != nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
parent := rt.stopCtx
|
||
|
|
if parent == nil {
|
||
|
|
parent = context.Background()
|
||
|
|
}
|
||
|
|
rt.transportStopCtx, rt.transportStopFn = context.WithCancel(parent)
|
||
|
|
}
|
||
|
|
|
||
|
|
func ensureClientConnSessionRuntimeTransportDone(rt *clientConnSessionRuntime) {
|
||
|
|
if rt == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if rt.tuConn == nil {
|
||
|
|
rt.transportDone = nil
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if rt.transportDone != nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
rt.transportDone = make(chan struct{})
|
||
|
|
}
|
||
|
|
|
||
|
|
func closeClientConnSessionRuntimeTransportDone(rt *clientConnSessionRuntime) {
|
||
|
|
if rt == nil || rt.transportDone == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
select {
|
||
|
|
case <-rt.transportDone:
|
||
|
|
return
|
||
|
|
default:
|
||
|
|
close(rt.transportDone)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clientConnTransportStopContextSnapshot() context.Context {
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
rt := c.clientConnSessionRuntimeSnapshot()
|
||
|
|
if rt == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
if rt.transportStopCtx != nil {
|
||
|
|
return rt.transportStopCtx
|
||
|
|
}
|
||
|
|
return rt.stopCtx
|
||
|
|
}
|
||
|
|
return logical.transportStopContextSnapshot()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *ClientConn) clientConnTransportAttachedSnapshot() bool {
|
||
|
|
logical := c.LogicalConn()
|
||
|
|
if logical == nil {
|
||
|
|
rt := c.clientConnSessionRuntimeSnapshot()
|
||
|
|
if rt == nil {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
return rt.transportAttached
|
||
|
|
}
|
||
|
|
return logical.transportAttachedSnapshot()
|
||
|
|
}
|