mt-multiserver-proxy/server_conn.go

144 lines
2.6 KiB
Go
Raw Normal View History

2021-09-06 02:03:27 -07:00
package proxy
import (
"errors"
"log"
"net"
2021-09-03 04:26:44 -07:00
"sync"
"time"
"github.com/anon55555/mt"
"github.com/anon55555/mt/rudp"
)
2021-09-10 03:47:19 -07:00
// A ServerConn is a connection to a minetest server.
2021-09-06 02:03:27 -07:00
type ServerConn struct {
mt.Peer
2021-09-06 02:03:27 -07:00
clt *ClientConn
2021-09-04 08:25:53 -07:00
mu sync.RWMutex
2021-09-13 03:14:11 -07:00
logger *log.Logger
2021-09-03 04:26:44 -07:00
cstate clientState
cstateMu sync.RWMutex
name string
initCh chan struct{}
auth struct {
method mt.AuthMethods
salt, srpA, a, srpK []byte
}
2021-08-30 05:36:00 -07:00
2022-05-01 07:58:11 -07:00
mediaPool string
2021-08-30 09:58:05 -07:00
inv mt.Inv
detachedInvs []string
aos map[mt.AOID]struct{}
particleSpawners map[mt.ParticleSpawnerID]struct{}
sounds map[mt.SoundID]struct{}
2021-08-30 12:38:44 -07:00
2021-09-02 13:10:51 -07:00
huds map[mt.HUDID]mt.HUDType
2021-09-01 03:39:36 -07:00
playerList map[string]struct{}
}
2021-09-06 02:03:27 -07:00
func (sc *ServerConn) client() *ClientConn {
2021-09-04 08:25:53 -07:00
sc.mu.RLock()
defer sc.mu.RUnlock()
return sc.clt
}
2021-09-06 02:03:27 -07:00
func (sc *ServerConn) state() clientState {
2021-09-03 04:26:44 -07:00
sc.cstateMu.RLock()
defer sc.cstateMu.RUnlock()
return sc.cstate
}
2021-09-06 02:03:27 -07:00
func (sc *ServerConn) setState(state clientState) {
2021-09-03 04:26:44 -07:00
sc.cstateMu.Lock()
defer sc.cstateMu.Unlock()
sc.cstate = state
}
2021-09-10 03:47:19 -07:00
// Init returns a channel that is closed
// when the ServerConn enters the csActive state.
2021-09-06 02:03:27 -07:00
func (sc *ServerConn) Init() <-chan struct{} { return sc.initCh }
2021-09-10 03:47:19 -07:00
// Log logs an interaction with the ServerConn.
// dir indicates the direction of the interaction.
2021-09-06 02:03:27 -07:00
func (sc *ServerConn) Log(dir string, v ...interface{}) {
2021-09-13 03:14:11 -07:00
sc.logger.Println(append([]interface{}{dir}, v...)...)
}
2021-09-06 02:03:27 -07:00
func handleSrv(sc *ServerConn) {
go func() {
init := make(chan struct{})
defer close(init)
go func(init <-chan struct{}) {
select {
case <-init:
case <-time.After(10 * time.Second):
2021-09-13 03:14:11 -07:00
sc.Log("->", "timeout")
sc.Close()
}
}(init)
2021-09-03 04:26:44 -07:00
for sc.state() == csCreated && sc.client() != nil {
sc.SendCmd(&mt.ToSrvInit{
SerializeVer: serializeVer,
MinProtoVer: protoVer,
MaxProtoVer: protoVer,
2021-09-09 11:07:36 -07:00
PlayerName: sc.client().Name(),
})
time.Sleep(500 * time.Millisecond)
}
}()
for {
pkt, err := sc.Recv()
if err != nil {
if errors.Is(err, net.ErrClosed) {
if errors.Is(sc.WhyClosed(), rudp.ErrTimedOut) {
2021-09-06 02:03:27 -07:00
sc.Log("<->", "timeout")
} else {
2021-09-06 02:03:27 -07:00
sc.Log("<->", "disconnect")
}
2021-08-30 06:17:11 -07:00
if sc.client() != nil {
2021-11-13 03:32:44 -08:00
ack, _ := sc.client().SendCmd(&mt.ToCltKick{
2021-08-30 06:17:11 -07:00
Reason: mt.Custom,
Custom: "Server connection closed unexpectedly.",
})
select {
case <-sc.client().Closed():
case <-ack:
sc.client().Close()
sc.client().mu.Lock()
2021-08-30 09:30:02 -07:00
sc.client().srv = nil
sc.client().mu.Unlock()
sc.mu.Lock()
2021-08-30 06:17:11 -07:00
sc.clt = nil
sc.mu.Unlock()
2021-08-30 06:17:11 -07:00
}
}
break
}
2021-09-13 03:14:11 -07:00
sc.Log("<-", err)
continue
}
sc.process(pkt)
}
}