Browse Source

Use new RUDP version

master
HimbeerserverDE 1 year ago
parent
commit
1540fd54f5
No known key found for this signature in database
GPG Key ID: 1A651504791E6A8B
  1. 85
      active_object.go
  2. 24
      ban.go
  3. 66
      blockdata.go
  4. 60
      chat.go
  5. 248
      command.go
  6. 171
      conn.go
  7. 9
      end.go
  8. 2
      go.mod
  9. 4
      go.sum
  10. 16
      hand.go
  11. 174
      igutils.go
  12. 374
      init.go
  13. 73
      listen.go
  14. 170
      media.go
  15. 8
      multiserver.go
  16. 15
      packet.go
  17. 166
      peer.go
  18. 32
      player.go
  19. 31
      privs.go
  20. 24
      proxy.go
  21. 128
      redirect.go
  22. 167
      rpc.go
  23. 8
      serverlist.go

85
active_object.go

@ -1,6 +1,7 @@
package main
import (
"bytes"
"encoding/binary"
"log"
@ -23,20 +24,23 @@ const (
AoCmdSetAnimSpeed
)
func processAoRmAdd(p *Peer, data []byte) []byte {
countRm := binary.BigEndian.Uint16(data[2:4])
func processAoRmAdd(c *Conn, r *bytes.Reader) []byte {
data := make([]byte, r.Len())
r.Read(data)
countRm := binary.BigEndian.Uint16(data[0:2])
var aoRm []uint16
for i := uint16(0); i < countRm; i += 2 {
id := binary.BigEndian.Uint16(data[4+i : 6+i])
if id == p.localPlayerCao {
id = p.currentPlayerCao
id := binary.BigEndian.Uint16(data[2+i : 4+i])
if id == c.localPlayerCao {
id = c.currentPlayerCao
}
aoRm = append(aoRm, id)
}
countAdd := binary.BigEndian.Uint16(data[4+countRm*2 : 6+countRm*2])
countAdd := binary.BigEndian.Uint16(data[2+countRm*2 : 4+countRm*2])
var aoAdd []uint16
si := 6 + uint32(countRm)*2
si := 4 + uint32(countRm)*2
for i := uint32(0); i < uint32(countAdd); i++ {
id := binary.BigEndian.Uint16(data[si : 2+si])
@ -44,8 +48,8 @@ func processAoRmAdd(p *Peer, data []byte) []byte {
namelen := binary.BigEndian.Uint16(data[8+si : 10+si])
name := data[10+si : 10+si+uint32(namelen)]
if string(name) == p.Username() {
if p.initAoReceived {
if string(name) == c.Username() {
if c.initAoReceived {
initData := data[7+si : 7+si+initDataLen]
// Read the messages from the packet
@ -65,13 +69,13 @@ func processAoRmAdd(p *Peer, data []byte) []byte {
msgpkt := []byte{0x00, ToClientActiveObjectMessages}
for _, msg := range msgs {
msgdata := make([]byte, 4+len(msg))
binary.BigEndian.PutUint16(msgdata[0:2], p.localPlayerCao)
binary.BigEndian.PutUint16(msgdata[0:2], c.localPlayerCao)
binary.BigEndian.PutUint16(msgdata[2:4], uint16(len(msg)))
copy(msgdata[4:], aoMsgReplaceIDs(p, msg))
copy(msgdata[4:], aoMsgReplaceIDs(c, msg))
msgpkt = append(msgpkt, msgdata...)
}
ack, err := p.Send(rudp.Pkt{Data: msgpkt})
ack, err := c.Send(rudp.Pkt{Reader: bytes.NewReader(msgpkt)})
if err != nil {
log.Print(err)
}
@ -79,18 +83,18 @@ func processAoRmAdd(p *Peer, data []byte) []byte {
binary.BigEndian.PutUint16(data[4+countRm*2:6+countRm*2], countAdd-1)
data = append(data[:si], data[7+si+initDataLen:]...)
p.currentPlayerCao = id
c.currentPlayerCao = id
si -= 7 + initDataLen
} else {
p.initAoReceived = true
p.localPlayerCao = id
p.currentPlayerCao = id
c.initAoReceived = true
c.localPlayerCao = id
c.currentPlayerCao = id
}
si += 7 + initDataLen
continue
} else if id == p.localPlayerCao {
id = p.currentPlayerCao
} else if id == c.localPlayerCao {
id = c.currentPlayerCao
binary.BigEndian.PutUint16(data[si:2+si], id)
}
@ -99,63 +103,68 @@ func processAoRmAdd(p *Peer, data []byte) []byte {
si += 7 + initDataLen
}
p.redirectMu.Lock()
c.redirectMu.Lock()
for i := range aoAdd {
if aoAdd[i] != 0 {
p.aoIDs[aoAdd[i]] = true
c.aoIDs[aoAdd[i]] = true
}
}
for i := range aoRm {
p.aoIDs[aoRm[i]] = false
c.aoIDs[aoRm[i]] = false
}
p.redirectMu.Unlock()
c.redirectMu.Unlock()
return data
}
func processAoMsgs(p *Peer, data []byte) []byte {
si := uint32(2)
func processAoMsgs(c *Conn, r *bytes.Reader) []byte {
data := make([]byte, r.Len())
r.Read(data)
si := uint32(0)
for si < uint32(len(data)) {
id := binary.BigEndian.Uint16(data[si : 2+si])
msglen := binary.BigEndian.Uint16(data[2+si : 4+si])
msg := data[4+si : 4+si+uint32(msglen)]
msg = aoMsgReplaceIDs(p, msg)
msg = aoMsgReplaceIDs(c, msg)
copy(data[4+si:4+si+uint32(msglen)], msg)
if id == p.currentPlayerCao {
id = p.localPlayerCao
if id == c.currentPlayerCao {
id = c.localPlayerCao
binary.BigEndian.PutUint16(data[si:2+si], id)
} else if id == p.localPlayerCao {
id = p.currentPlayerCao
} else if id == c.localPlayerCao {
id = c.currentPlayerCao
binary.BigEndian.PutUint16(data[si:2+si], id)
}
si += 4 + uint32(msglen)
}
return data
}
func aoMsgReplaceIDs(p *Peer, data []byte) []byte {
func aoMsgReplaceIDs(c *Conn, data []byte) []byte {
switch cmd := data[0]; cmd {
case AoCmdAttachTo:
id := binary.BigEndian.Uint16(data[1:3])
if id == p.currentPlayerCao {
id = p.localPlayerCao
if id == c.currentPlayerCao {
id = c.localPlayerCao
binary.BigEndian.PutUint16(data[1:3], id)
} else if id == p.localPlayerCao {
id = p.currentPlayerCao
} else if id == c.localPlayerCao {
id = c.currentPlayerCao
binary.BigEndian.PutUint16(data[1:3], id)
}
case AoCmdSpawnInfant:
id := binary.BigEndian.Uint16(data[1:3])
if id == p.currentPlayerCao {
id = p.localPlayerCao
if id == c.currentPlayerCao {
id = c.localPlayerCao
binary.BigEndian.PutUint16(data[1:3], id)
} else if id == p.localPlayerCao {
id = p.currentPlayerCao
} else if id == c.localPlayerCao {
id = c.currentPlayerCao
binary.BigEndian.PutUint16(data[1:3], id)
}
}
return data
}

24
ban.go

@ -1,6 +1,7 @@
package main
import (
"bytes"
"database/sql"
"encoding/binary"
"errors"
@ -116,15 +117,15 @@ func BanList() (map[string]string, error) {
return r, nil
}
// IsBanned reports whether a Peer is banned
func (p *Peer) IsBanned() (bool, string, error) {
// IsBanned reports whether a Conn is banned
func (c *Conn) IsBanned() (bool, string, error) {
db, err := initAuthDB()
if err != nil {
return true, "", err
}
defer db.Close()
addr := p.Addr().(*net.UDPAddr).IP.String()
addr := c.Addr().(*net.UDPAddr).IP.String()
name, err := readBanItem(db, addr)
if err != nil {
@ -134,15 +135,15 @@ func (p *Peer) IsBanned() (bool, string, error) {
return name != "", name, nil
}
// Ban adds a Peer to the ban list
func (p *Peer) Ban() error {
banned, _, err := p.IsBanned()
// Ban adds a Conn to the ban list
func (c *Conn) Ban() error {
banned, _, err := c.IsBanned()
if err != nil {
return err
}
if banned {
return fmt.Errorf("ip address %s is already banned", p.Addr().String())
return fmt.Errorf("ip address %s is already banned", c.Addr().String())
}
db, err := initAuthDB()
@ -151,8 +152,8 @@ func (p *Peer) Ban() error {
}
defer db.Close()
name := p.Username()
addr := p.Addr().(*net.UDPAddr).IP.String()
name := c.Username()
addr := c.Addr().(*net.UDPAddr).IP.String()
err = addBanItem(db, addr, name)
if err != nil {
@ -171,14 +172,13 @@ func (p *Peer) Ban() error {
data[5+l] = uint8(0x00)
data[6+l] = uint8(0x00)
ack, err := p.Send(rudp.Pkt{Data: data})
ack, err := c.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
return err
}
<-ack
p.SendDisco(0, true)
p.Close()
c.Close()
return nil
}

66
blockdata.go

@ -5,32 +5,33 @@ import (
"compress/zlib"
"encoding/binary"
"io"
"github.com/anon55555/mt/rudp"
)
const NodeCount = 16 * 16 * 16
func processBlockdata(p *Peer, pkt *rudp.Pkt) bool {
srv := p.ServerName()
func processBlockdata(c *Conn, r *bytes.Reader) ([]byte, bool) {
srv := c.ServerName()
posData := make([]byte, 6)
r.Read(posData)
x := int16(binary.BigEndian.Uint16(pkt.Data[2:4]))
y := int16(binary.BigEndian.Uint16(pkt.Data[4:6]))
z := int16(binary.BigEndian.Uint16(pkt.Data[6:8]))
x := int16(binary.BigEndian.Uint16(posData[0:2]))
y := int16(binary.BigEndian.Uint16(posData[2:4]))
z := int16(binary.BigEndian.Uint16(posData[4:6]))
p.blocks = append(p.blocks, [3]int16{x, y, z})
c.blocks = append(c.blocks, [3]int16{x, y, z})
r := bytes.NewReader(pkt.Data[13:])
r.Seek(13, io.SeekStart)
zr, err := zlib.NewReader(r)
if err != nil {
return true
return nil, true
}
buf := &bytes.Buffer{}
_, err = io.Copy(buf, zr)
if err != nil {
return true
return nil, true
}
zr.Close()
@ -52,30 +53,39 @@ func processBlockdata(p *Peer, pkt *rudp.Pkt) bool {
recompNodes := recompBuf.Bytes()
meta := make([]byte, 65536)
n, err := r.Read(meta)
if err != nil {
return true
}
meta := make([]byte, r.Len())
r.Read(meta)
meta = meta[:n]
r.Seek(2, io.SeekStart)
data := make([]byte, 13+len(recompNodes)+len(meta))
copy(data[:13], pkt.Data[:13])
copy(data[13:13+len(recompNodes)], recompNodes)
copy(data[13+len(recompNodes):], meta)
blockMeta := make([]byte, 11)
r.Read(blockMeta)
pkt.Data = data
data := make([]byte, 11+len(recompNodes)+len(meta))
copy(data[:11], blockMeta)
copy(data[11:11+len(recompNodes)], recompNodes)
copy(data[11+len(recompNodes):], meta)
return false
return data, false
}
func processAddnode(p *Peer, pkt *rudp.Pkt) bool {
srv := p.ServerName()
func processAddnode(c *Conn, r *bytes.Reader) []byte {
srv := c.ServerName()
r.Seek(8, io.SeekStart)
contentID := binary.BigEndian.Uint16(pkt.Data[8:10])
idBytes := make([]byte, 2)
r.Read(idBytes)
contentID := binary.BigEndian.Uint16(idBytes)
newID := NodeDefs()[srv][contentID].ID()
binary.BigEndian.PutUint16(pkt.Data[8:10], newID)
return false
r.Seek(2, io.SeekStart)
data := make([]byte, r.Len())
r.Read(data)
binary.BigEndian.PutUint16(data[6:8], newID)
return data
}

60
chat.go

@ -1,7 +1,9 @@
package main
import (
"bytes"
"encoding/binary"
"io"
"log"
"strings"
"time"
@ -15,17 +17,17 @@ var ChatCommandPrefix string = "#"
type chatCommand struct {
help string
privs map[string]bool
function func(*Peer, string)
function func(*Conn, string)
}
var chatCommands map[string]chatCommand
var onChatMsg []func(*Peer, string) bool
var onChatMsg []func(*Conn, string) bool
var onServerChatMsg []func(*Peer, string) bool
var onServerChatMsg []func(*Conn, string) bool
// RegisterChatCommand registers a callback function that is called
// when a client executes the command and has the required privileges
func RegisterChatCommand(name string, privs map[string]bool, help string, function func(*Peer, string)) {
func RegisterChatCommand(name string, privs map[string]bool, help string, function func(*Conn, string)) {
chatCommands[name] = chatCommand{
privs: privs,
help: help,
@ -40,7 +42,7 @@ func (c chatCommand) Help() string { return c.help }
// when a client sends a chat message
// If a callback function returns true the message is not forwarded
// to the minetest server
func RegisterOnChatMessage(function func(*Peer, string) bool) {
func RegisterOnChatMessage(function func(*Conn, string) bool) {
onChatMsg = append(onChatMsg, function)
}
@ -48,19 +50,24 @@ func RegisterOnChatMessage(function func(*Peer, string) bool) {
// that is called when a server sends a chat message
// If a callback function returns true the message is not forwarded
// to the minetest clients
func RegisterOnServerChatMessage(function func(*Peer, string) bool) {
func RegisterOnServerChatMessage(function func(*Conn, string) bool) {
onServerChatMsg = append(onServerChatMsg, function)
}
func processChatMessage(p *Peer, pkt rudp.Pkt) bool {
s := string(narrow(pkt.Data[4:]))
func processChatMessage(c *Conn, pkt rudp.Pkt) bool {
r := ByteReader(pkt)
wstr := make([]byte, r.Len()-4)
r.ReadAt(wstr, 4)
s := string(narrow(wstr))
if strings.HasPrefix(s, ChatCommandPrefix) {
// Chat command
s = strings.Replace(s, ChatCommandPrefix, "", 1)
params := strings.Split(s, " ")
// Priv check
allow, err := p.CheckPrivs(chatCommands[params[0]].privs)
allow, err := c.CheckPrivs(chatCommands[params[0]].privs)
if err != nil {
log.Print(err)
return true
@ -85,7 +92,7 @@ func processChatMessage(p *Peer, pkt rudp.Pkt) bool {
data[11+len(wstr)] = uint8(0x00)
binary.BigEndian.PutUint32(data[12+len(wstr):16+len(wstr)], uint32(time.Now().Unix()))
ack, err := p.Send(rudp.Pkt{Data: data})
ack, err := c.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
}
@ -115,7 +122,7 @@ func processChatMessage(p *Peer, pkt rudp.Pkt) bool {
data[11+len(wstr)] = uint8(0x00)
binary.BigEndian.PutUint32(data[12+len(wstr):16+len(wstr)], uint32(time.Now().Unix()))
ack, err := p.Send(rudp.Pkt{Data: data})
ack, err := c.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
}
@ -124,13 +131,13 @@ func processChatMessage(p *Peer, pkt rudp.Pkt) bool {
return true
}
chatCommands[params[0]].function(p, strings.Join(params[1:], " "))
chatCommands[params[0]].function(c, strings.Join(params[1:], " "))
return true
} else {
// Regular message
noforward := false
for i := range onChatMsg {
if onChatMsg[i](p, s) {
if onChatMsg[i](c, s) {
noforward = true
}
}
@ -138,20 +145,27 @@ func processChatMessage(p *Peer, pkt rudp.Pkt) bool {
}
}
func processServerChatMessage(p *Peer, pkt rudp.Pkt) bool {
s := string(narrow(pkt.Data[4:]))
func processServerChatMessage(c *Conn, pkt rudp.Pkt) bool {
r := ByteReader(pkt)
r.Seek(4, io.SeekStart)
wstr := make([]byte, r.Len())
r.Read(wstr)
s := string(narrow(wstr))
noforward := false
for i := range onServerChatMsg {
if onServerChatMsg[i](p, s) {
if onServerChatMsg[i](c, s) {
noforward = true
}
}
return noforward
}
// SendChatMsg sends a chat message to the Peer if it isn't a server
func (p *Peer) SendChatMsg(msg string) {
if p.IsSrv() {
// SendChatMsg sends a chat message to a Conn if it isn't a server
func (c *Conn) SendChatMsg(msg string) {
if c.IsSrv() {
return
}
@ -172,17 +186,17 @@ func (p *Peer) SendChatMsg(msg string) {
data[11+len(wstr)] = uint8(0x00)
binary.BigEndian.PutUint32(data[12+len(wstr):16+len(wstr)], uint32(time.Now().Unix()))
ack, err := p.Send(rudp.Pkt{Data: data})
ack, err := c.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
}
<-ack
}
// ChatSendAll sends a chat message to all connected client Peers
// ChatSendAll sends a chat message to all connected client Conns
func ChatSendAll(msg string) {
for _, p := range Peers() {
go p.SendChatMsg(msg)
for _, c := range Conns() {
go c.SendChatMsg(msg)
}
}

248
command.go

@ -4,6 +4,7 @@ import (
"bytes"
"crypto/subtle"
"encoding/binary"
"io"
"log"
"github.com/HimbeerserverDE/srp"
@ -112,19 +113,37 @@ const (
AccessDeniedCrash
)
func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
func processPktCommand(src, dst *Conn, pkt *rudp.Pkt) bool {
r := ByteReader(*pkt)
origReader := *r
pkt.Reader = &origReader
cmdBytes := make([]byte, 2)
r.Read(cmdBytes)
if src.IsSrv() {
switch cmd := binary.BigEndian.Uint16(pkt.Data[0:2]); cmd {
switch cmd := binary.BigEndian.Uint16(cmdBytes); cmd {
case ToClientActiveObjectRemoveAdd:
pkt.Data = processAoRmAdd(dst, pkt.Data)
pkt.Reader = bytes.NewReader(append(cmdBytes, processAoRmAdd(dst, r)...))
return false
case ToClientActiveObjectMessages:
pkt.Data = processAoMsgs(dst, pkt.Data)
pkt.Reader = bytes.NewReader(append(cmdBytes, processAoMsgs(dst, r)...))
return false
case ToClientChatMessage:
namelen := binary.BigEndian.Uint16(pkt.Data[4:6])
msglen := binary.BigEndian.Uint16(pkt.Data[6+namelen : 8+namelen])
msg := pkt.Data[8+namelen:]
r.Seek(2, io.SeekCurrent)
namelenBytes := make([]byte, 2)
r.Read(namelenBytes)
namelen := binary.BigEndian.Uint16(namelenBytes)
r.Seek(int64(namelen), io.SeekCurrent)
msglenBytes := make([]byte, 2)
r.Read(msglenBytes)
msglen := binary.BigEndian.Uint16(msglenBytes)
msg := make([]byte, r.Len())
r.Read(msg)
data := make([]byte, 4+msglen*2)
data[0] = uint8(0x00)
@ -132,64 +151,134 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
binary.BigEndian.PutUint16(data[2:4], uint16(msglen))
copy(data[4:], msg)
return processServerChatMessage(dst, rudp.Pkt{Data: data, ChNo: pkt.ChNo})
return processServerChatMessage(dst, rudp.Pkt{
Reader: bytes.NewReader(data),
PktInfo: rudp.PktInfo{
Channel: pkt.Channel,
},
})
case ToClientModChannelSignal:
chlen := binary.BigEndian.Uint16(pkt.Data[3:5])
ch := string(pkt.Data[5 : 5+chlen])
r.Seek(1, io.SeekCurrent)
chlenBytes := make([]byte, 2)
r.Read(chlenBytes)
chlen := binary.BigEndian.Uint16(chlenBytes)
chBytes := make([]byte, chlen)
r.Read(chBytes)
state, _ := r.ReadByte()
r.Seek(2, io.SeekStart)
ch := string(chBytes)
if ch == rpcCh {
switch sig := pkt.Data[2]; sig {
switch sig, _ := r.ReadByte(); sig {
case ModChSigJoinOk:
src.SetUseRpc(true)
case ModChSigSetState:
state := pkt.Data[5+chlen]
if state == ModChStateRO {
src.SetUseRpc(false)
}
}
return true
}
return false
case ToClientModChannelMsg:
return processRpc(src, *pkt)
return processRpc(src, r)
case ToClientBlockdata:
return processBlockdata(dst, pkt)
data, drop := processBlockdata(dst, r)
if drop {
return true
}
pkt.Reader = bytes.NewReader(append(cmdBytes, data...))
return false
case ToClientAddNode:
return processAddnode(dst, pkt)
pkt.Reader = bytes.NewReader(append(cmdBytes, processAddnode(dst, r)...))
return false
case ToClientHudAdd:
id := binary.BigEndian.Uint32(pkt.Data[2:6])
idBytes := make([]byte, 4)
r.Read(idBytes)
id := binary.BigEndian.Uint32(idBytes)
dst.huds[id] = true
return false
case ToClientHudRm:
id := binary.BigEndian.Uint32(pkt.Data[2:6])
idBytes := make([]byte, 4)
r.Read(idBytes)
id := binary.BigEndian.Uint32(idBytes)
dst.huds[id] = false
return false
case ToClientPlaySound:
id := int32(binary.BigEndian.Uint32(pkt.Data[2:6]))
namelen := binary.BigEndian.Uint16(pkt.Data[6:8])
objID := binary.BigEndian.Uint16(pkt.Data[17+namelen : 19+namelen])
idBytes := make([]byte, 4)
r.Read(idBytes)
id := int32(binary.BigEndian.Uint32(idBytes))
namelenBytes := make([]byte, 2)
r.Read(namelenBytes)
namelen := binary.BigEndian.Uint16(namelenBytes)
r.Seek(int64(17+namelen), io.SeekStart)
objIDBytes := make([]byte, 2)
r.Read(objIDBytes)
objID := binary.BigEndian.Uint16(objIDBytes)
if objID == dst.currentPlayerCao {
objID = dst.localPlayerCao
} else if objID == dst.localPlayerCao {
objID = dst.currentPlayerCao
}
binary.BigEndian.PutUint16(pkt.Data[17+namelen:19+namelen], objID)
if loop := pkt.Data[19+namelen]; loop > 0 {
r.Seek(2, io.SeekStart)
data := make([]byte, r.Len())
r.Read(data)
binary.BigEndian.PutUint16(data[17+namelen:19+namelen], objID)
pkt.Reader = bytes.NewReader(append(cmdBytes, data...))
if loop, _ := r.ReadByte(); loop > 0 {
dst.sounds[id] = true
}
case ToClientStopSound:
id := int32(binary.BigEndian.Uint32(pkt.Data[2:6]))
idBytes := make([]byte, 4)
r.Read(idBytes)
id := int32(binary.BigEndian.Uint32(idBytes))
dst.sounds[id] = false
case ToClientAddParticlespawner:
texturelen := binary.BigEndian.Uint32(pkt.Data[97:101])
id := binary.BigEndian.Uint16(pkt.Data[107+texturelen : 109+texturelen])
r.Seek(97, io.SeekStart)
texturelenBytes := make([]byte, 4)
r.Read(texturelenBytes)
texturelen := binary.BigEndian.Uint32(texturelenBytes)
r.Seek(int64(6+texturelen), io.SeekCurrent)
idBytes := make([]byte, 2)
r.Read(idBytes)
id := binary.BigEndian.Uint16(idBytes)
if id == dst.currentPlayerCao {
id = dst.localPlayerCao
} else if id == dst.localPlayerCao {
id = dst.currentPlayerCao
}
binary.BigEndian.PutUint16(pkt.Data[107+texturelen:109+texturelen], id)
r.Seek(2, io.SeekStart)
data := make([]byte, r.Len())
r.Read(data)
binary.BigEndian.PutUint16(data[107+texturelen:109+texturelen], id)
pkt.Reader = bytes.NewReader(append(cmdBytes, data...))
case ToClientInventory:
if err := dst.Inv().Deserialize(bytes.NewReader(pkt.Data[2:])); err != nil {
if err := dst.Inv().Deserialize(r); err != nil {
return true
}
@ -198,7 +287,7 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
buf := &bytes.Buffer{}
dst.Inv().Serialize(buf)
pkt.Data = append(pkt.Data[:2], buf.Bytes()...)
pkt.Reader = bytes.NewReader(append(cmdBytes, buf.Bytes()...))
return false
case ToClientAccessDenied:
@ -207,12 +296,14 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
return false
}
if pkt.Data[2] != uint8(11) && pkt.Data[2] != uint8(12) {
reason, _ := r.ReadByte()
if reason != uint8(11) && reason != uint8(12) {
return false
}
msg := "shut down"
if pkt.Data[2] == uint8(12) {
if reason == uint8(12) {
msg = "crashed"
}
@ -235,12 +326,27 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
return true
case ToClientMediaPush:
digLen := binary.BigEndian.Uint16(pkt.Data[2:4])
digest := pkt.Data[4 : 4+digLen]
namelen := binary.BigEndian.Uint16(pkt.Data[4+digLen : 6+digLen])
name := pkt.Data[6+digLen : 6+digLen+namelen]
cache := pkt.Data[6+digLen+namelen] == uint8(1)
data := pkt.Data[11+digLen+namelen:]
digLenBytes := make([]byte, 2)
r.Read(digLenBytes)
digLen := binary.BigEndian.Uint16(digLenBytes)
digest := make([]byte, digLen)
r.Read(digest)
namelenBytes := make([]byte, 2)
r.Read(namelenBytes)
namelen := binary.BigEndian.Uint16(namelenBytes)
name := make([]byte, namelen)
r.Read(name)
cacheByte, _ := r.ReadByte()
cache := cacheByte == uint8(1)
r.Seek(5, io.SeekCurrent)
data := make([]byte, r.Len())
r.Read(data)
media[string(name)] = &mediaFile{
digest: digest,
@ -248,8 +354,8 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
noCache: !cache,
}
for _, peer := range Peers() {
ack, err := peer.Send(*pkt)
for _, conn := range Conns() {
ack, err := conn.Send(*pkt)
if err != nil {
log.Print(err)
}
@ -263,7 +369,7 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
return false
}
} else {
switch cmd := binary.BigEndian.Uint16(pkt.Data[0:2]); cmd {
switch cmd := binary.BigEndian.Uint16(cmdBytes); cmd {
case ToServerChatMessage:
return processChatMessage(src, *pkt)
case ToServerFirstSrp:
@ -271,11 +377,19 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
src.sudoMode = false
// This is a password change, save verifier and salt
lenS := binary.BigEndian.Uint16(pkt.Data[2:4])
s := pkt.Data[4 : 4+lenS]
lenSBytes := make([]byte, 2)
r.Read(lenSBytes)
lenS := binary.BigEndian.Uint16(lenSBytes)
s := make([]byte, lenS)
r.Read(s)
lenVBytes := make([]byte, 2)
r.Read(lenVBytes)
lenV := binary.BigEndian.Uint16(lenVBytes)
lenV := binary.BigEndian.Uint16(pkt.Data[4+lenS : 6+lenS])
v := pkt.Data[6+lenS : 6+lenS+lenV]
v := make([]byte, lenV)
r.Read(v)
pwd := encodeVerifierAndSalt(s, v)
@ -295,11 +409,16 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
} else {
log.Print("User " + src.Username() + " at " + src.Addr().String() + " did not enter sudo mode before attempting to change the password")
}
return true
case ToServerSrpBytesA:
if !src.sudoMode {
lenA := binary.BigEndian.Uint16(pkt.Data[2:4])
A := pkt.Data[4 : 4+lenA]
lenABytes := make([]byte, 2)
r.Read(lenABytes)
lenA := binary.BigEndian.Uint16(lenABytes)
A := make([]byte, lenA)
r.Read(A)
db, err := initAuthDB()
if err != nil {
@ -341,7 +460,7 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
binary.BigEndian.PutUint16(data[4+len(s):6+len(s)], uint16(len(B)))
copy(data[6+len(s):6+len(s)+len(B)], B)
ack, err := src.Send(rudp.Pkt{Data: data})
ack, err := src.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
return true
@ -351,8 +470,12 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
return true
case ToServerSrpBytesM:
if !src.sudoMode {
lenM := binary.BigEndian.Uint16(pkt.Data[2:4])
M := pkt.Data[4 : 4+lenM]
lenMBytes := make([]byte, 2)
r.Read(lenMBytes)
lenM := binary.BigEndian.Uint16(lenMBytes)
M := make([]byte, lenM)
r.Read(M)
M2 := srp.CalculateM([]byte(src.Username()), src.srp_s, src.srp_A, src.srp_B, src.srp_K)
@ -364,7 +487,7 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
// Send ACCEPT_SUDO_MODE
data := []byte{0, ToClientAcceptSudoMode}
ack, err := src.Send(rudp.Pkt{Data: data})
ack, err := src.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
return true
@ -377,7 +500,7 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
// Send DENY_SUDO_MODE
data := []byte{0, ToClientDenySudoMode}
ack, err := src.Send(rudp.Pkt{Data: data})
ack, err := src.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
return true
@ -395,7 +518,7 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
binary.BigEndian.PutUint16(data[3:5], uint16(len(rpcCh)))
copy(data[5:], []byte(rpcCh))
ack, err := src.Send(rudp.Pkt{Data: data})
ack, err := src.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
}
@ -408,7 +531,11 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
return true
}
ch := string(pkt.Data[4:])
r.Seek(2, io.SeekCurrent)
chBytes := make([]byte, r.Len())
r.Read(chBytes)
ch := string(chBytes)
if ch == rpcCh {
deny()
return true
@ -425,7 +552,7 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
binary.BigEndian.PutUint16(data[3:5], uint16(len(rpcCh)))
copy(data[5:], []byte(rpcCh))
ack, err := src.Send(rudp.Pkt{Data: data})
ack, err := src.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
if err != nil {
log.Print(err)
}
@ -438,7 +565,11 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
return true
}
ch := string(pkt.Data[4:])
r.Seek(2, io.SeekCurrent)
chBytes := make([]byte, r.Len())
r.Read(chBytes)
ch := string(chBytes)
if ch == rpcCh {
deny()
return true
@ -452,8 +583,13 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool {
return true
}
chlen := binary.BigEndian.Uint16(pkt.Data[2:4])
ch := string(pkt.Data[4 : 4+chlen])
chlenBytes := make([]byte, 2)
r.Read(chlenBytes)
chlen := binary.BigEndian.Uint16(chlenBytes)
chBytes := make([]byte, chlen)
r.Read(chBytes)
ch := string(chBytes)
if ch == rpcCh {
return true
}

171
conn.go

@ -0,0 +1,171 @@
package main
import (
"bytes"
"fmt"
"net"
"sync"
"time"
"github.com/anon55555/mt"
"github.com/anon55555/mt/rudp"
)
var connectedConns int = 0
var connectedConnsMu sync.RWMutex
// A Conn is a connection to a client or server
type Conn struct {
*rudp.Conn
protoVer uint16
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 *Conn
initAoReceived bool
aoIDs map[uint16]bool
localPlayerCao uint16
currentPlayerCao uint16
useRpcMu sync.RWMutex
useRpc bool
noClt bool
modChs map[string]bool
huds map[uint32]bool
sounds map[int32]bool
blocks [][3]int16
inv *mt.Inv
}
// ProtoVer returns the protocol version of the Conn
func (c *Conn) ProtoVer() uint16 { return c.protoVer }
// Addr returns the remote address of the Conn
func (c *Conn) Addr() net.Addr {
return c.Conn.RemoteAddr()
}
// Username returns the username of the Conn
// if it isn't a server
func (c *Conn) Username() string { return c.username }
// Forward reports whether the Proxy func should continue or stop
func (c *Conn) Forward() bool {
c.forwardMu.RLock()
defer c.forwardMu.RUnlock()
return !c.stopforward
}
// stopForwarding tells the Proxy func to stop
func (c *Conn) stopForwarding() {
c.forwardMu.Lock()
defer c.forwardMu.Unlock()
c.stopforward = true
}
// Server returns the Conn this Conn is connected to
// if it isn't a server
func (c *Conn) Server() *Conn {
c.srvMu.RLock()
defer c.srvMu.RUnlock()
return c.srv
}
// ServerName returns the name of the Conn this Conn is connected to
// if this Conn is not a server
func (c *Conn) ServerName() string {
servers := ConfKey("servers").(map[interface{}]interface{})
for server := range servers {
if ConfKey("servers:"+server.(string)+":address") == c.Server().Addr().String() {
return server.(string)
}
}
return ""
}
// SetServer sets the Conn this Conn is connected to
// if this Conn is not a server
func (c *Conn) SetServer(s *Conn) {
c.srvMu.Lock()
defer c.srvMu.Unlock()
c.srv = s
}
// UseRpc reports whether RPC messages can be sent to the Conn
func (c *Conn) UseRpc() bool {
c.useRpcMu.RLock()
defer c.useRpcMu.RUnlock()
return c.useRpc
}
// SetUseRpc sets the value returned by UseRpc
func (c *Conn) SetUseRpc(useRpc bool) {
c.useRpcMu.Lock()
defer c.useRpcMu.Unlock()
c.useRpc = useRpc
}
// NoClt reports whether the Conn is RPC-only
func (c *Conn) NoClt() bool { return c.noClt }
// MakeRpcOnly marks the Conn as RPC-only
func (c *Conn) MakeRpcOnly() {
c.noClt = true
}
// Inv returns the inventory of the Conn
func (c *Conn) Inv() *mt.Inv { return c.inv }
// Connect connects to the server on conn
// and closes conn when the Conn disconnects
func Connect(conn net.Conn) (*Conn, error) {
srv := &Conn{Conn: rudp.Connect(conn)}
ack, err := srv.Send(rudp.Pkt{Reader: bytes.NewReader([]byte{0, 0})})
if err != nil {
return nil, err
}
select {
case <-time.After(8 * time.Second):
srv.Close()
return nil, fmt.Errorf("server at %s is unreachable", conn.RemoteAddr().String())
case <-ack:
}
return srv, nil
}
// ConnCount reports how many client Conns are connected
func ConnCount() int {
connectedConnsMu.RLock()
defer connectedConnsMu.RUnlock()
return connectedConns
}

9
end.go

@ -1,6 +1,7 @@
package main
import (
"bytes"
"log"
"os"
"time"
@ -29,19 +30,19 @@ func End(crash, reconnect bool) {
}
data[6] = uint8(0x00)
for _, clt := range Peers() {
_, err := clt.Send(rudp.Pkt{Data: data})
r := bytes.NewReader(data)
for _, clt := range Conns() {
_, err := clt.Send(rudp.Pkt{Reader: r})
if err != nil {
log.Print(err)
}
clt.SendDisco(0, true)
clt.Close()
}
rpcSrvMu.Lock()
for srv := range rpcSrvs {
srv.SendDisco(0, true)
srv.Close()
}
rpcSrvMu.Unlock()

2
go.mod

@ -4,7 +4,7 @@ go 1.16
require (
github.com/HimbeerserverDE/srp v0.0.0-20210220165753-1b954ef7b017
github.com/anon55555/mt v0.0.0-20210303173846-1bae1f4f7ea3
github.com/anon55555/mt v0.0.0-20210322183736-433955e45ef3
github.com/mattn/go-sqlite3 v1.14.6
gopkg.in/yaml.v2 v2.4.0
)

4
go.sum

@ -1,7 +1,7 @@
github.com/HimbeerserverDE/srp v0.0.0-20210220165753-1b954ef7b017 h1:0vIYOfwAd3MtssbclXpCuUHVVV+5VOH0H1ld9+zSxgM=
github.com/HimbeerserverDE/srp v0.0.0-20210220165753-1b954ef7b017/go.mod h1:pxNH8S2nh4n2DWE0ToX5GnnDr/uEAuaAhJsCpkDLIWw=
github.com/anon55555/mt v0.0.0-20210303173846-1bae1f4f7ea3 h1:oXXIHh5R80MlxHRWuzNphK1/E5EcUuWNv+a2GL+08f4=
github.com/anon55555/mt v0.0.0-20210303173846-1bae1f4f7ea3/go.mod h1:jH4ER+ahjl7H6TczzK+q4V9sXY++U2Geh6/vt3r4Xvs=
github.com/anon55555/mt v0.0.0-20210322183736-433955e45ef3 h1:hTmpFbZdelNmvmKQDsfk+a7vzpLpvtLR5nyzMYI9Xyc=
github.com/anon55555/mt v0.0.0-20210322183736-433955e45ef3/go.mod h1:jH4ER+ahjl7H6TczzK+q4V9sXY++U2Geh6/vt3r4Xvs=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

16
hand.go

@ -6,26 +6,26 @@ import (
"github.com/anon55555/mt"
)
func (p *Peer) UpdateHandCapabs() error {
l := p.Inv().List("hand")
func (c *Conn) UpdateHandCapabs() error {
l := c.Inv().List("hand")
if l == nil {
*p.inv = mt.Inv(append([]mt.NamedInvList(*p.inv), mt.NamedInvList{
*c.inv = mt.Inv(append([]mt.NamedInvList(*c.inv), mt.NamedInvList{
Name: "hand",
InvList: mt.InvList{
Width: 1,
},
}))
l = p.Inv().List("hand")
l = c.Inv().List("hand")
}
var hand mt.Stack
if len(l.Stacks) == 1 && l.Stacks[0].Name != "multiserver:hand_"+p.ServerName() {
if len(l.Stacks) == 1 && l.Stacks[0].Name != "multiserver:hand_"+c.ServerName() {
hand = l.Stacks[0]
caps := handcapabs[p.ServerName()]
caps := handcapabs[c.ServerName()]
if caps == nil {
return fmt.Errorf("hand tool capabilities of server %s missing", p.ServerName())
return fmt.Errorf("hand tool capabilities of server %s missing", c.ServerName())
}
s, err := caps.SerializeJSON()
@ -37,7 +37,7 @@ func (p *Peer) UpdateHandCapabs() error {
} else {
hand = mt.Stack{
Item: mt.Item{
Name: "multiserver:hand_" + p.ServerName(),
Name: "multiserver:hand_" + c.ServerName(),
},
Count: 1,
}

174
igutils.go

@ -22,18 +22,18 @@ func init() {
RegisterChatCommand("help",
nil,
"Shows the help for a command. Shows the help for all commands if executed without arguments. Usage: help [command]",
func(p *Peer, param string) {
func(c *Conn, param string) {
showHelp := func(name string) {
cmd := chatCommands[name]
if help := cmd.Help(); help != "" {
color := "#F00"
if has, err := p.CheckPrivs(cmd.privs); (err == nil && has) || cmd.privs == nil {
if has, err := c.CheckPrivs(cmd.privs); (err == nil && has) || cmd.privs == nil {
color = "#0F0"
}
p.SendChatMsg(Colorize(name, color) + ": " + help)
c.SendChatMsg(Colorize(name, color) + ": " + help)
} else {
p.SendChatMsg("No help available for " + name + ".")
c.SendChatMsg("No help available for " + name + ".")
}
}
@ -49,68 +49,68 @@ func init() {