package serverCommunication import ( "context" "crypto/rand" "math/big" "time" "github.com/gofiber/websocket/v2" "go.mongodb.org/mongo-driver/bson" "krakatoa.net/backend/modules/cache" kraSettingsConfig "krakatoa.net/backend/modules/configs/kraSettingsConfig" "krakatoa.net/backend/modules/kraProtocol" "krakatoa.net/backend/modules/logger" "krakatoa.net/backend/modules/mongo" "krakatoa.net/backend/modules/structs" ) func HandleWebMessage(isVoice bool, conn *websocket.Conn, uuid string, status int, cmdID int, dest int, cmdNumber int, args string) { var err error var raw []byte webClient := getWebClientByConn(conn) if webClient == nil { // TODO: when does this apply? Send error with conn? return } if status == kraProtocol.StatusGet { var cmdIDInList bool logger.Web.Println("cmdID", isVoice, webClient.VoiceCmdIDs, webClient.MobileCmdIDs) if isVoice { cmdIDInList = isCmdIDInList(webClient.VoiceCmdIDs, cmdID) } else { cmdIDInList = isCmdIDInList(webClient.MobileCmdIDs, cmdID) } if cmdIDInList { // cmdID already in queue raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusMessageAlreadyInQueue, cmdID, cmdNumber, "") err = webClient.SendBinaryMessage(conn, raw) if err != nil { logger.WebVoice.Warnln("write:", err) } return } // add cmdID to list if isVoice { logger.Web.Debugln("voiceCmdIDs", webClient.VoiceCmdIDs) webClient.VoiceCmdIDs = append(webClient.VoiceCmdIDs, cmdID) logger.Web.Debugln("after voiceCmdIDs", webClient.VoiceCmdIDs) } else { logger.Web.Debugln("MobileCmdIDs", webClient.MobileCmdIDs) webClient.MobileCmdIDs = append(webClient.MobileCmdIDs, cmdID) logger.Web.Debugln("after MobileCmdIDs", webClient.MobileCmdIDs) } } logger.Minecraft.Debugln("dest", dest, dest == kraProtocol.DestProxy) if dest == kraProtocol.DestProxy || dest == kraProtocol.DestPlayersCurrentServer { // forwarding message to java / minecraft err = SendMessageToMinecraftServer(status, dest, uuid, cmdNumber, args) if err != nil { raw := kraProtocol.EncodeWebMessage(kraProtocol.StatusErrTryAgain, cmdID, cmdNumber, args) webClient.SendBinaryMessage(conn, raw) return } /* connForDest := getConnForDest(dest, uuid) raw = kraProtocol.EncodeJavaMessage(status, cmdID, dest, uuid, cmdNumber, args) err = client.SendBinaryMessage(connForDest, raw) if err != nil { logger.Web.Warnln("write:", err) } */ } else { // web if isVoice { // message from voice if dest == kraProtocol.DestMobile { // forwarding message to mobile connForDest := getConnForDest(dest, uuid) // get conn for mobile if connForDest != nil { // mobile is connected raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusReply, cmdID, cmdNumber, args) err = webClient.SendBinaryMessage(connForDest, raw) if err != nil { logger.WebVoice.Warnln("write:", err) } } else { // mobile not connected raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusSend, 58299, cmdNumber, "") err = webClient.SendBinaryMessage(conn, raw) if err != nil { logger.WebVoice.Warnln("write:", err) } } } else if dest == kraProtocol.DestBackend { resArgs := voiceCommandHandler(cmdNumber, uuid) if status == kraProtocol.StatusGet { logger.Web.Debugln("status get reply") raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusReply, cmdID, cmdNumber, resArgs) err = webClient.SendBinaryMessage(conn, raw) if err != nil { logger.WebVoice.Warnln("write:", err) } } } } else { // message from mobile if dest == kraProtocol.DestVoice { // forwarding message to voice connForDest := getConnForDest(dest, uuid) // get conn for voice if connForDest != nil { // voice connected raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusSend, cmdID, cmdNumber, args) err = webClient.SendBinaryMessage(connForDest, raw) if err != nil { logger.WebMobile.Warnln("write:", err) } } else { // voice not connected raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusSend, 5456, cmdNumber, "") err = webClient.SendBinaryMessage(conn, raw) if err != nil { logger.WebMobile.Warnln("write:", err) } } } else if dest == kraProtocol.DestBackend { resArgs := mobileCommandHandler(cmdNumber) if status == kraProtocol.StatusGet { raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusReply, cmdID, cmdNumber, resArgs) err = webClient.SendBinaryMessage(conn, raw) if err != nil { logger.WebVoice.Warnln("write:", err) } } } else { // err dest unknown raw = kraProtocol.EncodeWebMessage(kraProtocol.StatusErrTryAgain, cmdID, cmdNumber, "") err = webClient.SendBinaryMessage(conn, raw) if err != nil { logger.WebMobile.Warnln("write:", err) } } } } if webClient != nil { // remove cmdID from list if isVoice { webClient.RemoveVoiceCmdID(cmdID) } else { webClient.RemoveMobileCmdID(cmdID) } /*var newArr []int if isVoice { newArr, err = removeCmdIDFromList(client.VoiceCmdIDs, cmdID) if err != nil { logger.WebVoice.Warnln("removeCmdIDFromList:", err) } else { client.VoiceCmdIDs = newArr } } else { newArr, err = removeCmdIDFromList(client.MobileCmdIDs, cmdID) if err != nil { logger.WebMobile.Warnln("removeCmdIDFromList:", err) } else { client.MobileCmdIDs = newArr } } */ } } func voiceCommandHandler(cmdNumber int, uuid string) (args string) { switch cmdNumber { case 36006: // mobile web code logger.WebMobile.Println("case 36006", uuid) mobileWebCode, err := generateMobileWebCode() if err != nil { logger.WebVoice.Warnln("gen mobileWebCode", err) } filter := bson.D{{"uuid", uuid}} update := bson.D{{"$set", bson.D{{"mobileWebCode", mobileWebCode}}}} _, err = mongo.PlayersCollection.UpdateOne(context.TODO(), filter, update) if err != nil { logger.WebVoice.Println("updRes", err) } return mobileWebCode case 28450: // testing message to mobile time.Sleep(time.Second * 10) return "hello my friend" default: logger.WebVoice.Println("case default", cmdNumber) return "vdefault" } } func mobileCommandHandler(cmdNumber int) (args string) { switch cmdNumber { case 15857: // testing message from voice return "from voice" default: logger.WebMobile.Println("case default", cmdNumber) return "mdefault" } } func generateMobileWebCode() (string, error) { mobileWebCodeLetters := kraSettingsConfig.Cfg.VoiceWebCode.Letters mobileWebCodeLength := kraSettingsConfig.Cfg.VoiceWebCode.Length ret := make([]byte, mobileWebCodeLength) for i := 0; i < mobileWebCodeLength; i++ { num, err := rand.Int(rand.Reader, big.NewInt(int64(len(mobileWebCodeLetters)))) if err != nil { return "", err } ret[i] = mobileWebCodeLetters[num.Int64()] } return string(ret), nil } /* func IsMessageInAckQueue(conn *websocket.Conn, cmdID int) bool { for _, client := range cache.VoiceCmdIDs { if client.CmdID == cmdID && client.Conn == conn { return true } } return false } */ func getWebClientByConn(conn *websocket.Conn) *structs.WebClient { for _, client := range cache.WebClients { if client.VoiceConn == conn || client.MobileConn == conn { return client } } return nil } func GetWebClientByUuid(Uuid string) *structs.WebClient { logger.Web.Debugln("len clients", len(cache.WebClients)) // return client from clients list for uuid, client := range cache.WebClients { if uuid == Uuid { logger.Web.Debugln("return client", client.Uuid) return client } } // add to clients list client := &structs.WebClient{Uuid: Uuid} cache.WebClients[Uuid] = client logger.Web.Debugln("new client") return client } func IsVoiceAndMobileSocketConnected(uuid string) string { client := GetWebClientByUuid(uuid) if client.MobileConn == nil && client.VoiceConn == nil { return "0" } else { return "1" } } func isCmdIDInList(arr []int, cmdID int) bool { for i := 0; i < len(arr); i++ { if arr[i] == cmdID { return true } } return false }