base-golang/pkg/proxy/service.go
2024-07-23 10:23:43 +08:00

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()
}