server/client/socket.go
crusader 49eee11b7f ing
2017-11-30 18:36:59 +09:00

100 lines
1.6 KiB
Go

package client
import (
"crypto/tls"
"net"
"sync"
"git.loafle.net/commons_go/logging"
cuc "git.loafle.net/commons_go/util/context"
)
type Socket interface {
Context() SocketContext
net.Conn
}
func NewSocket(sb SocketBuilder, parentContext cuc.Context) (Socket, error) {
if nil == sb {
logging.Logger().Panic("Client Socket: SocketBuilder must be specified")
}
sb.Validate()
sc := sb.SocketContext(parentContext)
if nil == sc {
logging.Logger().Panic("Client Socket: SocketContext must be specified")
}
sh := sb.SocketHandler()
if nil == sh {
logging.Logger().Panic("Client Socket: SocketHandler must be specified")
}
sh.Validate()
d := &net.Dialer{}
d.Timeout = sb.GetTimeout()
d.KeepAlive = sb.GetKeepAlive()
d.LocalAddr = sb.GetLocalAddress()
network := sb.GetNetwork()
address := sb.GetAddress()
tlsConfig := sb.GetTLSConfig()
var conn net.Conn
var err error
if nil == tlsConfig {
conn, err = d.Dial(network, address)
} else {
conn, err = tls.DialWithDialer(d, network, address, tlsConfig)
}
if nil != err {
return nil, err
}
sh.OnConnect(sc, conn)
s := retainSocket()
s.ctx = sc
s.sh = sh
return s, nil
}
type netSocket struct {
net.Conn
ctx SocketContext
sh SocketHandler
}
func (s *netSocket) Context() SocketContext {
return s.ctx
}
func (s *netSocket) Close() error {
err := s.Conn.Close()
s.sh.OnDisconnect(s)
releaseSocket(s)
return err
}
var socketPool sync.Pool
func retainSocket() *netSocket {
v := socketPool.Get()
if v == nil {
return &netSocket{}
}
return v.(*netSocket)
}
func releaseSocket(s *netSocket) {
s.sh = nil
s.ctx = nil
socketPool.Put(s)
}