diff --git a/api/groups.go b/api/groups.go index 54e3b77..5fc034e 100644 --- a/api/groups.go +++ b/api/groups.go @@ -5,7 +5,6 @@ import ( "net/http" "net/url" "strconv" - "wwfc/common" "wwfc/qr2" ) @@ -24,27 +23,6 @@ func HandleGroups(w http.ResponseWriter, r *http.Request) { groups := qr2.GetGroups(query["game"], query["id"]) - for _, group := range groups { - for i, player := range group.Players { - filtered := map[string]string{} - - filtered["count"] = player["+localplayers"] - filtered["pid"] = player["dwc_pid"] - filtered["name"] = player["+ingamesn"] - - if player["gamename"] == "mariokartwii" { - filtered["ev"] = player["ev"] - filtered["eb"] = player["eb"] - pid, err := strconv.ParseUint(player["dwc_pid"], 10, 32) - if err == nil { - filtered["fc"] = common.CalcFriendCodeString(uint32(pid), "RMCJ") - } - } - - group.Players[i] = filtered - } - } - var jsonData []byte if len(groups) == 0 { jsonData, _ = json.Marshal([]string{}) diff --git a/common/mii.go b/common/mii.go index 37cf770..f3ea12a 100644 --- a/common/mii.go +++ b/common/mii.go @@ -1,8 +1,10 @@ package common -// CalculateMiiCRC -// https://github.com/kiwi515/ogws/blob/ee72b2a329c50b773fcdce5c302e5674e5f2cf11/src/RVLFaceLib/RFL_Database.c#L640 -func CalculateMiiCRC(data []byte) uint16 { +// References: +// https://wiibrew.org/wiki/Mii_Data +// https://github.com/kiwi515/ogws/tree/master/src/RVLFaceLib + +func RFLCalculateCRC(data []byte) uint16 { crc := uint16(0) for _, val := range data { @@ -24,3 +26,22 @@ func CalculateMiiCRC(data []byte) uint16 { return crc } + +var officialMiiList = []uint64{ + 0x80000000ECFF82D2, + 0x80000001ECFF82D2, + 0x80000002ECFF82D2, + 0x80000003ECFF82D2, + 0x80000004ECFF82D2, + 0x80000005ECFF82D2, +} + +func RFLSearchOfficialData(id uint64) (bool, int) { + for i, v := range officialMiiList { + if v == id { + return true, i + } + } + + return false, -1 +} diff --git a/common/strings.go b/common/strings.go index 0cd695b..0474c90 100644 --- a/common/strings.go +++ b/common/strings.go @@ -2,8 +2,10 @@ package common import ( "bytes" + "encoding/binary" "errors" "math/rand" + "unicode/utf16" ) var letterRunes = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ") @@ -36,6 +38,18 @@ func GetString(buf []byte) (string, error) { return string(buf[:nullTerminator]), nil } +func GetWideString(buf []byte, byteOrder binary.ByteOrder) (string, error) { + var utf16String []uint16 + for i := 0; i < len(buf)/2; i++ { + if buf[i*2] == 0 && buf[i*2+1] == 0 { + break + } + + utf16String = append(utf16String, byteOrder.Uint16(buf[i*2:i*2+2])) + } + return string(utf16.Decode(utf16String)), nil +} + // IsUppercaseAlphanumeric checks if the given string is composed exclusively of uppercase alphanumeric characters. func IsUppercaseAlphanumeric(str string) bool { strLength := len(str) diff --git a/qr2/group.go b/qr2/group.go index ba10498..92e396a 100644 --- a/qr2/group.go +++ b/qr2/group.go @@ -1,6 +1,8 @@ package qr2 import ( + "encoding/base64" + "encoding/binary" "fmt" "strconv" "strings" @@ -253,7 +255,75 @@ func CheckGPReservationAllowed(senderIP uint64, senderPid uint32, destPid uint32 } func ProcessUSER(senderPid uint32, senderIP uint64, packet []byte) { - // TODO + moduleName := "QR2:ProcessUSER/" + strconv.FormatUint(uint64(senderPid), 10) + + mutex.Lock() + login := logins[senderPid] + if login == nil { + mutex.Unlock() + logging.Warn(moduleName, "Received USER packet from non-existent profile ID", aurora.Cyan(senderPid)) + return + } + + gpErrorCallback := login.GPErrorCallback + + session := login.Session + if session == nil { + mutex.Unlock() + logging.Warn(moduleName, "Received USER packet from profile ID", aurora.Cyan(senderPid), "but no session exists") + return + } + mutex.Unlock() + + miiGroupCount := binary.BigEndian.Uint16(packet[0x04:0x06]) + if miiGroupCount != 2 { + logging.Error(moduleName, "Received USER packet with unexpected Mii group count", aurora.Cyan(miiGroupCount)) + // Kick the client + gpErrorCallback(senderPid, "malpacket") + return + } + + miiGroupBitflags := binary.BigEndian.Uint32(packet[0x00:0x04]) + + var miiData []string + var miiName []string + for i := 0; i < int(miiGroupCount); i++ { + if miiGroupBitflags&(1<