241 lines
4.2 KiB
Go
241 lines
4.2 KiB
Go
package netlib
|
|
|
|
import (
|
|
"errors"
|
|
"math"
|
|
"time"
|
|
|
|
"mongo.games.com/goserver/core/logger"
|
|
"mongo.games.com/goserver/core/module"
|
|
"mongo.games.com/goserver/core/utils"
|
|
)
|
|
|
|
const (
|
|
IoServiceMaxCount int = 10
|
|
)
|
|
|
|
var (
|
|
NetModule = newNetEngine()
|
|
)
|
|
|
|
type NetEngine struct {
|
|
pool map[int]ioService
|
|
childAck chan int
|
|
backlogSc chan *SessionConfig
|
|
quit bool
|
|
reaped bool
|
|
}
|
|
|
|
func newNetEngine() *NetEngine {
|
|
e := &NetEngine{
|
|
pool: make(map[int]ioService),
|
|
childAck: make(chan int, IoServiceMaxCount),
|
|
backlogSc: make(chan *SessionConfig, IoServiceMaxCount),
|
|
}
|
|
|
|
return e
|
|
}
|
|
|
|
func (e *NetEngine) newIoService(sc *SessionConfig) ioService {
|
|
var s ioService
|
|
if sc.IsClient {
|
|
if !sc.AllowMultiConn && ConnectorMgr.IsConnecting(sc) {
|
|
return nil
|
|
}
|
|
switch sc.Protocol {
|
|
case "ws", "wss":
|
|
s = newWsConnector(e, sc)
|
|
case "udp":
|
|
s = newUdpConnector(e, sc)
|
|
default:
|
|
s = newTcpConnector(e, sc)
|
|
}
|
|
} else {
|
|
switch sc.Protocol {
|
|
case "ws", "wss":
|
|
s = newWsAcceptor(e, sc)
|
|
case "udp":
|
|
s = newUdpAcceptor(e, sc)
|
|
default:
|
|
s = newTcpAcceptor(e, sc)
|
|
}
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (e *NetEngine) GetAcceptors() []Acceptor {
|
|
acceptors := make([]Acceptor, 0, len(e.pool))
|
|
for _, v := range e.pool {
|
|
if a, is := v.(Acceptor); is {
|
|
acceptors = append(acceptors, a)
|
|
}
|
|
}
|
|
|
|
return acceptors
|
|
}
|
|
|
|
func (e *NetEngine) Connect(sc *SessionConfig) error {
|
|
if e.quit {
|
|
return errors.New("NetEngine already quiting")
|
|
}
|
|
SendStartNetIoService(sc)
|
|
return nil
|
|
}
|
|
|
|
func (e *NetEngine) Listen(sc *SessionConfig) error {
|
|
if e.quit {
|
|
return errors.New("NetEngine already quiting")
|
|
}
|
|
SendStartNetIoService(sc)
|
|
return nil
|
|
}
|
|
|
|
func (e *NetEngine) ShutConnector(ip string, port int) {
|
|
for _, v := range e.pool {
|
|
if c, is := v.(Connector); is {
|
|
sc := c.GetSessionConfig()
|
|
if sc.Ip == ip && sc.Port == port {
|
|
c.shutdown()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// //////////////////////////////////////////////////////////////////
|
|
// / Module Implement [beg]
|
|
// //////////////////////////////////////////////////////////////////
|
|
func (e *NetEngine) ModuleName() string {
|
|
return module.ModuleName_Net
|
|
}
|
|
|
|
func (e *NetEngine) Init() {
|
|
var err error
|
|
for i := 0; i < len(Config.IoServices); i++ {
|
|
s := e.newIoService(&Config.IoServices[i])
|
|
if s != nil {
|
|
e.pool[Config.IoServices[i].Id] = s
|
|
err = s.start()
|
|
if err != nil {
|
|
logger.Logger.Error(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
//time.AfterFunc(time.Minute*5, func() { e.dump() })
|
|
}
|
|
|
|
func (e *NetEngine) Update() {
|
|
defer utils.DumpStackIfPanic("NetEngine.Update")
|
|
|
|
e.clearClosedIo()
|
|
|
|
for _, v := range e.pool {
|
|
v.update()
|
|
}
|
|
}
|
|
|
|
func (e *NetEngine) Shutdown() {
|
|
if e.quit {
|
|
return
|
|
}
|
|
|
|
e.quit = true
|
|
|
|
if len(e.pool) > 0 {
|
|
for _, v := range e.pool {
|
|
v.shutdown()
|
|
}
|
|
go e.reapRoutine()
|
|
} else {
|
|
e.destroy()
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
/// Module Implement [end]
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
func (e *NetEngine) clearClosedIo() {
|
|
for {
|
|
select {
|
|
case k := <-e.childAck:
|
|
delete(e.pool, k)
|
|
case sc := <-e.backlogSc:
|
|
s := e.newIoService(sc)
|
|
if s != nil {
|
|
e.pool[sc.Id] = s
|
|
err := s.start()
|
|
if err != nil {
|
|
logger.Logger.Error(err)
|
|
}
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (e *NetEngine) reapRoutine() {
|
|
if e.reaped {
|
|
return
|
|
}
|
|
|
|
e.reaped = true
|
|
|
|
for {
|
|
select {
|
|
case k := <-e.childAck:
|
|
delete(e.pool, k)
|
|
if len(e.pool) == 0 {
|
|
e.destroy()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (e *NetEngine) destroy() {
|
|
module.UnregisteModule(e)
|
|
}
|
|
|
|
func (e *NetEngine) dump() {
|
|
for _, v := range e.pool {
|
|
v.dump()
|
|
}
|
|
time.AfterFunc(time.Minute*5, func() { e.dump() })
|
|
}
|
|
|
|
func (e *NetEngine) stats() map[int]ServiceStats {
|
|
stats := make(map[int]ServiceStats)
|
|
for k, v := range e.pool {
|
|
s := v.stats()
|
|
stats[k] = s
|
|
}
|
|
return stats
|
|
}
|
|
|
|
func init() {
|
|
module.RegisteModule(NetModule, 0, math.MaxInt32)
|
|
}
|
|
|
|
func Connect(sc *SessionConfig) error {
|
|
return NetModule.Connect(sc)
|
|
}
|
|
|
|
func Listen(sc *SessionConfig) error {
|
|
return NetModule.Listen(sc)
|
|
}
|
|
|
|
func GetAcceptors() []Acceptor {
|
|
return NetModule.GetAcceptors()
|
|
}
|
|
|
|
func ShutConnector(ip string, port int) {
|
|
NetModule.ShutConnector(ip, port)
|
|
}
|
|
|
|
func Stats() map[int]ServiceStats {
|
|
return NetModule.stats()
|
|
}
|