mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-09-25 08:45:32 -05:00
GPCM: Handle commands in a specific order
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
package gpcm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"github.com/logrusorgru/aurora/v3"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -19,7 +17,7 @@ func (g *GameSpySession) isFriendAdded(profileId uint32) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *GameSpySession) addFriend(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) {
|
||||
func (g *GameSpySession) addFriend(command common.GameSpyCommand) {
|
||||
strNewProfileId := command.OtherValues["newprofileid"]
|
||||
newProfileId, err := strconv.ParseUint(strNewProfileId, 10, 32)
|
||||
if err != nil {
|
||||
@@ -56,11 +54,11 @@ func (g *GameSpySession) addFriend(pool *pgxpool.Pool, ctx context.Context, comm
|
||||
sendMessageToProfileId("2", g.User.ProfileId, uint32(newProfileId), "\r\n\r\n|signed|"+common.RandomHexString(32))
|
||||
}
|
||||
|
||||
func (g *GameSpySession) removeFriend(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) {
|
||||
func (g *GameSpySession) removeFriend(command common.GameSpyCommand) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func (g *GameSpySession) authAddFriend(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) {
|
||||
func (g *GameSpySession) authAddFriend(command common.GameSpyCommand) {
|
||||
strFromProfileId := command.OtherValues["fromprofileid"]
|
||||
fromProfileId, err := strconv.ParseUint(strFromProfileId, 10, 32)
|
||||
if err != nil {
|
||||
@@ -77,7 +75,7 @@ func (g *GameSpySession) authAddFriend(pool *pgxpool.Pool, ctx context.Context,
|
||||
g.exchangeFriendStatus(uint32(fromProfileId))
|
||||
}
|
||||
|
||||
func (g *GameSpySession) setStatus(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) {
|
||||
func (g *GameSpySession) setStatus(command common.GameSpyCommand) {
|
||||
status := command.CommandValue
|
||||
|
||||
statstring, ok := command.OtherValues["statstring"]
|
||||
@@ -119,7 +117,7 @@ func (g *GameSpySession) setStatus(pool *pgxpool.Pool, ctx context.Context, comm
|
||||
mutex.Unlock()
|
||||
}
|
||||
|
||||
func (g *GameSpySession) bestieMessage(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) {
|
||||
func (g *GameSpySession) bestieMessage(command common.GameSpyCommand) {
|
||||
if command.CommandValue != "1" {
|
||||
logging.Notice(g.ModuleName, "Received unknown bestie message type:", aurora.Cyan(command.CommandValue))
|
||||
return
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package gpcm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -32,20 +30,20 @@ func generateProof(gpcmChallenge, nasChallenge, authToken, clientChallenge strin
|
||||
return generateResponse(clientChallenge, nasChallenge, authToken, gpcmChallenge)
|
||||
}
|
||||
|
||||
func (g *GameSpySession) Login(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand, challenge string) (string, bool) {
|
||||
func (g *GameSpySession) login(command common.GameSpyCommand) {
|
||||
if g.LoggedIn {
|
||||
log.Fatalf("Attempt to login twice")
|
||||
}
|
||||
|
||||
// TODO: Validate login token with one in database
|
||||
authToken := command.OtherValues["authtoken"]
|
||||
response := generateResponse(challenge, "0qUekMb4", authToken, command.OtherValues["challenge"])
|
||||
response := generateResponse(g.Challenge, "0qUekMb4", authToken, command.OtherValues["challenge"])
|
||||
if response != command.OtherValues["response"] {
|
||||
// TODO: Return an error
|
||||
log.Fatalf("response mismatch")
|
||||
}
|
||||
|
||||
proof := generateProof(challenge, "0qUekMb4", command.OtherValues["authtoken"], command.OtherValues["challenge"])
|
||||
proof := generateProof(g.Challenge, "0qUekMb4", command.OtherValues["authtoken"], command.OtherValues["challenge"])
|
||||
|
||||
// Perform the login with the database.
|
||||
// TODO: Check valid result
|
||||
@@ -76,7 +74,7 @@ func (g *GameSpySession) Login(pool *pgxpool.Pool, ctx context.Context, command
|
||||
g.ModuleName += ":" + strconv.FormatInt(int64(g.User.ProfileId), 10)
|
||||
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, "RMCJ")
|
||||
|
||||
return common.CreateGameSpyMessage(common.GameSpyCommand{
|
||||
payload := common.CreateGameSpyMessage(common.GameSpyCommand{
|
||||
Command: "lc",
|
||||
CommandValue: "2",
|
||||
OtherValues: map[string]string{
|
||||
@@ -88,7 +86,9 @@ func (g *GameSpySession) Login(pool *pgxpool.Pool, ctx context.Context, command
|
||||
"lt": loginTicket,
|
||||
"id": command.OtherValues["id"],
|
||||
},
|
||||
}), true
|
||||
})
|
||||
|
||||
g.Conn.Write([]byte(payload))
|
||||
}
|
||||
|
||||
func IsLoggedIn(profileID uint32) bool {
|
||||
|
||||
118
gpcm/main.go
118
gpcm/main.go
@@ -21,6 +21,7 @@ type GameSpySession struct {
|
||||
User database.User
|
||||
ModuleName string
|
||||
LoggedIn bool
|
||||
Challenge string
|
||||
Status string
|
||||
LocString string
|
||||
FriendList []uint32
|
||||
@@ -93,14 +94,16 @@ func handleRequest(conn net.Conn) {
|
||||
User: database.User{},
|
||||
ModuleName: "GPCM",
|
||||
LoggedIn: false,
|
||||
Challenge: "",
|
||||
Status: "",
|
||||
LocString: "",
|
||||
FriendList: []uint32{},
|
||||
}
|
||||
|
||||
defer session.closeSession()
|
||||
|
||||
// Set session ID and challenge
|
||||
challenge := common.RandomString(10)
|
||||
session.Challenge = common.RandomString(10)
|
||||
|
||||
err := conn.(*net.TCPConn).SetKeepAlive(true)
|
||||
if err != nil {
|
||||
@@ -112,7 +115,15 @@ func handleRequest(conn net.Conn) {
|
||||
logging.Notice(session.ModuleName, "Unable to set keepalive (2):", err.Error())
|
||||
}
|
||||
|
||||
conn.Write([]byte(fmt.Sprintf(`\lc\1\challenge\%s\id\1\final\`, challenge)))
|
||||
payload := common.CreateGameSpyMessage(common.GameSpyCommand{
|
||||
Command: "lc",
|
||||
CommandValue: "1",
|
||||
OtherValues: map[string]string{
|
||||
"challenge": session.Challenge,
|
||||
"id": "1",
|
||||
},
|
||||
})
|
||||
conn.Write([]byte(payload))
|
||||
|
||||
logging.Notice(session.ModuleName, "Connection established from", conn.RemoteAddr())
|
||||
|
||||
@@ -127,79 +138,68 @@ func handleRequest(conn net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
logging.Notice(session.ModuleName, "Connection lost")
|
||||
logging.Error(session.ModuleName, "Connection lost")
|
||||
return
|
||||
}
|
||||
|
||||
commands, err := common.ParseGameSpyMessage(string(buffer))
|
||||
if err != nil {
|
||||
logging.Notice(session.ModuleName, "Error parsing message:", err.Error())
|
||||
logging.Notice(session.ModuleName, "Raw data:", string(buffer))
|
||||
logging.Error(session.ModuleName, "Error parsing message:", err.Error())
|
||||
logging.Error(session.ModuleName, "Raw data:", string(buffer))
|
||||
return
|
||||
}
|
||||
|
||||
for _, command := range commands {
|
||||
logging.Notice(session.ModuleName, "Command:", aurora.Yellow(command.Command))
|
||||
// Commands must be handled in a certain order, not in the order supplied by the client
|
||||
|
||||
if command.Command == "login" {
|
||||
payload, _ := session.Login(pool, ctx, command, challenge)
|
||||
conn.Write([]byte(payload))
|
||||
}
|
||||
}
|
||||
commands = session.handleCommand("ka", commands, func(command common.GameSpyCommand) {
|
||||
session.Conn.Write([]byte(`\ka\\final\`))
|
||||
})
|
||||
commands = session.handleCommand("login", commands, session.login)
|
||||
commands = session.ignoreCommand("logout", commands)
|
||||
|
||||
if session.LoggedIn == false {
|
||||
logging.Notice(session.ModuleName, "Attempt to run command before login!")
|
||||
logging.Error(session.ModuleName, "Attempt to run command before login!")
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure commands that update the profile run before getprofile
|
||||
for _, command := range commands {
|
||||
switch command.Command {
|
||||
case "login":
|
||||
// User should already be authenticated
|
||||
break
|
||||
|
||||
case "logout":
|
||||
// Bye
|
||||
return
|
||||
|
||||
case "updatepro":
|
||||
session.updateProfile(pool, ctx, command)
|
||||
break
|
||||
|
||||
case "status":
|
||||
session.setStatus(pool, ctx, command)
|
||||
break
|
||||
|
||||
case "addbuddy":
|
||||
session.addFriend(pool, ctx, command)
|
||||
break
|
||||
|
||||
case "delbuddy":
|
||||
session.removeFriend(pool, ctx, command)
|
||||
break
|
||||
|
||||
case "bm":
|
||||
session.bestieMessage(pool, ctx, command)
|
||||
break
|
||||
|
||||
case "authadd":
|
||||
session.authAddFriend(pool, ctx, command)
|
||||
break
|
||||
}
|
||||
}
|
||||
commands = session.handleCommand("updatepro", commands, session.updateProfile)
|
||||
commands = session.handleCommand("status", commands, session.setStatus)
|
||||
commands = session.handleCommand("addbuddy", commands, session.addFriend)
|
||||
commands = session.handleCommand("delbuddy", commands, session.removeFriend)
|
||||
commands = session.handleCommand("authadd", commands, session.authAddFriend)
|
||||
commands = session.handleCommand("bm", commands, session.bestieMessage)
|
||||
commands = session.handleCommand("getprofile", commands, session.getProfile)
|
||||
|
||||
for _, command := range commands {
|
||||
switch command.Command {
|
||||
case "ka":
|
||||
conn.Write([]byte(`\ka\\final\`))
|
||||
break
|
||||
|
||||
case "getprofile":
|
||||
payload := session.getProfile(pool, ctx, command)
|
||||
conn.Write([]byte(payload))
|
||||
break
|
||||
}
|
||||
logging.Error(session.ModuleName, "Unknown command:", aurora.Cyan(command.Command))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameSpySession) handleCommand(name string, commands []common.GameSpyCommand, handler func(command common.GameSpyCommand)) []common.GameSpyCommand {
|
||||
unhandled := []common.GameSpyCommand{}
|
||||
|
||||
for _, command := range commands {
|
||||
if command.Command != name {
|
||||
unhandled = append(unhandled, command)
|
||||
continue
|
||||
}
|
||||
|
||||
logging.Notice(g.ModuleName, "Command:", aurora.Yellow(command.Command))
|
||||
handler(command)
|
||||
}
|
||||
|
||||
return unhandled
|
||||
}
|
||||
|
||||
func (g *GameSpySession) ignoreCommand(name string, commands []common.GameSpyCommand) []common.GameSpyCommand {
|
||||
unhandled := []common.GameSpyCommand{}
|
||||
|
||||
for _, command := range commands {
|
||||
if command.Command != name {
|
||||
unhandled = append(unhandled, command)
|
||||
}
|
||||
}
|
||||
|
||||
return unhandled
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package gpcm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"github.com/logrusorgru/aurora/v3"
|
||||
"strconv"
|
||||
"wwfc/common"
|
||||
@@ -10,11 +8,12 @@ import (
|
||||
"wwfc/logging"
|
||||
)
|
||||
|
||||
func (g *GameSpySession) getProfile(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) string {
|
||||
func (g *GameSpySession) getProfile(command common.GameSpyCommand) {
|
||||
strProfileId := command.OtherValues["profileid"]
|
||||
profileId, err := strconv.ParseUint(strProfileId, 10, 32)
|
||||
if err != nil {
|
||||
return createGameSpyError(2560)
|
||||
g.replyError(2560)
|
||||
return
|
||||
}
|
||||
|
||||
logging.Notice(g.ModuleName, "Looking up the profile of", aurora.Cyan(profileId).String())
|
||||
@@ -32,7 +31,7 @@ func (g *GameSpySession) getProfile(pool *pgxpool.Pool, ctx context.Context, com
|
||||
user, _ = database.GetProfile(pool, ctx, uint32(profileId))
|
||||
}
|
||||
|
||||
return common.CreateGameSpyMessage(common.GameSpyCommand{
|
||||
response := common.CreateGameSpyMessage(common.GameSpyCommand{
|
||||
Command: "pi",
|
||||
CommandValue: "",
|
||||
OtherValues: map[string]string{
|
||||
@@ -51,8 +50,10 @@ func (g *GameSpySession) getProfile(pool *pgxpool.Pool, ctx context.Context, com
|
||||
"id": command.OtherValues["id"],
|
||||
},
|
||||
})
|
||||
|
||||
g.Conn.Write([]byte(response))
|
||||
}
|
||||
|
||||
func (g *GameSpySession) updateProfile(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) {
|
||||
func (g *GameSpySession) updateProfile(command common.GameSpyCommand) {
|
||||
g.User = database.UpdateProfile(pool, ctx, g.User.ProfileId, command.OtherValues)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user