Matchmaking: Handle server list command

This commit is contained in:
mkwcat
2023-10-20 03:36:51 -04:00
parent 50fc53aa5c
commit ecf8fcf32c
2 changed files with 73 additions and 25 deletions

View File

@@ -79,9 +79,6 @@ func handleRequest(conn net.Conn) {
fmt.Printf("Unable to set keepalive - %s", err)
}
// log.Printf("%s: Connection established from %s. Sending challenge.", aurora.Green("[NOTICE]"), aurora.Yellow(conn.RemoteAddr()))
// conn.Write([]byte(fmt.Sprintf(`\lc\1\challenge\%s\id\1\final\`, challenge)))
// Here we go into the listening loop
for {
buffer := make([]byte, 1024)
@@ -95,11 +92,13 @@ func handleRequest(conn net.Conn) {
switch buffer[2] {
case ServerList:
logging.Notice(ModuleName, "Command:", aurora.Yellow("SERVER_LIST").String())
serverList(conn, buffer)
break
default:
logging.Notice(ModuleName, "Command:", aurora.Yellow(buffer[2]).String())
logging.Notice(ModuleName, "Unknown command:", aurora.Yellow(buffer[2]).String())
break
}
}

View File

@@ -2,6 +2,7 @@ package matchmaking
import (
"encoding/binary"
"github.com/logrusorgru/aurora/v3"
"net"
"strconv"
"strings"
@@ -9,29 +10,36 @@ import (
"wwfc/logging"
)
func popString(buffer []byte, index int) (string, int) {
str := common.GetString(buffer[index:])
return str, index + len(str) + 1
}
func popBytes(buffer []byte, index int, size int) ([]byte, int) {
return buffer[index : index+size], index + size
}
func popUint32(buffer []byte, index int) (uint32, int) {
return binary.BigEndian.Uint32(buffer[index:]), index + 4
}
func serverList(conn net.Conn, buffer []byte) {
logging.Notice(ModuleName, "Received server list command")
const (
FlagNoServerList = 1 << 1 // 0x02
FlagAlternateSourceIP = 1 << 3 // 0x08
FlagLimitResultCount = 1 << 7 // 0x80
)
index := 9
queryGame := common.GetString(buffer[index:])
index += len(queryGame) + 1
gameName := common.GetString(buffer[index:])
index += len(gameName) + 1
queryGame, index := popString(buffer, index)
gameName, index := popString(buffer, index)
challenge, index := popBytes(buffer, index, 8)
filter, index := popString(buffer, index)
fields, index := popString(buffer, index)
flags, index := popUint32(buffer, index)
challenge := buffer[index : index+8]
index += 8
logging.Notice(ModuleName, "queryGame:", aurora.Cyan(queryGame).String(), "- gameName:", aurora.Cyan(gameName).String(), "- filter:", aurora.Cyan(filter).String(), "- fields:", aurora.Cyan(fields).String())
filter := common.GetString(buffer[index:])
index += len(filter) + 1
fields := common.GetString(buffer[index:])
index += len(fields) + 1
options := binary.BigEndian.Uint32(buffer[index:])
index += 4
logging.Notice(ModuleName, "Values", queryGame, gameName, string(challenge), string(options))
// TODO: Find a game if possible, but there is nobody to do that with yet!
var output []byte
for _, s := range strings.Split(strings.Split(conn.RemoteAddr().String(), ":")[0], ".") {
val, err := strconv.Atoi(s)
@@ -42,8 +50,49 @@ func serverList(conn net.Conn, buffer []byte) {
output = append(output, byte(val))
}
output = binary.BigEndian.AppendUint16(output, 6500)
var fieldList []string
for _, field := range strings.Split(fields, "\\") {
if len(field) == 0 || field == " " {
continue
}
encrypted := common.EncryptTypeX([]byte("9r3Rmy"), challenge, output)
conn.Write(encrypted)
fieldList = append(fieldList, field)
}
if flags&FlagNoServerList != 0 || len(fieldList) == 0 {
// The client requests its own public IP and game port
logging.Notice(ModuleName, "Reply without server list", aurora.Cyan(conn.RemoteAddr()).String())
// The default game port 6500
output = binary.BigEndian.AppendUint16(output, 6500)
// Write the encrypted reply
conn.Write(common.EncryptTypeX([]byte("9r3Rmy"), challenge, output))
return
}
logging.Notice(ModuleName, "Reply with server list", aurora.Cyan(conn.RemoteAddr()).String())
// The client's port
port, err := strconv.Atoi(strings.Split(conn.RemoteAddr().String(), ":")[1])
if err != nil {
panic(err)
}
output = binary.BigEndian.AppendUint16(output, uint16(port))
output = append(output, byte(len(fieldList)))
for _, field := range fieldList {
output = append(output, 0x00) // Value?
output = append(output, []byte(field)...)
output = append(output, 0x00) // String end
}
output = append(output, 0x00) // Zero length string to end the list
// TODO: Send server list here
// Server with no flags and -1 tells the client the message has ended
output = append(output, []byte{0x00, 0xff, 0xff, 0xff, 0xff}...)
// Write the encrypted reply
conn.Write(common.EncryptTypeX([]byte("9r3Rmy"), challenge, output))
}