Lua -> Go: Send command family

master
HimbeerserverDE 2021-01-14 19:06:40 +01:00
parent 3658be0384
commit f39b46e2ee
10 changed files with 248 additions and 117 deletions

View File

@ -170,3 +170,7 @@ func wider(b []byte) []byte {
return r
}
func init() {
chatCommands = make(map[string]chatCommand)
}

View File

@ -1,8 +1,6 @@
package multiserver
import (
"encoding/binary"
)
import "encoding/binary"
const (
ToClientHello = 0x02

6
end.go
View File

@ -13,11 +13,11 @@ func End(crash, reconnect bool) {
data := make([]byte, 7)
data[0] = uint8(0x00)
data[1] = uint8(0x0A)
data[1] = uint8(ToClientAccessDenied)
if crash {
data[2] = uint8(0x0C)
data[2] = uint8(AccessDeniedCrash)
} else {
data[2] = uint8(0x0B)
data[2] = uint8(AccessDeniedShutdown)
}
data[3] = uint8(0x00)
data[4] = uint8(0x00)

81
init.go
View File

@ -63,7 +63,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
}
switch cmd := binary.BigEndian.Uint16(pkt.Data[0:2]); cmd {
case 0x02:
case ToClientHello:
if pkt.Data[10]&AuthMechSRP > 0 {
// Compute and send SRP_BYTES_A
_, _, err := srp.NewClient([]byte(strings.ToLower(string(p.username))), passPhrase)
@ -83,7 +83,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
data := make([]byte, 5+len(p.srp_A))
data[0] = uint8(0x00)
data[1] = uint8(0x51)
data[1] = uint8(ToServerSrpBytesA)
binary.BigEndian.PutUint16(data[2:4], uint16(len(p.srp_A)))
copy(data[4:4+len(p.srp_A)], p.srp_A)
data[4+len(p.srp_A)] = uint8(1)
@ -104,7 +104,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
data := make([]byte, 7+len(s)+len(v))
data[0] = uint8(0x00)
data[1] = uint8(0x50)
data[1] = uint8(ToServerFirstSrp)
binary.BigEndian.PutUint16(data[2:4], uint16(len(s)))
copy(data[4:4+len(s)], s)
binary.BigEndian.PutUint16(data[4+len(s):6+len(s)], uint16(len(v)))
@ -118,7 +118,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
}
<-ack
}
case 0x60:
case ToClientSrpBytesSB:
// Compute and send SRP_BYTES_M
lenS := binary.BigEndian.Uint16(pkt.Data[2:4])
s := pkt.Data[4 : lenS+4]
@ -136,7 +136,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
data := make([]byte, 4+len(M))
data[0] = uint8(0x00)
data[1] = uint8(0x52)
data[1] = uint8(ToServerSrpBytesM)
binary.BigEndian.PutUint16(data[2:4], uint16(len(M)))
copy(data[4:], M)
@ -146,13 +146,13 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
continue
}
<-ack
case 0x0A:
case ToClientAccessDenied:
// Auth failed for some reason
log.Print(ErrAuthFailed)
data := []byte{
uint8(0x00), uint8(0x0A),
uint8(0x09), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(ToClientAccessDenied),
uint8(AccessDeniedServerFail), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
ack, err := p.Send(Pkt{Data: data})
@ -164,9 +164,9 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
p.SendDisco(0, true)
p.Close()
return
case 0x03:
case ToClientAuthAccept:
// Auth succeeded
ack, err := p2.Send(Pkt{Data: []byte{uint8(0), uint8(0x11), uint8(0), uint8(0)}, ChNo: 1})
ack, err := p2.Send(Pkt{Data: []byte{uint8(0), uint8(ToServerInit2), uint8(0), uint8(0)}, ChNo: 1})
if err != nil {
log.Print(err)
continue
@ -176,7 +176,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
if !ignMedia {
return
}
case 0x2A:
case ToClientCsmRestrictionFlags:
// Definitions sent (by server)
if !ignMedia {
continue
@ -185,7 +185,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
v := []byte("5.4.0-dev-dd5a732fa")
data := make([]byte, 8+len(v))
copy(data[0:6], []byte{uint8(0), uint8(0x43), uint8(5), uint8(4), uint8(0), uint8(0)})
copy(data[0:6], []byte{uint8(0), uint8(ToServerClientReady), uint8(5), uint8(4), uint8(0), uint8(0)})
binary.BigEndian.PutUint16(data[6:8], uint16(len(v)))
copy(data[8:], v)
@ -226,18 +226,37 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
}
switch cmd := binary.BigEndian.Uint16(pkt.Data[0:2]); cmd {
case 0x02:
case ToServerInit:
// Process data
p2.username = pkt.Data[11:]
// Send HELLO
data := make([]byte, 13+len(p2.username))
data[0] = uint8(0x00)
data[1] = uint8(0x02)
data[1] = uint8(ToClientHello)
data[2] = uint8(0x1c)
binary.BigEndian.PutUint16(data[3:5], uint16(0x0000))
binary.BigEndian.PutUint16(data[5:7], uint16(0x0027))
// Check if user is already connected
if IsOnline(string(p2.username)) {
data := []byte{
uint8(0x00), uint8(ToClientAccessDenied),
uint8(AccessDeniedAlreadyConnected), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
ack, err := p2.Send(Pkt{Data: data})
if err != nil {
log.Print(err)
continue
}
<-ack
p2.SendDisco(0, true)
p2.Close()
return
}
db, err := initAuthDB()
if err != nil {
log.Print(err)
@ -271,7 +290,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
continue
}
<-ack
case 0x50:
case ToServerFirstSrp:
// Process data
// Make sure the client is allowed to use AuthMechFirstSRP
if p2.authMech != AuthMechFirstSRP {
@ -279,8 +298,8 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send ACCESS_DENIED
data := []byte{
uint8(0x00), uint8(0x0A),
uint8(0x01), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(ToClientAccessDenied),
uint8(AccessDeniedUnexpectedData), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
ack, err := p2.Send(Pkt{Data: data})
@ -326,7 +345,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send AUTH_ACCEPT
data := []byte{
uint8(0x00), uint8(0x03),
uint8(0x00), uint8(ToClientAuthAccept),
// Position stuff
uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
@ -337,7 +356,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send interval
uint8(0x3D), uint8(0xB8), uint8(0x51), uint8(0xEC),
// Sudo mode mechs
uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x02),
uint8(0x00), uint8(0x00), uint8(0x00), uint8(AuthMechSRP),
}
ack, err := p2.Send(Pkt{Data: data})
@ -350,7 +369,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Connect to Minetest server
fin2 := make(chan struct{}) // close-only
Init(p2, p, ignMedia, fin2)
case 0x51:
case ToServerSrpBytesA:
// Process data
// Make sure the client is allowed to use AuthMechSRP
if p2.authMech != AuthMechSRP {
@ -358,8 +377,8 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send ACCESS_DENIED
data := []byte{
uint8(0x00), uint8(0x0A),
uint8(0x01), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(ToClientAccessDenied),
uint8(AccessDeniedUnexpectedData), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
ack, err := p2.Send(Pkt{Data: data, ChNo: 0, Unrel: false})
@ -411,7 +430,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send SRP_BYTES_S_B
data := make([]byte, 6+len(s)+len(B))
data[0] = uint8(0x00)
data[1] = uint8(0x60)
data[1] = uint8(ToClientSrpBytesSB)
binary.BigEndian.PutUint16(data[2:4], uint16(len(s)))
copy(data[4:4+len(s)], s)
binary.BigEndian.PutUint16(data[4+len(s):6+len(s)], uint16(len(B)))
@ -423,7 +442,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
continue
}
<-ack
case 0x52:
case ToServerSrpBytesM:
// Process data
// Make sure the client is allowed to use AuthMechSRP
if p2.authMech != AuthMechSRP {
@ -431,8 +450,8 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send ACCESS_DENIED
data := []byte{
uint8(0x00), uint8(0x0A),
uint8(0x01), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(ToClientAccessDenied),
uint8(AccessDeniedUnexpectedData), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
ack, err := p2.Send(Pkt{Data: data})
@ -456,7 +475,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Password is correct
// Send AUTH_ACCEPT
data := []byte{
uint8(0x00), uint8(0x03),
uint8(0x00), uint8(ToClientAuthAccept),
// Position stuff
uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
@ -467,7 +486,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send interval
uint8(0x3D), uint8(0xB8), uint8(0x51), uint8(0xEC),
// Sudo mode mechs
uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x02),
uint8(0x00), uint8(0x00), uint8(0x00), uint8(AuthMechSRP),
}
ack, err := p2.Send(Pkt{Data: data})
@ -486,8 +505,8 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
// Send ACCESS_DENIED
data := []byte{
uint8(0x00), uint8(0x0A),
uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(ToClientAccessDenied),
uint8(AccessDeniedWrongPassword), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
ack, err := p2.Send(Pkt{Data: data})
@ -501,7 +520,7 @@ func Init(p, p2 *Peer, ignMedia bool, fin chan struct{}) {
p2.Close()
return
}
case 0x11:
case ToServerInit2:
return
}
}

View File

@ -134,8 +134,8 @@ func (l *Listener) processNetPkt(pkt netPkt) error {
if GetPeerCount() >= maxPeers && maxPeers > -1 {
data := []byte{
uint8(0x00), uint8(0x0A),
uint8(0x06), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(ToClientAccessDenied),
uint8(AccessDeniedTooManyUsers), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
_, err := clt.Send(Pkt{Data: data})
@ -183,11 +183,27 @@ func (l *Listener) processNetPkt(pkt netPkt) error {
return nil
}
func (l *Listener) GetPeerByID(id PeerID) *Peer {
func (l *Listener) GetPeerByName(name string) *Peer {
l.mu.Lock()
defer l.mu.Unlock()
return l.id2peer[id].Peer
for i := range l.addr2peer {
if string(l.addr2peer[i].username) == name {
return l.addr2peer[i].Peer
}
}
return nil
}
func (l *Listener) GetPeers() []*Peer {
l.mu.Lock()
defer l.mu.Unlock()
var r []*Peer
for i := range l.addr2peer {
r = append(r, l.addr2peer[i].Peer)
}
return r
}
func SetListener(l *Listener) {

143
multiserver/igutils.go Normal file
View File

@ -0,0 +1,143 @@
package main
import (
"github.com/HimbeerserverDE/multiserver"
"strings"
)
func cmdSend(p *multiserver.Peer, param string) {
if param == "" {
p.SendChatMsg("Usage: #send <playername> <servername>")
return
}
name := strings.Split(param, " ")[0]
if name == "" || len(strings.Split(param, " ")) < 2 {
p.SendChatMsg("Usage: #send <playername> <servername>")
return
}
tosrv := strings.Split(param, " ")[1]
if tosrv == "" {
p.SendChatMsg("Usage: #send <playername> <servername>")
return
}
servers := multiserver.GetConfKey("servers").(map[interface{}]interface{})
if servers[tosrv] == nil {
p.SendChatMsg("Unknown servername " + tosrv)
return
}
p2 := multiserver.GetListener().GetPeerByName(name)
if p2 == nil {
p.SendChatMsg(name + " is not online.")
return
}
var srv string
for server := range servers {
if multiserver.GetConfKey("servers:"+server.(string)+":address") == p2.Server().Addr().String() {
srv = server.(string)
break
}
}
if srv == tosrv {
p.SendChatMsg(name + " is already connected to this server!")
}
p2.Redirect(tosrv)
}
func init() {
privs := make(map[string]map[string]bool)
privs["send"] = make(map[string]bool)
privs["send"]["send"] = true
privs["sendcurrent"] = make(map[string]bool)
privs["sendcurrent"]["send"] = true
multiserver.RegisterChatCommand("send", privs["send"], cmdSend)
multiserver.RegisterChatCommand("sendcurrent", privs["sendcurrent"],
func(p *multiserver.Peer, param string) {
if param == "" {
p.SendChatMsg("Usage: #sendcurrent <servername>")
return
}
servers := multiserver.GetConfKey("servers").(map[interface{}]interface{})
if servers[param] == nil {
p.SendChatMsg("Unknown servername " + param)
}
var srv string
for server := range servers {
if multiserver.GetConfKey("servers:"+server.(string)+":address") == p.Server().Addr().String() {
srv = server.(string)
break
}
}
if srv == param {
p.SendChatMsg("All targets are already connected to this server!")
return
}
p.Redirect(param)
peers := multiserver.GetListener().GetPeers()
for i := range peers {
var psrv string
for server := range servers {
if multiserver.GetConfKey("servers:"+server.(string)+":address") == peers[i].Server().Addr().String() {
psrv = server.(string)
break
}
}
if psrv == srv {
peers[i].Redirect(param)
}
}
})
multiserver.RegisterChatCommand("sendall", nil,
func(p *multiserver.Peer, param string) {
if param == "" {
p.SendChatMsg("Usage: #sendall <servername>")
return
}
servers := multiserver.GetConfKey("servers").(map[interface{}]interface{})
if servers[param] == nil {
p.SendChatMsg("Unknown servername " + param)
}
var srv string
for server := range servers {
if multiserver.GetConfKey("servers:"+server.(string)+":address") == p.Server().Addr().String() {
srv = server.(string)
break
}
}
if srv != param {
p.Redirect(param)
}
peers := multiserver.GetListener().GetPeers()
for i := range peers {
var psrv string
for server := range servers {
if multiserver.GetConfKey("servers:"+server.(string)+":address") == peers[i].Server().Addr().String() {
psrv = server.(string)
break
}
}
if psrv != param {
peers[i].Redirect(param)
}
}
})
}

View File

@ -63,8 +63,8 @@ func main() {
if srv == nil {
data := []byte{
uint8(0x00), uint8(0x0A),
uint8(0x09), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
uint8(0x00), uint8(multiserver.ToClientAccessDenied),
uint8(multiserver.AccessDeniedServerFail), uint8(0x00), uint8(0x00), uint8(0x00), uint8(0x00),
}
_, err := clt.Send(multiserver.Pkt{Data: data})

View File

@ -1,76 +1,3 @@
multiserver.register_chatcommand("send", {
privs = {send = true},
func = function(id, param)
local name = multiserver.split(param, " ")[1]
local tosrv = multiserver.split(param, " ")[2]
if not name or name == "" or not tosrv or tosrv == "" then
return "Usage: /send <playername> <servername>"
end
if not multiserver.get_servers()[tosrv] then
return "Unknown servername " .. tosrv
end
local peerid = multiserver.get_peer_id(name)
if peerid then
if multiserver.get_current_server(peerid) == tosrv then
return name .. " is already connected to this server!"
end
multiserver.redirect(peerid, tosrv)
return "Redirecting " .. name .. " to " .. tosrv .. "."
end
end,
})
multiserver.register_chatcommand("sendcurrent", {
privs = {send = true},
func = function(id, param)
if not param or param == "" then
return "Usage: /sendcurrent <servername>"
end
if not multiserver.get_servers()[param] then
return "Unkown servername " .. param
end
if param == multiserver.get_current_server(id) then
return "All targets are already connected to this server!"
end
local fromsrv = multiserver.get_current_server(id)
for _, peerid in ipairs(multiserver.get_connected_players()) do
if multiserver.get_current_server(peerid) == fromsrv then
multiserver.redirect(peerid, param)
end
end
end,
})
multiserver.register_chatcommand("sendall", {
privs = {send = true},
func = function(id, param)
if not param or param == "" then
return "Usage: /sendall <servername>"
end
if not multiserver.get_servers()[param] then
return "Unkown servername " .. param
end
for _, peerid in ipairs(multiserver.get_connected_players()) do
multiserver.log(peerid)
multiserver.log(multiserver.get_current_server(peerid))
multiserver.log(param)
if multiserver.get_current_server(peerid) ~= param then
multiserver.redirect(peerid, param)
end
end
end,
})
multiserver.register_chatcommand("alert", {
privs = {alert = true},
func = function(id, param)

View File

@ -1,5 +1,10 @@
package multiserver
import "sync"
var onlinePlayers map[string]bool
var onlinePlayerMu sync.RWMutex
var onJoinPlayer []func(*Peer)
var onLeavePlayer []func(*Peer)
@ -12,13 +17,32 @@ func RegisterOnLeavePlayer(function func(*Peer)) {
}
func processJoin(p *Peer) {
onlinePlayerMu.Lock()
defer onlinePlayerMu.Unlock()
onlinePlayers[string(p.username)] = true
for i := range onJoinPlayer {
onJoinPlayer[i](p)
}
}
func processLeave(p *Peer) {
onlinePlayerMu.Lock()
defer onlinePlayerMu.Unlock()
onlinePlayers[string(p.username)] = false
for i := range onLeavePlayer {
onLeavePlayer[i](p)
}
}
func IsOnline(name string) bool {
onlinePlayerMu.RLock()
defer onlinePlayerMu.RUnlock()
return onlinePlayers[name]
}
func init() {
onlinePlayers = make(map[string]bool)
}

View File

@ -75,7 +75,7 @@ func (p *Peer) Redirect(newsrv string) error {
data := make([]byte, 6+len*2)
data[0] = uint8(0x00)
data[1] = uint8(0x31)
data[1] = uint8(ToClientActiveObjectRemoveAdd)
binary.BigEndian.PutUint16(data[2:4], uint16(len))
i := 4
for ao := range aoIDs[p.ID()] {