Files
Erupe/server/entranceserver/make_resp.go
2020-01-19 12:52:57 -05:00

97 lines
2.3 KiB
Go

package entranceserver
import (
"encoding/binary"
"fmt"
"io/ioutil"
"log"
"net"
"github.com/Andoryuuta/Erupe/config"
"github.com/Andoryuuta/byteframe"
)
func paddedString(x string, size uint) []byte {
out := make([]byte, size)
copy(out, x)
// Null terminate it.
out[len(out)-1] = 0
return out
}
func encodeServerInfo(serverInfos []config.EntranceServerInfo) []byte {
bf := byteframe.NewByteFrame()
for serverIdx, si := range serverInfos {
bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(si.IP).To4()))
bf.WriteUint16(16 + uint16(serverIdx))
bf.WriteUint16(si.Unk2)
bf.WriteUint16(uint16(len(si.Channels)))
bf.WriteUint8(si.Type)
bf.WriteUint8(si.Season)
bf.WriteUint8(si.Unk6)
bf.WriteBytes(paddedString(si.Name, 66))
bf.WriteUint32(si.AllowedClientFlags)
for channelIdx, ci := range si.Channels {
fmt.Println("Channel idx", channelIdx)
bf.WriteUint16(ci.Port)
bf.WriteUint16(16 + uint16(channelIdx))
bf.WriteUint16(ci.MaxPlayers)
bf.WriteUint16(ci.CurrentPlayers)
bf.WriteUint16(ci.Unk4)
bf.WriteUint16(ci.Unk5)
bf.WriteUint16(ci.Unk6)
bf.WriteUint16(ci.Unk7)
bf.WriteUint16(ci.Unk8)
bf.WriteUint16(ci.Unk9)
bf.WriteUint16(ci.Unk10)
bf.WriteUint16(ci.Unk11)
bf.WriteUint16(ci.Unk12)
bf.WriteUint16(ci.Unk13)
}
}
return bf.Data()
}
func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byte {
bf := byteframe.NewByteFrame()
bf.WriteBytes([]byte(respType))
bf.WriteUint16(entryCount)
bf.WriteUint16(uint16(len(data)))
if len(data) > 0 {
bf.WriteUint32(CalcSum32(data))
bf.WriteBytes(data)
}
dataToEncrypt := bf.Data()
bf = byteframe.NewByteFrame()
bf.WriteUint8(key)
bf.WriteBytes(EncryptBin8(dataToEncrypt, key))
return bf.Data()
}
func makeResp(servers []config.EntranceServerInfo) []byte {
fmt.Printf("%+v\n", servers)
rawServerData := encodeServerInfo(servers)
bf := byteframe.NewByteFrame()
bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(servers)), 0x00))
// TODO(Andoryuuta): Figure out what this user data is.
// Is it for the friends list at the world selection screen?
// If so, how does it work without the entrance server connection being authenticated?
bf.WriteBytes(makeHeader([]byte{}, "USR", 0, 0x00))
err := ioutil.WriteFile("go_entrance_resp.bin", bf.Data(), 0644)
if err != nil {
log.Fatal(err)
}
return bf.Data()
}