This commit is contained in:
crusader 2017-11-30 18:13:58 +09:00
parent d29aa17537
commit 48ecd0a6fa
7 changed files with 261 additions and 0 deletions

98
client/socket.go Normal file
View File

@ -0,0 +1,98 @@
package client
import (
"crypto/tls"
"net"
"sync"
"git.loafle.net/commons_go/logging"
)
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)
}

31
client/socket_builder.go Normal file
View File

@ -0,0 +1,31 @@
package client
import (
"crypto/tls"
"net"
"time"
cuc "git.loafle.net/commons_go/util/context"
)
type SocketBuilder interface {
SocketContext(parent cuc.Context) SocketContext
SocketHandler() SocketHandler
GetNetwork() string
GetAddress() string
GetTLSConfig() *tls.Config
GetKeepAlive() time.Duration
GetTimeout() time.Duration
GetLocalAddress() net.Addr
// Validate is check handler value
// If you override ths method, must call
//
// func (sh *SocketHandlers) Validate() {
// sh.SocketHandlers.Validate()
// ...
// }
Validate()
}

70
client/socket_builders.go Normal file
View File

@ -0,0 +1,70 @@
package client
import (
"crypto/tls"
"net"
"time"
"git.loafle.net/commons_go/logging"
cs "git.loafle.net/commons_go/server"
)
type SocketBuilders struct {
Network string
Address string
TLSConfig *tls.Config
KeepAlive time.Duration
Timeout time.Duration
LocalAddress net.Addr
}
func (sb *SocketBuilders) SocketContext(parent cuc.Context) SocketContext {
return newSocketContext(parent)
}
func (sb *SocketBuilders) SocketHandler() SocketHandler {
return NewSocketHandler()
}
func (sb *SocketBuilders) GetNetwork() string {
return sb.NewSocket
}
func (sb *SocketBuilders) GetAddress() string {
return sb.Address
}
func (sb *SocketBuilders) GetTLSConfig() *tls.Config {
return sb.TLSConfig
}
func (sb *SocketBuilders) GetKeepAlive() time.Duration {
return sb.KeepAlive
}
func (sb *SocketBuilders) GetTimeout() time.Duration {
return sb.Timeout
}
func (sb *SocketBuilders) GetLocalAddress() Addr {
return sb.LocalAddress
}
func (sb *SocketBuilders) Validate() {
if "" == sb.Network {
logging.Logger().Panic("Client Socket: Network must be specified")
}
if "" == sb.Address {
logging.Logger().Panic("Client Socket: Address must be specified")
}
if 0 >= sb.KeepAlive {
sb.KeepAlive = cs.DefaultKeepAlive
}
if 0 >= sb.Timeout {
sb.Timeout = cs.DefaultConnectTimeout
}
}

20
client/socket_context.go Normal file
View File

@ -0,0 +1,20 @@
package client
import (
cuc "git.loafle.net/commons_go/util/context"
)
type SocketContext interface {
cuc.Context
}
func newSocketContext(parent cuc.Context) SocketContext {
sCTX := &socketContext{}
sCTX.Context = cuc.NewContext(parent)
return sCTX
}
type socketContext struct {
cuc.Context
}

17
client/socket_handler.go Normal file
View File

@ -0,0 +1,17 @@
package client
import "net"
type SocketHandler interface {
OnConnect(socketContext SocketContext, conn net.Conn)
OnDisconnect(soc Socket)
// Validate is check handler value
// If you override ths method, must call
//
// func (sh *SocketHandlers) Validate() {
// sh.SocketHandlers.Validate()
// ...
// }
Validate()
}

21
client/socket_handlers.go Normal file
View File

@ -0,0 +1,21 @@
package client
import "net"
type SocketHandlers struct {
}
func (sh *SocketHandlers) OnConnect(socketContext SocketContext, conn net.Conn) {
// no op
}
func (sh *SocketHandlers) OnDisconnect(soc Socket) {
// no op
}
func (sh *SocketHandlers) Validate() {
}
func NewSocketHandler() SocketHandler {
return &SocketHandlers{}
}

View File

@ -30,4 +30,8 @@ const (
DefaultReadTimeout = 0 DefaultReadTimeout = 0
// DefaultWriteTimeout is default value of write timeout // DefaultWriteTimeout is default value of write timeout
DefaultWriteTimeout = 0 DefaultWriteTimeout = 0
DefaultConnectTimeout = 0
DefaultKeepAlive = 0
) )