Files
Erupe/Erupe/server/entranceserver/make_resp.go
2022-07-06 00:19:15 +10:00

129 lines
3.6 KiB
Go

package entranceserver
import (
"encoding/binary"
"net"
"erupe-ce/common/stringsupport"
"github.com/Andoryuuta/byteframe"
"erupe-ce/config"
"erupe-ce/server/channelserver"
)
func paddedString(x string, size uint) []byte {
out := make([]byte, size)
copy(out, x)
// Null terminate it.
out[len(out)-1] = 0
return out
}
// Server Entries
var name string
var season uint8
// Server Channels
var currentplayers uint16
func encodeServerInfo(serverInfos []config.EntranceServerInfo, s *Server) []byte {
bf := byteframe.NewByteFrame()
for serverIdx, si := range serverInfos {
err := s.db.QueryRow("SELECT server_name FROM servers WHERE server_name=$1", si.Name).Scan(&name)
if err != nil {
_, err := s.db.Exec("INSERT INTO servers (server_name, season, current_players, event_id, event_expiration) VALUES ($1, $2, 0, 0, 0)", si.Name, si.Season)
if err != nil {
panic(err)
}
} else {
err := s.db.QueryRow("SELECT season FROM servers WHERE server_name=$1", si.Name).Scan(&season)
if err != nil {
panic(err)
}
}
bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(si.IP).To4()))
bf.WriteUint16(16 + uint16(serverIdx))
bf.WriteUint16(0x0000)
bf.WriteUint16(uint16(len(si.Channels)))
bf.WriteUint8(si.Type)
bf.WriteUint8(season)
bf.WriteUint8(si.Recommended)
shiftjisName, err := stringsupport.ConvertUTF8ToShiftJIS(si.Name)
if err != nil {
panic(err)
}
bf.WriteBytes(paddedString(string(shiftjisName), 66))
bf.WriteUint32(si.AllowedClientFlags)
for channelIdx, ci := range si.Channels {
bf.WriteUint16(ci.Port)
bf.WriteUint16(16 + uint16(channelIdx))
bf.WriteUint16(ci.MaxPlayers)
err := s.db.QueryRow("SELECT current_players FROM servers WHERE server_name=$1", si.Name).Scan(&currentplayers)
if err != nil {
panic(err)
}
bf.WriteUint16(currentplayers)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint16(ci.Unk0)
bf.WriteUint16(ci.Unk1)
bf.WriteUint16(ci.Unk2)
bf.WriteUint16(0x3039)
}
}
bf.WriteUint32(uint32(channelserver.Time_Current_Adjusted().Unix()))
bf.WriteUint32(0x0000003C)
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 makeSv2Resp(servers []config.EntranceServerInfo, s *Server) []byte {
rawServerData := encodeServerInfo(servers, s)
bf := byteframe.NewByteFrame()
bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(servers)), 0x00))
return bf.Data()
}
func makeUsrResp(pkt []byte) []byte {
// 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?
// uint16 for number of requested ids
// uint32 for each id
// response seems to be server number starting from 10 10 00 00 for server 1 channel 1?
bf := byteframe.NewByteFrameFromBytes(pkt)
_ = bf.ReadUint32() // ALL+
_ = bf.ReadUint8() // 0x00
userEntries := bf.ReadUint16()
// actual process will be reading all ids and returning real server, just returning all in server 1 for now
bf = byteframe.NewByteFrame()
for i := 0; i < int(userEntries); i++ {
bf.WriteBytes([]byte{0x10, 0x10, 0x00, 0x00})
}
return makeHeader(bf.Data(), "USR", userEntries, 0x00)
}