package server import ( "crypto/tls" "net" "sync/atomic" "time" ) type ConnectionHandler interface { GetConcurrency() int GetKeepAlive() time.Duration GetHandshakeTimeout() time.Duration GetTLSConfig() *tls.Config Listener(serverCtx ServerCtx) (net.Listener, error) } type ConnectionHandlers struct { // The maximum number of concurrent connections the server may serve. // // DefaultConcurrency is used if not set. Network string `json:"network,omitempty"` Address string `json:"address,omitempty"` Concurrency int `json:"concurrency,omitempty"` KeepAlive time.Duration `json:"keepAlive,omitempty"` HandshakeTimeout time.Duration `json:"handshakeTimeout,omitempty"` TLSConfig *tls.Config `json:"-"` validated atomic.Value } func (ch *ConnectionHandlers) Listener(serverCtx ServerCtx) (net.Listener, error) { l, err := net.Listen(ch.Network, ch.Address) if nil != err { return nil, err } return l, nil } func (ch *ConnectionHandlers) GetConcurrency() int { return ch.Concurrency } func (ch *ConnectionHandlers) GetKeepAlive() time.Duration { return ch.KeepAlive } func (ch *ConnectionHandlers) GetHandshakeTimeout() time.Duration { return ch.HandshakeTimeout } func (ch *ConnectionHandlers) GetTLSConfig() *tls.Config { return ch.TLSConfig } func (ch *ConnectionHandlers) Clone() *ConnectionHandlers { return &ConnectionHandlers{ Network: ch.Network, Address: ch.Address, Concurrency: ch.Concurrency, KeepAlive: ch.KeepAlive, HandshakeTimeout: ch.HandshakeTimeout, TLSConfig: ch.TLSConfig, validated: ch.validated, } } func (ch *ConnectionHandlers) Validate() error { if nil != ch.validated.Load() { return nil } ch.validated.Store(true) if ch.Concurrency <= 0 { ch.Concurrency = DefaultConcurrency } if ch.KeepAlive <= 0 { ch.KeepAlive = DefaultKeepAlive } else { ch.KeepAlive = ch.KeepAlive * time.Second } if ch.HandshakeTimeout <= 0 { ch.HandshakeTimeout = DefaultHandshakeTimeout } else { ch.HandshakeTimeout = ch.HandshakeTimeout * time.Second } return nil }