153 lines
2.9 KiB
Go
153 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/anon55555/mt"
|
|
"github.com/anon55555/mt/rudp"
|
|
)
|
|
|
|
var ErrServerUnreachable = errors.New("server is unreachable")
|
|
|
|
var connectedPeers int = 0
|
|
var connectedPeersMu sync.RWMutex
|
|
|
|
// A Peer is a connection to a client or server
|
|
type Peer struct {
|
|
*rudp.Peer
|
|
|
|
username string
|
|
srp_s []byte
|
|
srp_A []byte
|
|
srp_a []byte
|
|
srp_B []byte
|
|
srp_K []byte
|
|
authMech int
|
|
sudoMode bool
|
|
|
|
stopforward bool
|
|
forwardMu sync.RWMutex
|
|
|
|
redirectMu sync.Mutex
|
|
srvMu sync.RWMutex
|
|
srv *Peer
|
|
|
|
initAoReceived bool
|
|
aoIDs map[uint16]bool
|
|
localPlayerCao uint16
|
|
currentPlayerCao uint16
|
|
|
|
useRpcMu sync.RWMutex
|
|
useRpc bool
|
|
modChs map[string]bool
|
|
|
|
huds map[uint32]bool
|
|
|
|
sounds map[int32]bool
|
|
|
|
inv *mt.Inv
|
|
}
|
|
|
|
// Username returns the username of the Peer
|
|
// if it isn't a server
|
|
func (p *Peer) Username() string { return p.username }
|
|
|
|
// Forward reports whether the Proxy func should continue or stop
|
|
func (p *Peer) Forward() bool {
|
|
p.forwardMu.RLock()
|
|
defer p.forwardMu.RUnlock()
|
|
|
|
return !p.stopforward
|
|
}
|
|
|
|
// stopForwarding tells the Proxy func to stop
|
|
func (p *Peer) stopForwarding() {
|
|
p.forwardMu.Lock()
|
|
defer p.forwardMu.Unlock()
|
|
|
|
p.stopforward = true
|
|
}
|
|
|
|
// Server returns the Peer this Peer is connected to
|
|
// if it isn't a server
|
|
func (p *Peer) Server() *Peer {
|
|
p.srvMu.RLock()
|
|
defer p.srvMu.RUnlock()
|
|
|
|
return p.srv
|
|
}
|
|
|
|
// ServerName returns the name of the Peer this Peer is connected to
|
|
// if this Peer is not a server
|
|
func (p *Peer) ServerName() string {
|
|
servers := GetConfKey("servers").(map[interface{}]interface{})
|
|
for server := range servers {
|
|
if GetConfKey("servers:"+server.(string)+":address") == p.Server().Addr().String() {
|
|
return server.(string)
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// SetServer sets the Peer this Peer is connected to
|
|
// if this Peer is not a server
|
|
func (p *Peer) SetServer(s *Peer) {
|
|
p.srvMu.Lock()
|
|
defer p.srvMu.Unlock()
|
|
|
|
p.srv = s
|
|
}
|
|
|
|
// UseRpc reports whether RPC messages can be sent to the Peer
|
|
func (p *Peer) UseRpc() bool {
|
|
p.useRpcMu.RLock()
|
|
defer p.useRpcMu.RUnlock()
|
|
|
|
return p.useRpc
|
|
}
|
|
|
|
// SetUseRpc sets the value returned by UseRpc
|
|
func (p *Peer) SetUseRpc(useRpc bool) {
|
|
p.useRpcMu.Lock()
|
|
defer p.useRpcMu.Unlock()
|
|
|
|
p.useRpc = useRpc
|
|
}
|
|
|
|
// Inv returns the inventory of the Peer
|
|
func (p *Peer) Inv() *mt.Inv { return p.inv }
|
|
|
|
// Connect connects to the server on conn
|
|
// and closes conn when the Peer disconnects
|
|
func Connect(conn net.PacketConn, addr net.Addr) (*Peer, error) {
|
|
srv := &Peer{Peer: rudp.Connect(conn, addr)}
|
|
|
|
ack, err := srv.Send(rudp.Pkt{Data: []byte{0, 0}})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
select {
|
|
case <-time.After(8 * time.Second):
|
|
srv.SendDisco(0, true)
|
|
srv.Close()
|
|
|
|
return nil, ErrServerUnreachable
|
|
case <-ack:
|
|
}
|
|
|
|
return srv, nil
|
|
}
|
|
|
|
// GetPeerCount reports how many client Peers are connected
|
|
func GetPeerCount() int {
|
|
connectedPeersMu.RLock()
|
|
defer connectedPeersMu.RUnlock()
|
|
|
|
return connectedPeers
|
|
}
|