106 lines
2.1 KiB
Go
106 lines
2.1 KiB
Go
|
package proxy
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"go.uber.org/zap"
|
||
|
"net"
|
||
|
"runtime/debug"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
servicesMap = new(sync.Map)
|
||
|
logger *zap.Logger
|
||
|
)
|
||
|
|
||
|
type Service struct {
|
||
|
TCPConn TCP
|
||
|
Name string
|
||
|
}
|
||
|
|
||
|
func (s *Service) Stop() {
|
||
|
servicesMap.Delete(s.Name)
|
||
|
s.TCPConn.Close()
|
||
|
}
|
||
|
|
||
|
func Run(name string, args TCPArgs, zapLogger *zap.Logger) *Service {
|
||
|
logger = zapLogger
|
||
|
service := &Service{
|
||
|
TCPConn: &tcp{cfg: args},
|
||
|
Name: name,
|
||
|
}
|
||
|
store, loaded := servicesMap.LoadOrStore(name, service)
|
||
|
if loaded {
|
||
|
service = store.(*Service)
|
||
|
}
|
||
|
|
||
|
go func() {
|
||
|
defer func() {
|
||
|
recoverErr := recover()
|
||
|
if recoverErr != nil {
|
||
|
logger.Sugar().Errorf("%s servcie crashed, ERR: %s\ntrace:%s", name, recoverErr, string(debug.Stack()))
|
||
|
}
|
||
|
}()
|
||
|
startErr := service.TCPConn.Start()
|
||
|
if startErr != nil {
|
||
|
logger.Sugar().Errorf("%s servcie fail, ERR: %s", name, startErr)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
return service
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
type Listener struct {
|
||
|
ip string
|
||
|
port int
|
||
|
Listener net.Listener
|
||
|
errAcceptHandler func(err error)
|
||
|
}
|
||
|
|
||
|
func NewListener(ip string, port int) Listener {
|
||
|
return Listener{
|
||
|
ip: ip,
|
||
|
port: port,
|
||
|
errAcceptHandler: func(err error) {
|
||
|
logger.Sugar().Errorf("accept error , ERR:%s", err)
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (sc *Listener) ListenTCP(fn func(conn net.Conn)) (err error) {
|
||
|
sc.Listener, err = net.Listen("tcp", fmt.Sprintf("%s:%d", sc.ip, sc.port))
|
||
|
if err == nil {
|
||
|
go func() {
|
||
|
defer func() {
|
||
|
if e := recover(); e != nil {
|
||
|
logger.Sugar().Infof("ListenTCP crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||
|
}
|
||
|
}()
|
||
|
for {
|
||
|
var conn net.Conn
|
||
|
conn, err = sc.Listener.Accept()
|
||
|
if err == nil {
|
||
|
go func() {
|
||
|
defer func() {
|
||
|
if e := recover(); e != nil {
|
||
|
logger.Sugar().Infof("connection handler crashed , err : %s , \ntrace:%s", e, string(debug.Stack()))
|
||
|
}
|
||
|
}()
|
||
|
fn(conn)
|
||
|
}()
|
||
|
} else {
|
||
|
sc.errAcceptHandler(err)
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (sc *Listener) CloseListen() error {
|
||
|
return sc.Listener.Close()
|
||
|
}
|