From 7b54d5fa1d274c5466e4574e32b8e5005240d4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Mon, 5 Jun 2023 20:44:31 +0100 Subject: [PATCH 1/9] Remove handlers on Secure Connection Since we now store the client station URLs on nex.Client, there's no need for external handlers to do so, so remove them. Also, the handlers were deprecated as they didn't do anything anyway. --- secure-connection/protocol.go | 25 ------------------------- secure-connection/register.go | 16 ---------------- secure-connection/replace_url.go | 4 ---- secure-connection/send_report.go | 5 ++--- 4 files changed, 2 insertions(+), 48 deletions(-) diff --git a/secure-connection/protocol.go b/secure-connection/protocol.go index fdec666..78228ca 100644 --- a/secure-connection/protocol.go +++ b/secure-connection/protocol.go @@ -12,31 +12,6 @@ var logger = plogger.NewLogger() type CommonSecureConnectionProtocol struct { *secure_connection.SecureConnectionProtocol server *nex.Server - - addConnectionHandler func(rvcid uint32, urls []string, ip string, port string) - updateConnectionHandler func(rvcid uint32, urls []string, ip string, port string) - doesConnectionExistHandler func(rvcid uint32) bool - replaceConnectionUrlHandler func(rvcid uint32, oldurl string, newurl string) -} - -// AddConnection sets the AddConnection handler function -func (commonSecureConnectionProtocol *CommonSecureConnectionProtocol) AddConnection(handler func(rvcid uint32, urls []string, ip string, port string)) { - commonSecureConnectionProtocol.addConnectionHandler = handler -} - -// UpdateConnection sets the UpdateConnection handler function -func (commonSecureConnectionProtocol *CommonSecureConnectionProtocol) UpdateConnection(handler func(rvcid uint32, urls []string, ip string, port string)) { - commonSecureConnectionProtocol.updateConnectionHandler = handler -} - -// ReplaceConnectionUrl sets the ReplaceConnectionUrl handler function -func (commonSecureConnectionProtocol *CommonSecureConnectionProtocol) ReplaceConnectionUrl(handler func(rvcid uint32, oldurl string, newurl string)) { - commonSecureConnectionProtocol.replaceConnectionUrlHandler = handler -} - -// DoesConnectionExist sets the DoesConnectionExist handler function -func (commonSecureConnectionProtocol *CommonSecureConnectionProtocol) DoesConnectionExist(handler func(rvcid uint32) bool) { - commonSecureConnectionProtocol.doesConnectionExistHandler = handler } // NewCommonSecureConnectionProtocol returns a new CommonSecureConnectionProtocol diff --git a/secure-connection/register.go b/secure-connection/register.go index 5886145..a3aa18c 100644 --- a/secure-connection/register.go +++ b/secure-connection/register.go @@ -9,22 +9,6 @@ import ( func register(err error, client *nex.Client, callID uint32, stationUrls []*nex.StationURL) { server := commonSecureConnectionProtocol.server - missingHandler := false - if commonSecureConnectionProtocol.addConnectionHandler == nil { - logger.Warning("Missing AddConnectionHandler!") - missingHandler = true - } - if commonSecureConnectionProtocol.updateConnectionHandler == nil { - logger.Warning("Missing UpdateConnectionHandler!") - missingHandler = true - } - if commonSecureConnectionProtocol.doesConnectionExistHandler == nil { - logger.Warning("Missing DoesConnectionExistHandler!") - missingHandler = true - } - if missingHandler { - return - } localStation := stationUrls[0] localStationURL := localStation.EncodeToString() pidConnectionID := uint32(server.ConnectionIDCounter().Increment()) diff --git a/secure-connection/replace_url.go b/secure-connection/replace_url.go index edd254b..13406e0 100644 --- a/secure-connection/replace_url.go +++ b/secure-connection/replace_url.go @@ -7,10 +7,6 @@ import ( func replaceURL(err error, client *nex.Client, callID uint32, oldStation *nex.StationURL, newStation *nex.StationURL) { server := commonSecureConnectionProtocol.server - if commonSecureConnectionProtocol.replaceConnectionUrlHandler == nil { - logger.Warning("Missing ReplaceConnectionUrlHandler!") - return - } urls := client.StationURLs() diff --git a/secure-connection/send_report.go b/secure-connection/send_report.go index e4ca864..8f9af3e 100644 --- a/secure-connection/send_report.go +++ b/secure-connection/send_report.go @@ -2,7 +2,6 @@ package secureconnection import ( "encoding/hex" - "fmt" "strconv" nex "github.com/PretendoNetwork/nex-go" @@ -10,8 +9,8 @@ import ( ) func sendReport(err error, client *nex.Client, callID uint32, reportID uint32, reportData []byte) { - fmt.Println("Report ID: " + strconv.Itoa(int(reportID))) - fmt.Println("Report Data: " + hex.EncodeToString(reportData)) + logger.Info("Report ID: " + strconv.Itoa(int(reportID))) + logger.Info("Report Data: " + hex.EncodeToString(reportData)) rmcResponse := nex.NewRMCResponse(secure_connection.ProtocolID, callID) rmcResponse.SetSuccess(secure_connection.MethodSendReport, nil) From 2e3bc892e88e78529916c7b75691e17bacb87186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Mon, 5 Jun 2023 20:46:52 +0100 Subject: [PATCH 2/9] Use common struct on NAT Traversal Also remove external handlers, as we now store the client station URLs on nex.Client. And implement ReportNATTraversalResult. --- nat-traversal/protocol.go | 34 ++++++--------- nat-traversal/report_nat_properties.go | 38 ++++++----------- nat-traversal/report_nat_traversal_result.go | 42 +++++++++---------- nat-traversal/request_probe_initiation_ext.go | 16 +++---- 4 files changed, 55 insertions(+), 75 deletions(-) diff --git a/nat-traversal/protocol.go b/nat-traversal/protocol.go index 71fbda5..49e3a9b 100644 --- a/nat-traversal/protocol.go +++ b/nat-traversal/protocol.go @@ -6,31 +6,21 @@ import ( "github.com/PretendoNetwork/plogger-go" ) -var ( - server *nex.Server - GetConnectionUrlsHandler func(rvcid uint32) []string - ReplaceConnectionUrlHandler func(rvcid uint32, oldurl string, newurl string) -) - +var commonNATTraversalProtocol *CommonNATTraversalProtocol var logger = plogger.NewLogger() -// GetConnectionUrls sets the GetConnectionUrls handler function -func GetConnectionUrls(handler func(rvcid uint32) []string) { - GetConnectionUrlsHandler = handler -} - -// ReplaceConnectionUrl sets the ReplaceConnectionUrl handler function -func ReplaceConnectionUrl(handler func(rvcid uint32, oldurl string, newurl string)) { - ReplaceConnectionUrlHandler = handler +type CommonNATTraversalProtocol struct { + *nat_traversal.NATTraversalProtocol + server *nex.Server } -// InitNatTraversalProtocol returns a new NatTraversalProtocol -func InitNatTraversalProtocol(nexServer *nex.Server) *nat_traversal.NATTraversalProtocol { - server = nexServer - natTraversalProtocolServer := nat_traversal.NewNATTraversalProtocol(nexServer) +// NewCommonNATTraversalProtocol returns a new CommonNATTraversalProtocol +func NewCommonNATTraversalProtocol(server *nex.Server) *CommonNATTraversalProtocol { + natTraversalProtocol := nat_traversal.NewNATTraversalProtocol(server) + commonNATTraversalProtocol = &CommonNATTraversalProtocol{NATTraversalProtocol: natTraversalProtocol, server: server} - natTraversalProtocolServer.RequestProbeInitiationExt(requestProbeInitiationExt) - natTraversalProtocolServer.ReportNATProperties(reportNatProperties) - //natTraversalProtocolServer.ReportNATTraversalResult(reportNATTraversalResult) // not implemented in nex-protocols-go yet - return natTraversalProtocolServer + commonNATTraversalProtocol.RequestProbeInitiationExt(requestProbeInitiationExt) + commonNATTraversalProtocol.ReportNATProperties(reportNATProperties) + commonNATTraversalProtocol.ReportNATTraversalResult(reportNATTraversalResult) + return commonNATTraversalProtocol } diff --git a/nat-traversal/report_nat_properties.go b/nat-traversal/report_nat_properties.go index f12242c..0d9d1aa 100644 --- a/nat-traversal/report_nat_properties.go +++ b/nat-traversal/report_nat_properties.go @@ -7,37 +7,25 @@ import ( nat_traversal "github.com/PretendoNetwork/nex-protocols-go/nat-traversal" ) -func reportNatProperties(err error, client *nex.Client, callID uint32, natm uint32, natf uint32, rtt uint32) { - missingHandler := false - if GetConnectionUrlsHandler == nil { - logger.Warning("Missing GetConnectionUrlsHandler!") - missingHandler = true - } - if ReplaceConnectionUrlHandler == nil { - logger.Warning("Missing ReplaceConnectionUrlHandler!") - missingHandler = true - } - if missingHandler { - return - } - stationUrlsStrings := GetConnectionUrlsHandler(client.ConnectionID()) - stationUrls := make([]nex.StationURL, len(stationUrlsStrings)) - pid := strconv.FormatUint(uint64(client.PID()), 10) - rvcid := strconv.FormatUint(uint64(client.ConnectionID()), 10) +func reportNATProperties(err error, client *nex.Client, callID uint32, natm uint32, natf uint32, rtt uint32) { + server := commonNATTraversalProtocol.server - for i := 0; i < len(stationUrlsStrings); i++ { - stationUrls[i] = *nex.NewStationURL(stationUrlsStrings[i]) - if stationUrls[i].Type() == "3" { + stationURLsStrings := client.StationURLs() + stationURLs := make([]*nex.StationURL, len(stationURLsStrings)) + + for i := 0; i < len(stationURLsStrings); i++ { + stationURLs[i] = nex.NewStationURL(stationURLsStrings[i]) + if stationURLs[i].Type() == "3" { natm_s := strconv.FormatUint(uint64(natm), 10) natf_s := strconv.FormatUint(uint64(natf), 10) - stationUrls[i].SetNatm(natm_s) - stationUrls[i].SetNatf(natf_s) + stationURLs[i].SetNatm(natm_s) + stationURLs[i].SetNatf(natf_s) } - stationUrls[i].SetPID(pid) - stationUrls[i].SetRVCID(rvcid) - ReplaceConnectionUrlHandler(client.ConnectionID(), stationUrlsStrings[i], stationUrls[i].EncodeToString()) + stationURLsStrings[i] = stationURLs[i].EncodeToString() } + client.SetStationURLs(stationURLsStrings) + rmcResponse := nex.NewRMCResponse(nat_traversal.ProtocolID, callID) rmcResponse.SetSuccess(nat_traversal.MethodReportNATProperties, nil) diff --git a/nat-traversal/report_nat_traversal_result.go b/nat-traversal/report_nat_traversal_result.go index f9fab0f..1276e3a 100644 --- a/nat-traversal/report_nat_traversal_result.go +++ b/nat-traversal/report_nat_traversal_result.go @@ -2,35 +2,35 @@ package nattraversal import ( nex "github.com/PretendoNetwork/nex-go" + nat_traversal "github.com/PretendoNetwork/nex-protocols-go/nat-traversal" ) func reportNATTraversalResult(err error, client *nex.Client, callID uint32, cid uint32, result bool, rtt uint32) { - // MethodReportNATTraversalResult does not exist yet in nex-protocols-go - /* - rmcResponse := nex.NewRMCResponse(nexproto.ProtocolID, callID) - rmcResponse.SetSuccess(nexproto.MethodReportNATTraversalResult, nil) + server := commonNATTraversalProtocol.server - rmcResponseBytes := rmcResponse.Bytes() + rmcResponse := nex.NewRMCResponse(nat_traversal.ProtocolID, callID) + rmcResponse.SetSuccess(nat_traversal.MethodReportNATTraversalResult, nil) - var responsePacket nex.PacketInterface + rmcResponseBytes := rmcResponse.Bytes() - if server.PRUDPVersion() == 0 { - responsePacket, _ = nex.NewPacketV0(client, nil) - responsePacket.SetVersion(0) - } else { - responsePacket, _ = nex.NewPacketV1(client, nil) - responsePacket.SetVersion(1) - } + var responsePacket nex.PacketInterface + if server.PRUDPVersion() == 0 { + responsePacket, _ = nex.NewPacketV0(client, nil) + responsePacket.SetVersion(0) + } else { + responsePacket, _ = nex.NewPacketV1(client, nil) responsePacket.SetVersion(1) - responsePacket.SetSource(0xA1) - responsePacket.SetDestination(0xAF) - responsePacket.SetType(nex.DataPacket) - responsePacket.SetPayload(rmcResponseBytes) + } - responsePacket.AddFlag(nex.FlagNeedsAck) - responsePacket.AddFlag(nex.FlagReliable) + responsePacket.SetVersion(1) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) - server.Send(responsePacket) - */ + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + server.Send(responsePacket) } diff --git a/nat-traversal/request_probe_initiation_ext.go b/nat-traversal/request_probe_initiation_ext.go index 23cce13..8609ade 100644 --- a/nat-traversal/request_probe_initiation_ext.go +++ b/nat-traversal/request_probe_initiation_ext.go @@ -1,7 +1,6 @@ package nattraversal import ( - "fmt" "strconv" nex "github.com/PretendoNetwork/nex-go" @@ -9,6 +8,7 @@ import ( ) func requestProbeInitiationExt(err error, client *nex.Client, callID uint32, targetList []string, stationToProbe string) { + server := commonNATTraversalProtocol.server rmcResponse := nex.NewRMCResponse(nat_traversal.ProtocolID, callID) rmcResponse.SetSuccess(nat_traversal.MethodRequestProbeInitiationExt, nil) @@ -34,22 +34,24 @@ func requestProbeInitiationExt(err error, client *nex.Client, callID uint32, tar server.Send(responsePacket) - rmcMessage := nex.RMCRequest{} + rmcMessage := nex.NewRMCRequest() rmcMessage.SetProtocolID(nat_traversal.ProtocolID) rmcMessage.SetCallID(0xffff0000 + callID) rmcMessage.SetMethodID(nat_traversal.MethodInitiateProbe) + rmcRequestStream := nex.NewStreamOut(server) rmcRequestStream.WriteString(stationToProbe) rmcRequestBody := rmcRequestStream.Bytes() + rmcMessage.SetParameters(rmcRequestBody) rmcMessageBytes := rmcMessage.Bytes() for _, target := range targetList { targetUrl := nex.NewStationURL(target) - fmt.Println("target: " + target) - fmt.Println("toProbe: " + stationToProbe) - targetRvcID, _ := strconv.Atoi(targetUrl.RVCID()) - targetClient := server.FindClientFromConnectionID(uint32(targetRvcID)) + logger.Info("Target: " + target) + logger.Info("ToProbe: " + stationToProbe) + targetRVCID, _ := strconv.Atoi(targetUrl.RVCID()) + targetClient := server.FindClientFromConnectionID(uint32(targetRVCID)) if targetClient != nil { var messagePacket nex.PacketInterface @@ -71,7 +73,7 @@ func requestProbeInitiationExt(err error, client *nex.Client, callID uint32, tar server.Send(messagePacket) } else { - fmt.Println("not found") + logger.Warning("Client not found") } } } From 3e7d634b71e6c17613715e40746ad23ab53bca17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Mon, 5 Jun 2023 20:51:02 +0100 Subject: [PATCH 3/9] Various changes to Matchmaking - Use structure.Copy() and structure.Equal() now that they are implemented. - Add notification types that weren't used before. - Remove handlers for MatchMaking(-Ext) and use global sessions for handling rooms. - And possibly more --- globals/matchmaking_globals.go | 7 +-- .../auto_matchmake_postpone.go | 24 ++++---- matchmake-extension/protocol.go | 4 +- matchmaking-ext/end_participation.go | 48 ++++++++++++++++ matchmaking/get_session_urls.go | 18 +----- matchmaking/protocol.go | 33 +---------- matchmaking/unregister_gathering.go | 56 ++++++++++++++++--- matchmaking/update_session_host.go | 49 +++++----------- matchmaking/update_session_host_v1.go | 11 +--- 9 files changed, 134 insertions(+), 116 deletions(-) diff --git a/globals/matchmaking_globals.go b/globals/matchmaking_globals.go index 0db4e72..973748a 100644 --- a/globals/matchmaking_globals.go +++ b/globals/matchmaking_globals.go @@ -2,7 +2,6 @@ package common_globals import ( match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" "math" - "reflect" ) type CommonMatchmakeSession struct { @@ -25,7 +24,7 @@ func RemoveConnectionIDFromRoom(clientConnectionID uint32, gathering uint32) { } } if len(Sessions[gathering].ConnectionIDs) == 0 { - delete(Sessions, gathering) + delete(Sessions, gathering) } } @@ -52,7 +51,7 @@ func FindSearchMatchmakeSession(searchMatchmakeSession match_making.MatchmakeSes //this portion finds any sessions that match the search session. It does not care about anything beyond that, such as if the match is already full. This is handled below. candidateSessionIndexes := make([]uint32, 0, len(Sessions)) for index, session := range Sessions { - if reflect.DeepEqual(session.SearchMatchmakeSession, searchMatchmakeSession) { // TODO - for Jon: Equals in StructureInterface + if session.SearchMatchmakeSession.Equals(&searchMatchmakeSession) { candidateSessionIndexes = append(candidateSessionIndexes, index) } } @@ -66,4 +65,4 @@ func FindSearchMatchmakeSession(searchMatchmakeSession match_making.MatchmakeSes } } return returnSessionIndex -} \ No newline at end of file +} diff --git a/matchmake-extension/auto_matchmake_postpone.go b/matchmake-extension/auto_matchmake_postpone.go index ef62a3b..df1d6ba 100644 --- a/matchmake-extension/auto_matchmake_postpone.go +++ b/matchmake-extension/auto_matchmake_postpone.go @@ -8,21 +8,17 @@ import ( matchmake_extension "github.com/PretendoNetwork/nex-protocols-go/matchmake-extension" "github.com/PretendoNetwork/nex-protocols-go/notifications" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" - "encoding/json" ) func AutoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchmakeSession *match_making.MatchmakeSession, message string) { server := commonMatchmakeExtensionProtocol.server - if commonMatchmakeExtensionProtocol.CleanupSearchMatchmakeSessionHandler == nil { + if commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler == nil { logger.Warning("MatchmakeExtension::AutoMatchmake_Postpone missing CleanupSearchMatchmakeSessionHandler!") return } - //This is the best way I found to copy the full object. And I still hate it. - // TODO - for Jon: Copy in MatchmakeSession (and anything else that needs it) - tmp, _ := json.Marshal(matchmakeSession) - matchmakeSessionCopy := match_making.NewMatchmakeSession() - json.Unmarshal(tmp, &matchmakeSessionCopy) - searchMatchmakeSession := commonMatchmakeExtensionProtocol.CleanupSearchMatchmakeSessionHandler(*matchmakeSessionCopy) + + matchmakeSessionCopy := matchmakeSession.Copy().(*match_making.MatchmakeSession) + searchMatchmakeSession := commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler(*matchmakeSessionCopy) sessionIndex := uint32(common_globals.FindSearchMatchmakeSession(searchMatchmakeSession)) if sessionIndex == math.MaxUint32 { session := common_globals.CommonMatchmakeSession{ @@ -34,10 +30,16 @@ func AutoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchm common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.ID = uint32(sessionIndex) common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.OwnerPID = client.PID() common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.HostPID = client.PID() + + currentTime := nex.NewDateTime(0) + currentTime = nex.NewDateTime(currentTime.UTC()) + common_globals.Sessions[sessionIndex].GameMatchmakeSession.StartedTime = currentTime + common_globals.CurrentGatheringID++ } common_globals.Sessions[sessionIndex].ConnectionIDs = append(common_globals.Sessions[sessionIndex].ConnectionIDs, client.ConnectionID()) + common_globals.Sessions[sessionIndex].GameMatchmakeSession.ParticipationCount = uint32(len(common_globals.Sessions[sessionIndex].ConnectionIDs)) rmcResponseStream := nex.NewStreamOut(server) matchmakeDataHolder := nex.NewDataHolder() @@ -78,17 +80,17 @@ func AutoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchm oEvent := notifications.NewNotificationEvent() oEvent.PIDSource = common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.HostPID - // TODO - for Jon: notifications type to make this simpler - oEvent.Type = 3001 // New participant + oEvent.Type = notifications.NotificationTypes.NewParticipant oEvent.Param1 = uint32(sessionIndex) oEvent.Param2 = client.PID() + oEvent.StrParam = message stream := nex.NewStreamOut(server) oEventBytes := oEvent.Bytes(stream) rmcMessage.SetParameters(oEventBytes) rmcMessageBytes := rmcMessage.Bytes() - targetClient := server.FindClientFromPID(uint32(common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.HostPID)) + targetClient := server.FindClientFromPID(uint32(common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.OwnerPID)) var messagePacket nex.PacketInterface diff --git a/matchmake-extension/protocol.go b/matchmake-extension/protocol.go index 72acb06..b47a521 100644 --- a/matchmake-extension/protocol.go +++ b/matchmake-extension/protocol.go @@ -14,12 +14,12 @@ type CommonMatchmakeExtensionProtocol struct { *matchmake_extension.MatchmakeExtensionProtocol server *nex.Server - CleanupSearchMatchmakeSessionHandler func(matchmakeSession match_making.MatchmakeSession) match_making.MatchmakeSession + cleanupSearchMatchmakeSessionHandler func(matchmakeSession match_making.MatchmakeSession) match_making.MatchmakeSession } // CleanupSearchMatchmakeSession sets the CleanupSearchMatchmakeSession handler function func (commonMatchmakeExtensionProtocol *CommonMatchmakeExtensionProtocol) CleanupSearchMatchmakeSession(handler func(matchmakeSession match_making.MatchmakeSession) match_making.MatchmakeSession) { - commonMatchmakeExtensionProtocol.CleanupSearchMatchmakeSessionHandler = handler + commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler = handler } // NewCommonMatchmakeExtensionProtocol returns a new CommonMatchmakeExtensionProtocol diff --git a/matchmaking-ext/end_participation.go b/matchmaking-ext/end_participation.go index ada5eae..27cc683 100644 --- a/matchmaking-ext/end_participation.go +++ b/matchmaking-ext/end_participation.go @@ -4,10 +4,19 @@ import ( nex "github.com/PretendoNetwork/nex-go" match_making_ext "github.com/PretendoNetwork/nex-protocols-go/match-making-ext" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" + "github.com/PretendoNetwork/nex-protocols-go/notifications" ) func EndParticipation(err error, client *nex.Client, callID uint32, idGathering uint32, strMessage string) { server := commonMatchMakingExtProtocol.server + matchmakeSession := common_globals.Sessions[idGathering].GameMatchmakeSession + ownerPID := matchmakeSession.Gathering.OwnerPID + if client.PID() == matchmakeSession.Gathering.OwnerPID { + if matchmakeSession.Gathering.Flags & 0x10 == 0 { + delete(common_globals.Sessions, idGathering) + } + } + common_globals.RemoveConnectionIDFromRoom(client.ConnectionID(), idGathering) rmcResponseStream := nex.NewStreamOut(server) @@ -40,4 +49,43 @@ func EndParticipation(err error, client *nex.Client, callID uint32, idGathering responsePacket.AddFlag(nex.FlagReliable) server.Send(responsePacket) + + rmcMessage := nex.NewRMCRequest() + rmcMessage.SetProtocolID(notifications.ProtocolID) + rmcMessage.SetCallID(0xffff0000 + callID) + rmcMessage.SetMethodID(notifications.MethodProcessNotificationEvent) + + oEvent := notifications.NewNotificationEvent() + oEvent.PIDSource = client.PID() + oEvent.Type = notifications.NotificationTypes.ParticipationEnded + oEvent.Param1 = idGathering + oEvent.Param2 = client.PID() + oEvent.StrParam = strMessage + + stream := nex.NewStreamOut(server) + oEventBytes := oEvent.Bytes(stream) + rmcMessage.SetParameters(oEventBytes) + + rmcMessageBytes := rmcMessage.Bytes() + + targetClient := server.FindClientFromPID(uint32(ownerPID)) + + var messagePacket nex.PacketInterface + + if server.PRUDPVersion() == 0 { + messagePacket, _ = nex.NewPacketV0(targetClient, nil) + messagePacket.SetVersion(0) + } else { + messagePacket, _ = nex.NewPacketV1(targetClient, nil) + messagePacket.SetVersion(1) + } + messagePacket.SetSource(0xA1) + messagePacket.SetDestination(0xAF) + messagePacket.SetType(nex.DataPacket) + messagePacket.SetPayload(rmcMessageBytes) + + messagePacket.AddFlag(nex.FlagNeedsAck) + messagePacket.AddFlag(nex.FlagReliable) + + server.Send(messagePacket) } diff --git a/matchmaking/get_session_urls.go b/matchmaking/get_session_urls.go index e311e43..d4389d7 100644 --- a/matchmaking/get_session_urls.go +++ b/matchmaking/get_session_urls.go @@ -4,32 +4,20 @@ import ( nex "github.com/PretendoNetwork/nex-go" match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" - "fmt" ) func getSessionURLs(err error, client *nex.Client, callID uint32, gatheringId uint32) { server := commonMatchMakingProtocol.server - missingHandler := false - if commonMatchMakingProtocol.GetConnectionUrlsHandler == nil { - logger.Warning("MatchMaking::GetSessionURLs missing GetConnectionUrlsHandler!") - missingHandler = true - } - if commonMatchMakingProtocol.GetRoomInfoHandler == nil { - logger.Warning("MatchMaking::GetSessionURLs missing GetRoomInfoHandler!") - missingHandler = true - } - if missingHandler { - return - } var stationUrlStrings []string hostpid := common_globals.Sessions[gatheringId].GameMatchmakeSession.Gathering.HostPID hostclient := server.FindClientFromPID(hostpid) - if(hostclient == nil){ - fmt.Println("nil hostclient?!") //this popped up once during testing. Leaving it noted here in case it becomes a problem. + if hostclient == nil { + logger.Warning("Host client not found") //this popped up once during testing. Leaving it noted here in case it becomes a problem. return } + stationUrlStrings = hostclient.StationURLs() rmcResponseStream := nex.NewStreamOut(server) diff --git a/matchmaking/protocol.go b/matchmaking/protocol.go index 50edb57..8d7ee8a 100644 --- a/matchmaking/protocol.go +++ b/matchmaking/protocol.go @@ -14,37 +14,6 @@ var logger = plogger.NewLogger() type CommonMatchMakingProtocol struct { *match_making.MatchMakingProtocol server *nex.Server - - GetConnectionUrlsHandler func(rvcid uint32) []string - UpdateRoomHostHandler func(gid uint32, newownerpid uint32) - DestroyRoomHandler func(gid uint32) - GetRoomInfoHandler func(gid uint32) (uint32, uint32, uint32, uint32, uint32) - GetRoomPlayersHandler func(gid uint32) []uint32 -} - -// GetConnectionUrls sets the GetConnectionUrls handler function -func (commonMatchMakingProtocol *CommonMatchMakingProtocol) GetConnectionUrls(handler func(rvcid uint32) []string) { - commonMatchMakingProtocol.GetConnectionUrlsHandler = handler -} - -// UpdateRoomHost sets the UpdateRoomHost handler function -func (commonMatchMakingProtocol *CommonMatchMakingProtocol) UpdateRoomHost(handler func(gid uint32, newownerpid uint32)) { - commonMatchMakingProtocol.UpdateRoomHostHandler = handler -} - -// DestroyRoom sets the DestroyRoom handler function -func (commonMatchMakingProtocol *CommonMatchMakingProtocol) DestroyRoom(handler func(gid uint32)) { - commonMatchMakingProtocol.DestroyRoomHandler = handler -} - -// GetRoomInfo sets the GetRoomInfo handler function -func (commonMatchMakingProtocol *CommonMatchMakingProtocol) GetRoomInfo(handler func(gid uint32) (uint32, uint32, uint32, uint32, uint32)) { - commonMatchMakingProtocol.GetRoomInfoHandler = handler -} - -// GetRoomPlayers sets the GetRoomPlayers handler function -func (commonMatchMakingProtocol *CommonMatchMakingProtocol) GetRoomPlayers(handler func(gid uint32) []uint32) { - commonMatchMakingProtocol.GetRoomPlayersHandler = handler } // NewCommonMatchMakingProtocol returns a new CommonMatchMakingProtocol @@ -52,7 +21,7 @@ func NewCommonMatchMakingProtocol(server *nex.Server) *CommonMatchMakingProtocol matchMakingProtocol := match_making.NewMatchMakingProtocol(server) commonMatchMakingProtocol = &CommonMatchMakingProtocol{MatchMakingProtocol: matchMakingProtocol, server: server} - common_globals.Sessions = make(map[uint32]*common_globals.CommonMatchmakeSession) + common_globals.Sessions = make(map[uint32]*common_globals.CommonMatchmakeSession) commonMatchMakingProtocol.GetSessionURLs(getSessionURLs) commonMatchMakingProtocol.UnregisterGathering(unregisterGathering) diff --git a/matchmaking/unregister_gathering.go b/matchmaking/unregister_gathering.go index ebf26ee..db2cb72 100644 --- a/matchmaking/unregister_gathering.go +++ b/matchmaking/unregister_gathering.go @@ -3,19 +3,14 @@ package matchmaking import ( nex "github.com/PretendoNetwork/nex-go" match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" + "github.com/PretendoNetwork/nex-protocols-go/notifications" + common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" ) func unregisterGathering(err error, client *nex.Client, callID uint32, gatheringId uint32) { server := commonMatchMakingProtocol.server - missingHandler := false - if commonMatchMakingProtocol.DestroyRoomHandler == nil { - logger.Warning("MatchMaking::UnregisterGathering missing DestroyRoomHandler!") - missingHandler = true - } - if missingHandler { - return - } - commonMatchMakingProtocol.DestroyRoomHandler(gatheringId) + gatheringPlayers := common_globals.Sessions[gatheringId].ConnectionIDs + delete(common_globals.Sessions, gatheringId) rmcResponse := nex.NewRMCResponse(match_making.ProtocolID, callID) rmcResponse.SetSuccess(match_making.MethodUnregisterGathering, nil) @@ -40,4 +35,47 @@ func unregisterGathering(err error, client *nex.Client, callID uint32, gathering responsePacket.AddFlag(nex.FlagReliable) server.Send(responsePacket) + + rmcMessage := nex.NewRMCRequest() + rmcMessage.SetProtocolID(notifications.ProtocolID) + rmcMessage.SetCallID(0xffff0000 + callID) + rmcMessage.SetMethodID(notifications.MethodProcessNotificationEvent) + + oEvent := notifications.NewNotificationEvent() + oEvent.PIDSource = client.PID() + oEvent.Type = notifications.NotificationTypes.GatheringUnregistered + oEvent.Param1 = gatheringId + + stream := nex.NewStreamOut(server) + oEventBytes := oEvent.Bytes(stream) + rmcMessage.SetParameters(oEventBytes) + + rmcRequestBytes := rmcMessage.Bytes() + + for _, connectionID := range gatheringPlayers { + targetClient := server.FindClientFromConnectionID(connectionID) + if targetClient != nil { + var messagePacket nex.PacketInterface + + if server.PRUDPVersion() == 0 { + messagePacket, _ = nex.NewPacketV0(targetClient, nil) + messagePacket.SetVersion(0) + } else { + messagePacket, _ = nex.NewPacketV1(targetClient, nil) + messagePacket.SetVersion(1) + } + + messagePacket.SetSource(0xA1) + messagePacket.SetDestination(0xAF) + messagePacket.SetType(nex.DataPacket) + messagePacket.SetPayload(rmcRequestBytes) + + messagePacket.AddFlag(nex.FlagNeedsAck) + messagePacket.AddFlag(nex.FlagReliable) + + server.Send(messagePacket) + } else { + logger.Warning("Client not found") + } + } } diff --git a/matchmaking/update_session_host.go b/matchmaking/update_session_host.go index 99b0b57..03a72c6 100644 --- a/matchmaking/update_session_host.go +++ b/matchmaking/update_session_host.go @@ -1,25 +1,18 @@ package matchmaking import ( - "strconv" - "time" - nex "github.com/PretendoNetwork/nex-go" match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" "github.com/PretendoNetwork/nex-protocols-go/notifications" + common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" ) -func updateSessionHost(err error, client *nex.Client, callID uint32, gid uint32) { +func updateSessionHost(err error, client *nex.Client, callID uint32, gid uint32, isMigrateOwner bool) { server := commonMatchMakingProtocol.server - missingHandler := false - if commonMatchMakingProtocol.UpdateRoomHostHandler == nil { - logger.Warning("MatchMaking::UpdateSessionHostV1 missing UpdateRoomHostHandler!") - missingHandler = true - } - if missingHandler { - return + common_globals.Sessions[gid].GameMatchmakeSession.Gathering.HostPID = client.PID() + if isMigrateOwner { + common_globals.Sessions[gid].GameMatchmakeSession.Gathering.OwnerPID = client.PID() } - commonMatchMakingProtocol.UpdateRoomHostHandler(gid, client.PID()) rmcResponse := nex.NewRMCResponse(match_making.ProtocolID, callID) rmcResponse.SetSuccess(match_making.MethodUpdateSessionHost, nil) @@ -46,6 +39,10 @@ func updateSessionHost(err error, client *nex.Client, callID uint32, gid uint32) server.Send(responsePacket) + if !isMigrateOwner { + return + } + rmcMessage := nex.NewRMCRequest() rmcMessage.SetProtocolID(notifications.ProtocolID) rmcMessage.SetCallID(0xffff0000 + callID) @@ -53,13 +50,14 @@ func updateSessionHost(err error, client *nex.Client, callID uint32, gid uint32) oEvent := notifications.NewNotificationEvent() oEvent.PIDSource = client.PID() - oEvent.Type = 4000 // Ownership changed + oEvent.Type = notifications.NotificationTypes.OwnershipChanged oEvent.Param1 = gid oEvent.Param2 = client.PID() + // TODO - This doesn't seem to appear on all servers // https://github.com/kinnay/NintendoClients/issues/101 - unixTime := time.Now() - oEvent.StrParam = strconv.FormatInt(unixTime.UnixMicro(), 10) + // unixTime := time.Now() + // oEvent.StrParam = strconv.FormatInt(unixTime.UnixMicro(), 10) stream := nex.NewStreamOut(server) oEventBytes := oEvent.Bytes(stream) @@ -67,14 +65,9 @@ func updateSessionHost(err error, client *nex.Client, callID uint32, gid uint32) rmcRequestBytes := rmcMessage.Bytes() - for _, pid := range commonMatchMakingProtocol.GetRoomPlayersHandler(gid) { - if pid == 0 { - continue - } - - targetClient := server.FindClientFromPID(uint32(pid)) + for _, connectionID := range common_globals.Sessions[gid].ConnectionIDs { + targetClient := server.FindClientFromConnectionID(connectionID) if targetClient != nil { - var messagePacket nex.PacketInterface if server.PRUDPVersion() == 0 { @@ -98,16 +91,4 @@ func updateSessionHost(err error, client *nex.Client, callID uint32, gid uint32) logger.Warning("Client not found") } } - - messagePacket, _ := nex.NewPacketV0(client, nil) - messagePacket.SetVersion(1) - messagePacket.SetSource(0xA1) - messagePacket.SetDestination(0xAF) - messagePacket.SetType(nex.DataPacket) - messagePacket.SetPayload(rmcRequestBytes) - - messagePacket.AddFlag(nex.FlagNeedsAck) - messagePacket.AddFlag(nex.FlagReliable) - - server.Send(messagePacket) } diff --git a/matchmaking/update_session_host_v1.go b/matchmaking/update_session_host_v1.go index a724644..b4d1d8f 100644 --- a/matchmaking/update_session_host_v1.go +++ b/matchmaking/update_session_host_v1.go @@ -3,19 +3,12 @@ package matchmaking import ( nex "github.com/PretendoNetwork/nex-go" match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" + common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" ) func updateSessionHostV1(err error, client *nex.Client, callID uint32, gid uint32) { server := commonMatchMakingProtocol.server - missingHandler := false - if commonMatchMakingProtocol.UpdateRoomHostHandler == nil { - logger.Warning("MatchMaking::UpdateSessionHostV1 missing UpdateRoomHostHandler!") - missingHandler = true - } - if missingHandler { - return - } - commonMatchMakingProtocol.UpdateRoomHostHandler(gid, client.PID()) + common_globals.Sessions[gid].GameMatchmakeSession.Gathering.HostPID = client.PID() rmcResponse := nex.NewRMCResponse(match_making.ProtocolID, callID) rmcResponse.SetSuccess(match_making.MethodUpdateSessionHostV1, nil) From 237060b9cba3e01e7c0dc1d5f751dbd9f1de0078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Tue, 6 Jun 2023 20:48:03 +0100 Subject: [PATCH 4/9] Update go modules --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 7104ac7..2dd2a8c 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/PretendoNetwork/nex-protocols-common-go go 1.19 require ( - github.com/PretendoNetwork/nex-go v1.0.22 - github.com/PretendoNetwork/nex-protocols-go v1.0.26 + github.com/PretendoNetwork/nex-go v1.0.25 + github.com/PretendoNetwork/nex-protocols-go v1.0.28 github.com/PretendoNetwork/plogger-go v1.0.2 ) @@ -12,7 +12,7 @@ require ( github.com/fatih/color v1.15.0 // indirect github.com/jwalton/go-supportscolor v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/superwhiskers/crunch/v3 v3.5.7 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/term v0.8.0 // indirect diff --git a/go.sum b/go.sum index 0a7048d..213b492 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -github.com/PretendoNetwork/nex-go v1.0.22 h1:BXUvnp++muen86t2Iv47h2ZCX8xWMw00p8nTzS57zRE= -github.com/PretendoNetwork/nex-go v1.0.22/go.mod h1:Bx2ONeSefnbJyE0IDIwGopxrjRrnszOV/uQv74Cx+m0= -github.com/PretendoNetwork/nex-protocols-go v1.0.26 h1:jscXlgcyz1xZVY4kyR2m9366uof8pm9msf+IOtK6tVU= -github.com/PretendoNetwork/nex-protocols-go v1.0.26/go.mod h1:Rg3dwo0dU+uujoI9q1kcQkDiSYKpuew0xF8ojIaUPm0= +github.com/PretendoNetwork/nex-go v1.0.25 h1:x324hqKItxZSq+8KFhdwjVusB9y05CciTmAOZ+i819U= +github.com/PretendoNetwork/nex-go v1.0.25/go.mod h1:qzc5s4iNrt1ubS9Axb38b2jPuEsiETN2mDijn+MthmI= +github.com/PretendoNetwork/nex-protocols-go v1.0.28 h1:Nn+qt0pqwALvnlYwfTk34uEt4w3LRRkTurLelsKWcyo= +github.com/PretendoNetwork/nex-protocols-go v1.0.28/go.mod h1:YXXNqT7mjE/fDX4ia/liLzrzJxzdSRIlwQ+2MA2LRls= github.com/PretendoNetwork/plogger-go v1.0.2 h1:vWKEnEmJJzYwqLxLyiSsAvCrZV6qnnu/a0GQOjIfzY0= github.com/PretendoNetwork/plogger-go v1.0.2/go.mod h1:7kD6M4vPq1JL4LTuPg6kuB1OvUBOwQOtAvTaUwMbwvU= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= @@ -12,8 +12,8 @@ github.com/jwalton/go-supportscolor v1.1.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2q github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/superwhiskers/crunch/v3 v3.5.7 h1:N9RLxaR65C36i26BUIpzPXGy2f6pQ7wisu2bawbKNqg= github.com/superwhiskers/crunch/v3 v3.5.7/go.mod h1:4ub2EKgF1MAhTjoOCTU4b9uLMsAweHEa89aRrfAypXA= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From e59833437320b6f3c20d3072838c92627c7245da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Tue, 6 Jun 2023 20:54:09 +0100 Subject: [PATCH 5/9] Address PR issues And other improvements --- globals/matchmaking_globals.go | 25 ++++++++++++++----- .../auto_matchmake_postpone.go | 17 +++++++------ matchmake-extension/protocol.go | 6 ++--- matchmaking-ext/end_participation.go | 25 +++++++++++++++++-- matchmaking-ext/protocol.go | 2 +- nat-traversal/report_nat_traversal_result.go | 1 - 6 files changed, 56 insertions(+), 20 deletions(-) diff --git a/globals/matchmaking_globals.go b/globals/matchmaking_globals.go index 973748a..907236d 100644 --- a/globals/matchmaking_globals.go +++ b/globals/matchmaking_globals.go @@ -5,8 +5,8 @@ import ( ) type CommonMatchmakeSession struct { - GameMatchmakeSession match_making.MatchmakeSession //used by the game, contains the current state of the MatchmakeSession - SearchMatchmakeSession match_making.MatchmakeSession //used by the server when searching for matches, contains the state of the MatchmakeSession during the search process for easy compares + GameMatchmakeSession *match_making.MatchmakeSession //used by the game, contains the current state of the MatchmakeSession + SearchMatchmakeSession *match_making.MatchmakeSession //used by the server when searching for matches, contains the state of the MatchmakeSession during the search process for easy compares ConnectionIDs []uint32 //players in the room, referenced by their connection IDs. This is used instead of the PID in order to ensure we're talking to the correct client (in case of e.g. multiple logins) } @@ -14,7 +14,20 @@ var Sessions map[uint32]*CommonMatchmakeSession var CurrentGatheringID uint32 func DeleteIndex(s []uint32, index int) []uint32 { - return append(s[:index], s[index+1:]...) + if len(s) <= 1 { + return make([]uint32, 0) + } + + return append(s[:index], s[index+1:]...) +} + +func FindOtherConnectionID(myConnectionID uint32, gathering uint32) uint32 { + for _, connectionID := range Sessions[gathering].ConnectionIDs { + if connectionID != myConnectionID { + return connectionID + } + } + return math.MaxUint32 } func RemoveConnectionIDFromRoom(clientConnectionID uint32, gathering uint32) { @@ -41,17 +54,17 @@ func FindClientSession(clientConnectionID uint32) uint32 { func RemoveConnectionIDFromAllSessions(clientConnectionID uint32) { foundSession := FindClientSession(clientConnectionID) - if(foundSession != math.MaxUint32){ + if foundSession != math.MaxUint32 { RemoveConnectionIDFromRoom(clientConnectionID, foundSession) } } -func FindSearchMatchmakeSession(searchMatchmakeSession match_making.MatchmakeSession) int { +func FindSearchMatchmakeSession(searchMatchmakeSession *match_making.MatchmakeSession) int { returnSessionIndex := math.MaxUint32 //this portion finds any sessions that match the search session. It does not care about anything beyond that, such as if the match is already full. This is handled below. candidateSessionIndexes := make([]uint32, 0, len(Sessions)) for index, session := range Sessions { - if session.SearchMatchmakeSession.Equals(&searchMatchmakeSession) { + if session.SearchMatchmakeSession.Equals(searchMatchmakeSession) { candidateSessionIndexes = append(candidateSessionIndexes, index) } } diff --git a/matchmake-extension/auto_matchmake_postpone.go b/matchmake-extension/auto_matchmake_postpone.go index df1d6ba..14257b8 100644 --- a/matchmake-extension/auto_matchmake_postpone.go +++ b/matchmake-extension/auto_matchmake_postpone.go @@ -10,20 +10,24 @@ import ( common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" ) -func AutoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchmakeSession *match_making.MatchmakeSession, message string) { +func autoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchmakeSession *match_making.MatchmakeSession, message string) { server := commonMatchmakeExtensionProtocol.server if commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler == nil { logger.Warning("MatchmakeExtension::AutoMatchmake_Postpone missing CleanupSearchMatchmakeSessionHandler!") return } - matchmakeSessionCopy := matchmakeSession.Copy().(*match_making.MatchmakeSession) - searchMatchmakeSession := commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler(*matchmakeSessionCopy) + // A client may disconnect from a session without leaving reliably, + // so let's make sure the client is removed from the session + common_globals.RemoveConnectionIDFromAllSessions(client.ConnectionID()) + + searchMatchmakeSession := matchmakeSession.Copy().(*match_making.MatchmakeSession) + commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler(searchMatchmakeSession) sessionIndex := uint32(common_globals.FindSearchMatchmakeSession(searchMatchmakeSession)) if sessionIndex == math.MaxUint32 { session := common_globals.CommonMatchmakeSession{ SearchMatchmakeSession: searchMatchmakeSession, - GameMatchmakeSession: *matchmakeSession, + GameMatchmakeSession: matchmakeSession, } sessionIndex = common_globals.CurrentGatheringID common_globals.Sessions[sessionIndex] = &session @@ -32,8 +36,7 @@ func AutoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchm common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.HostPID = client.PID() currentTime := nex.NewDateTime(0) - currentTime = nex.NewDateTime(currentTime.UTC()) - common_globals.Sessions[sessionIndex].GameMatchmakeSession.StartedTime = currentTime + common_globals.Sessions[sessionIndex].GameMatchmakeSession.StartedTime = nex.NewDateTime(currentTime.UTC()) common_globals.CurrentGatheringID++ } @@ -44,7 +47,7 @@ func AutoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchm rmcResponseStream := nex.NewStreamOut(server) matchmakeDataHolder := nex.NewDataHolder() matchmakeDataHolder.SetTypeName("MatchmakeSession") - matchmakeDataHolder.SetObjectData(&common_globals.Sessions[sessionIndex].GameMatchmakeSession) + matchmakeDataHolder.SetObjectData(common_globals.Sessions[sessionIndex].GameMatchmakeSession) rmcResponseStream.WriteDataHolder(matchmakeDataHolder) rmcResponseBody := rmcResponseStream.Bytes() diff --git a/matchmake-extension/protocol.go b/matchmake-extension/protocol.go index b47a521..78402f1 100644 --- a/matchmake-extension/protocol.go +++ b/matchmake-extension/protocol.go @@ -14,11 +14,11 @@ type CommonMatchmakeExtensionProtocol struct { *matchmake_extension.MatchmakeExtensionProtocol server *nex.Server - cleanupSearchMatchmakeSessionHandler func(matchmakeSession match_making.MatchmakeSession) match_making.MatchmakeSession + cleanupSearchMatchmakeSessionHandler func(matchmakeSession *match_making.MatchmakeSession) } // CleanupSearchMatchmakeSession sets the CleanupSearchMatchmakeSession handler function -func (commonMatchmakeExtensionProtocol *CommonMatchmakeExtensionProtocol) CleanupSearchMatchmakeSession(handler func(matchmakeSession match_making.MatchmakeSession) match_making.MatchmakeSession) { +func (commonMatchmakeExtensionProtocol *CommonMatchmakeExtensionProtocol) CleanupSearchMatchmakeSession(handler func(matchmakeSession *match_making.MatchmakeSession)) { commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler = handler } @@ -27,7 +27,7 @@ func NewCommonMatchmakeExtensionProtocol(server *nex.Server) *CommonMatchmakeExt MatchmakeExtensionProtocol := matchmake_extension.NewMatchmakeExtensionProtocol(server) commonMatchmakeExtensionProtocol = &CommonMatchmakeExtensionProtocol{MatchmakeExtensionProtocol: MatchmakeExtensionProtocol, server: server} - MatchmakeExtensionProtocol.AutoMatchmake_Postpone(AutoMatchmake_Postpone) + MatchmakeExtensionProtocol.AutoMatchmake_Postpone(autoMatchmake_Postpone) return commonMatchmakeExtensionProtocol } diff --git a/matchmaking-ext/end_participation.go b/matchmaking-ext/end_participation.go index 27cc683..828c5eb 100644 --- a/matchmaking-ext/end_participation.go +++ b/matchmaking-ext/end_participation.go @@ -1,19 +1,26 @@ package match_making_ext import ( + "math" + nex "github.com/PretendoNetwork/nex-go" - match_making_ext "github.com/PretendoNetwork/nex-protocols-go/match-making-ext" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" + match_making_ext "github.com/PretendoNetwork/nex-protocols-go/match-making-ext" "github.com/PretendoNetwork/nex-protocols-go/notifications" ) -func EndParticipation(err error, client *nex.Client, callID uint32, idGathering uint32, strMessage string) { +func endParticipation(err error, client *nex.Client, callID uint32, idGathering uint32, strMessage string) { server := commonMatchMakingExtProtocol.server matchmakeSession := common_globals.Sessions[idGathering].GameMatchmakeSession ownerPID := matchmakeSession.Gathering.OwnerPID if client.PID() == matchmakeSession.Gathering.OwnerPID { + // Flag 0x10 tells the server to change the matchmake session owner if they disconnect + // If the flag is not set, delete the session + // More info: https://nintendo-wiki.pretendo.network/docs/nex/protocols/match-making/types#flags if matchmakeSession.Gathering.Flags & 0x10 == 0 { delete(common_globals.Sessions, idGathering) + } else { + changeSessionOwner(client.ConnectionID(), idGathering) } } @@ -89,3 +96,17 @@ func EndParticipation(err error, client *nex.Client, callID uint32, idGathering server.Send(messagePacket) } + +func changeSessionOwner(ownerConnectionID uint32, gathering uint32) { + otherConnectionID := common_globals.FindOtherConnectionID(ownerConnectionID, gathering) + if otherConnectionID != math.MaxUint32 { + server := commonMatchMakingExtProtocol.server + + otherClient := server.FindClientFromConnectionID(otherConnectionID) + if otherClient != nil { + common_globals.Sessions[gathering].GameMatchmakeSession.Gathering.OwnerPID = otherClient.PID() + } else { + logger.Warning("Other client not found") + } + } +} diff --git a/matchmaking-ext/protocol.go b/matchmaking-ext/protocol.go index 2ad9537..2dd77e6 100644 --- a/matchmaking-ext/protocol.go +++ b/matchmaking-ext/protocol.go @@ -19,7 +19,7 @@ func NewCommonMatchMakingExtProtocol(server *nex.Server) *CommonMatchMakingExtPr MatchMakingExtProtocol := match_making_ext.NewMatchMakingExtProtocol(server) commonMatchMakingExtProtocol = &CommonMatchMakingExtProtocol{MatchMakingExtProtocol: MatchMakingExtProtocol, server: server} - MatchMakingExtProtocol.EndParticipation(EndParticipation) + MatchMakingExtProtocol.EndParticipation(endParticipation) return commonMatchMakingExtProtocol } diff --git a/nat-traversal/report_nat_traversal_result.go b/nat-traversal/report_nat_traversal_result.go index 1276e3a..39d7323 100644 --- a/nat-traversal/report_nat_traversal_result.go +++ b/nat-traversal/report_nat_traversal_result.go @@ -23,7 +23,6 @@ func reportNATTraversalResult(err error, client *nex.Client, callID uint32, cid responsePacket.SetVersion(1) } - responsePacket.SetVersion(1) responsePacket.SetSource(0xA1) responsePacket.SetDestination(0xAF) responsePacket.SetType(nex.DataPacket) From 6f5fbd94d5a3eddaceea6e4263cc097beb095d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Thu, 8 Jun 2023 18:30:01 +0100 Subject: [PATCH 6/9] Send ownership change from EndParticipation --- matchmaking-ext/end_participation.go | 73 +++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/matchmaking-ext/end_participation.go b/matchmaking-ext/end_participation.go index 828c5eb..2d4e63b 100644 --- a/matchmaking-ext/end_participation.go +++ b/matchmaking-ext/end_participation.go @@ -13,18 +13,24 @@ func endParticipation(err error, client *nex.Client, callID uint32, idGathering server := commonMatchMakingExtProtocol.server matchmakeSession := common_globals.Sessions[idGathering].GameMatchmakeSession ownerPID := matchmakeSession.Gathering.OwnerPID + + var deleteSession bool = false if client.PID() == matchmakeSession.Gathering.OwnerPID { // Flag 0x10 tells the server to change the matchmake session owner if they disconnect // If the flag is not set, delete the session // More info: https://nintendo-wiki.pretendo.network/docs/nex/protocols/match-making/types#flags if matchmakeSession.Gathering.Flags & 0x10 == 0 { - delete(common_globals.Sessions, idGathering) + deleteSession = true } else { - changeSessionOwner(client.ConnectionID(), idGathering) + changeSessionOwner(client.ConnectionID(), idGathering, callID) } } - common_globals.RemoveConnectionIDFromRoom(client.ConnectionID(), idGathering) + if deleteSession { + delete(common_globals.Sessions, idGathering) + } else { + common_globals.RemoveConnectionIDFromRoom(client.ConnectionID(), idGathering) + } rmcResponseStream := nex.NewStreamOut(server) @@ -97,16 +103,69 @@ func endParticipation(err error, client *nex.Client, callID uint32, idGathering server.Send(messagePacket) } -func changeSessionOwner(ownerConnectionID uint32, gathering uint32) { +func changeSessionOwner(ownerConnectionID uint32, gathering uint32, callID uint32) { + server := commonMatchMakingExtProtocol.server + var otherClient *nex.Client + otherConnectionID := common_globals.FindOtherConnectionID(ownerConnectionID, gathering) if otherConnectionID != math.MaxUint32 { - server := commonMatchMakingExtProtocol.server - - otherClient := server.FindClientFromConnectionID(otherConnectionID) + otherClient = server.FindClientFromConnectionID(otherConnectionID) if otherClient != nil { common_globals.Sessions[gathering].GameMatchmakeSession.Gathering.OwnerPID = otherClient.PID() } else { logger.Warning("Other client not found") + return + } + } else { + return + } + + rmcMessage := nex.NewRMCRequest() + rmcMessage.SetProtocolID(notifications.ProtocolID) + rmcMessage.SetCallID(0xffff0000 + callID) + rmcMessage.SetMethodID(notifications.MethodProcessNotificationEvent) + + oEvent := notifications.NewNotificationEvent() + oEvent.PIDSource = otherClient.PID() + oEvent.Type = notifications.NotificationTypes.OwnershipChanged + oEvent.Param1 = gathering + oEvent.Param2 = otherClient.PID() + + // TODO - This doesn't seem to appear on all servers + // https://github.com/kinnay/NintendoClients/issues/101 + // unixTime := time.Now() + // oEvent.StrParam = strconv.FormatInt(unixTime.UnixMicro(), 10) + + stream := nex.NewStreamOut(server) + oEventBytes := oEvent.Bytes(stream) + rmcMessage.SetParameters(oEventBytes) + + rmcRequestBytes := rmcMessage.Bytes() + + for _, connectionID := range common_globals.Sessions[gathering].ConnectionIDs { + targetClient := server.FindClientFromConnectionID(connectionID) + if targetClient != nil { + var messagePacket nex.PacketInterface + + if server.PRUDPVersion() == 0 { + messagePacket, _ = nex.NewPacketV0(targetClient, nil) + messagePacket.SetVersion(0) + } else { + messagePacket, _ = nex.NewPacketV1(targetClient, nil) + messagePacket.SetVersion(1) + } + + messagePacket.SetSource(0xA1) + messagePacket.SetDestination(0xAF) + messagePacket.SetType(nex.DataPacket) + messagePacket.SetPayload(rmcRequestBytes) + + messagePacket.AddFlag(nex.FlagNeedsAck) + messagePacket.AddFlag(nex.FlagReliable) + + server.Send(messagePacket) + } else { + logger.Warning("Client not found") } } } From c1dc70edfc34528c86a9f08e67c6c4b64ba4ee23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Sun, 11 Jun 2023 15:46:28 +0100 Subject: [PATCH 7/9] Fix PR issues --- globals/matchmaking_globals.go | 53 +++++++++++++------ .../auto_matchmake_postpone.go | 26 +++++---- matchmaking-ext/end_participation.go | 10 ++-- matchmaking/update_session_host.go | 2 +- 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/globals/matchmaking_globals.go b/globals/matchmaking_globals.go index 907236d..aeee225 100644 --- a/globals/matchmaking_globals.go +++ b/globals/matchmaking_globals.go @@ -1,35 +1,50 @@ package common_globals import ( - match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" "math" + + match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" ) type CommonMatchmakeSession struct { - GameMatchmakeSession *match_making.MatchmakeSession //used by the game, contains the current state of the MatchmakeSession - SearchMatchmakeSession *match_making.MatchmakeSession //used by the server when searching for matches, contains the state of the MatchmakeSession during the search process for easy compares - ConnectionIDs []uint32 //players in the room, referenced by their connection IDs. This is used instead of the PID in order to ensure we're talking to the correct client (in case of e.g. multiple logins) + GameMatchmakeSession *match_making.MatchmakeSession // Used by the game, contains the current state of the MatchmakeSession + SearchMatchmakeSession *match_making.MatchmakeSession // Used by the server when searching for matches, contains the state of the MatchmakeSession during the search process for easy compares + ConnectionIDs []uint32 // Players in the room, referenced by their connection IDs. This is used instead of the PID in order to ensure we're talking to the correct client (in case of e.g. multiple logins) } var Sessions map[uint32]*CommonMatchmakeSession -var CurrentGatheringID uint32 -func DeleteIndex(s []uint32, index int) []uint32 { - if len(s) <= 1 { - return make([]uint32, 0) +// GetSessionIndex returns a gathering ID which doesn't belong to any session +func GetSessionIndex() uint32 { + var gatheringID uint32 = 1 + for gatheringID < math.MaxUint32 { + // If the session does not exist, the gathering ID is empty and can be used + if _, ok := Sessions[gatheringID]; !ok { + return gatheringID + } + + gatheringID++ } - return append(s[:index], s[index+1:]...) + return 0 } +// DeleteIndex removes a value from a slice with the given index +func DeleteIndex(s []uint32, index int) []uint32 { + s[index] = s[len(s)-1] + return s[:len(s)-1] +} + +// FindOtherConnectionID searches a connection ID on the gathering that isn't the given one func FindOtherConnectionID(myConnectionID uint32, gathering uint32) uint32 { for _, connectionID := range Sessions[gathering].ConnectionIDs { if connectionID != myConnectionID { return connectionID } } - return math.MaxUint32 + return 0 } +// RemoveConnectionIDFromRoom removes a client from the gathering func RemoveConnectionIDFromRoom(clientConnectionID uint32, gathering uint32) { for index, connectionID := range Sessions[gathering].ConnectionIDs { if connectionID == clientConnectionID { @@ -41,6 +56,7 @@ func RemoveConnectionIDFromRoom(clientConnectionID uint32, gathering uint32) { } } +// FindClientSession searches the gathering where the client is on func FindClientSession(clientConnectionID uint32) uint32 { for gatheringID := range Sessions { for _, connectionID := range Sessions[gatheringID].ConnectionIDs { @@ -49,19 +65,22 @@ func FindClientSession(clientConnectionID uint32) uint32 { } } } - return math.MaxUint32 + return 0 } +// RemoveConnectionIDFromAllSessions removes a client from every session func RemoveConnectionIDFromAllSessions(clientConnectionID uint32) { foundSession := FindClientSession(clientConnectionID) - if foundSession != math.MaxUint32 { - RemoveConnectionIDFromRoom(clientConnectionID, foundSession) + if foundSession != 0 { + RemoveConnectionIDFromRoom(clientConnectionID, uint32(foundSession)) } } -func FindSearchMatchmakeSession(searchMatchmakeSession *match_making.MatchmakeSession) int { - returnSessionIndex := math.MaxUint32 - //this portion finds any sessions that match the search session. It does not care about anything beyond that, such as if the match is already full. This is handled below. +// SearchGatheringWithMatchmakeSession finds a gathering that matches with a MatchmakeSession +func SearchGatheringWithMatchmakeSession(searchMatchmakeSession *match_making.MatchmakeSession) uint32 { + var returnSessionIndex uint32 = 0 + + // This portion finds any sessions that match the search session. It does not care about anything beyond that, such as if the match is already full. This is handled below. candidateSessionIndexes := make([]uint32, 0, len(Sessions)) for index, session := range Sessions { if session.SearchMatchmakeSession.Equals(searchMatchmakeSession) { @@ -73,7 +92,7 @@ func FindSearchMatchmakeSession(searchMatchmakeSession *match_making.MatchmakeSe if len(sessionToCheck.ConnectionIDs) >= int(sessionToCheck.GameMatchmakeSession.MaximumParticipants) { continue } else { - returnSessionIndex = int(sessionIndex) //found a match + returnSessionIndex = sessionIndex //found a match break } } diff --git a/matchmake-extension/auto_matchmake_postpone.go b/matchmake-extension/auto_matchmake_postpone.go index 14257b8..a64b94c 100644 --- a/matchmake-extension/auto_matchmake_postpone.go +++ b/matchmake-extension/auto_matchmake_postpone.go @@ -1,8 +1,6 @@ package matchmake_extension import ( - "math" - nex "github.com/PretendoNetwork/nex-go" match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" matchmake_extension "github.com/PretendoNetwork/nex-protocols-go/matchmake-extension" @@ -23,22 +21,28 @@ func autoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchm searchMatchmakeSession := matchmakeSession.Copy().(*match_making.MatchmakeSession) commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler(searchMatchmakeSession) - sessionIndex := uint32(common_globals.FindSearchMatchmakeSession(searchMatchmakeSession)) - if sessionIndex == math.MaxUint32 { + sessionIndex := common_globals.SearchGatheringWithMatchmakeSession(searchMatchmakeSession) + if sessionIndex == 0 { + sessionIndex = common_globals.GetSessionIndex() + // This should in theory be impossible, as there aren't enough PIDs creating sessions to fill the uint32 limit. + // If we ever get here, we must be not deleting sessions properly + if sessionIndex == 0 { + logger.Critical("No gatherings available!") + return + } + session := common_globals.CommonMatchmakeSession{ SearchMatchmakeSession: searchMatchmakeSession, GameMatchmakeSession: matchmakeSession, } - sessionIndex = common_globals.CurrentGatheringID + common_globals.Sessions[sessionIndex] = &session - common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.ID = uint32(sessionIndex) + common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.ID = sessionIndex common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.OwnerPID = client.PID() common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.HostPID = client.PID() - currentTime := nex.NewDateTime(0) - common_globals.Sessions[sessionIndex].GameMatchmakeSession.StartedTime = nex.NewDateTime(currentTime.UTC()) - - common_globals.CurrentGatheringID++ + common_globals.Sessions[sessionIndex].GameMatchmakeSession.StartedTime = nex.NewDateTime(0) + common_globals.Sessions[sessionIndex].GameMatchmakeSession.StartedTime.UTC() } common_globals.Sessions[sessionIndex].ConnectionIDs = append(common_globals.Sessions[sessionIndex].ConnectionIDs, client.ConnectionID()) @@ -84,7 +88,7 @@ func autoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchm oEvent := notifications.NewNotificationEvent() oEvent.PIDSource = common_globals.Sessions[sessionIndex].GameMatchmakeSession.Gathering.HostPID oEvent.Type = notifications.NotificationTypes.NewParticipant - oEvent.Param1 = uint32(sessionIndex) + oEvent.Param1 = sessionIndex oEvent.Param2 = client.PID() oEvent.StrParam = message diff --git a/matchmaking-ext/end_participation.go b/matchmaking-ext/end_participation.go index 2d4e63b..4185919 100644 --- a/matchmaking-ext/end_participation.go +++ b/matchmaking-ext/end_participation.go @@ -1,8 +1,6 @@ package match_making_ext import ( - "math" - nex "github.com/PretendoNetwork/nex-go" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" match_making_ext "github.com/PretendoNetwork/nex-protocols-go/match-making-ext" @@ -19,7 +17,7 @@ func endParticipation(err error, client *nex.Client, callID uint32, idGathering // Flag 0x10 tells the server to change the matchmake session owner if they disconnect // If the flag is not set, delete the session // More info: https://nintendo-wiki.pretendo.network/docs/nex/protocols/match-making/types#flags - if matchmakeSession.Gathering.Flags & 0x10 == 0 { + if matchmakeSession.Gathering.Flags & 0x10 == 0 { // DisconnectChangeOwner deleteSession = true } else { changeSessionOwner(client.ConnectionID(), idGathering, callID) @@ -108,8 +106,8 @@ func changeSessionOwner(ownerConnectionID uint32, gathering uint32, callID uint3 var otherClient *nex.Client otherConnectionID := common_globals.FindOtherConnectionID(ownerConnectionID, gathering) - if otherConnectionID != math.MaxUint32 { - otherClient = server.FindClientFromConnectionID(otherConnectionID) + if otherConnectionID != 0 { + otherClient = server.FindClientFromConnectionID(uint32(otherConnectionID)) if otherClient != nil { common_globals.Sessions[gathering].GameMatchmakeSession.Gathering.OwnerPID = otherClient.PID() } else { @@ -131,7 +129,7 @@ func changeSessionOwner(ownerConnectionID uint32, gathering uint32, callID uint3 oEvent.Param1 = gathering oEvent.Param2 = otherClient.PID() - // TODO - This doesn't seem to appear on all servers + // TODO - StrParam doesn't have this value on some servers // https://github.com/kinnay/NintendoClients/issues/101 // unixTime := time.Now() // oEvent.StrParam = strconv.FormatInt(unixTime.UnixMicro(), 10) diff --git a/matchmaking/update_session_host.go b/matchmaking/update_session_host.go index 03a72c6..d89f740 100644 --- a/matchmaking/update_session_host.go +++ b/matchmaking/update_session_host.go @@ -54,7 +54,7 @@ func updateSessionHost(err error, client *nex.Client, callID uint32, gid uint32, oEvent.Param1 = gid oEvent.Param2 = client.PID() - // TODO - This doesn't seem to appear on all servers + // TODO - StrParam doesn't have this value on some servers // https://github.com/kinnay/NintendoClients/issues/101 // unixTime := time.Now() // oEvent.StrParam = strconv.FormatInt(unixTime.UnixMicro(), 10) From ec12cfb374c445f95df747bf061f0a8ec8f20db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Thu, 15 Jun 2023 19:06:08 +0100 Subject: [PATCH 8/9] Update go modules Also implement Kerberos ticket time check. --- authentication/generate_ticket.go | 19 +++++- authentication/login_ex.go | 2 +- authentication/protocol.go | 1 + go.mod | 4 +- go.sum | 8 +-- .../auto_matchmake_postpone.go | 9 ++- matchmaking-ext/end_participation.go | 5 +- matchmaking/protocol.go | 1 + secure-connection/connect.go | 64 ++++++++++++++++--- 9 files changed, 91 insertions(+), 22 deletions(-) diff --git a/authentication/generate_ticket.go b/authentication/generate_ticket.go index e77871a..91b5f1e 100644 --- a/authentication/generate_ticket.go +++ b/authentication/generate_ticket.go @@ -50,15 +50,28 @@ func generateTicket(userPID uint32, targetPID uint32) ([]byte, uint32) { rand.Read(sessionKey) ticketInternalData := nex.NewKerberosTicketInternalData() - ticketInternalData.SetTimestamp(nex.NewDateTime(0)) // CHANGE THIS + serverTime := nex.NewDateTime(0) + serverTime.UTC() + ticketInternalData.SetTimestamp(serverTime) ticketInternalData.SetUserPID(userPID) ticketInternalData.SetSessionKey(sessionKey) - encryptedTicketInternalData := ticketInternalData.Encrypt(targetKey, nex.NewStreamOut(commonAuthenticationProtocol.server)) + + encryptedTicketInternalData, err := ticketInternalData.Encrypt(targetKey, nex.NewStreamOut(commonAuthenticationProtocol.server)) + if err != nil { + logger.Error(err.Error()) + return []byte{}, nex.Errors.Authentication.Unknown + } ticket := nex.NewKerberosTicket() ticket.SetSessionKey(sessionKey) ticket.SetTargetPID(targetPID) ticket.SetInternalData(encryptedTicketInternalData) - return ticket.Encrypt(userKey, nex.NewStreamOut(commonAuthenticationProtocol.server)), 0 + encryptedTicket, err := ticket.Encrypt(userKey, nex.NewStreamOut(commonAuthenticationProtocol.server)) + if err != nil { + logger.Error(err.Error()) + return []byte{}, nex.Errors.Authentication.Unknown + } + + return encryptedTicket, 0 } diff --git a/authentication/login_ex.go b/authentication/login_ex.go index b276f18..759fb17 100644 --- a/authentication/login_ex.go +++ b/authentication/login_ex.go @@ -8,7 +8,7 @@ import ( "github.com/PretendoNetwork/nex-protocols-go/authentication" ) -func loginEx(err error, client *nex.Client, callID uint32, username string, authenticationInfo *authentication.AuthenticationInfo) { +func loginEx(err error, client *nex.Client, callID uint32, username string, oExtraData *nex.DataHolder) { var userPID uint32 if username == "guest" { diff --git a/authentication/protocol.go b/authentication/protocol.go index 47ded43..d7e854c 100644 --- a/authentication/protocol.go +++ b/authentication/protocol.go @@ -2,6 +2,7 @@ package authentication import ( "github.com/PretendoNetwork/nex-go" + _ "github.com/PretendoNetwork/nex-protocols-go" "github.com/PretendoNetwork/nex-protocols-go/authentication" "github.com/PretendoNetwork/plogger-go" ) diff --git a/go.mod b/go.mod index 2dd2a8c..1f10235 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/PretendoNetwork/nex-protocols-common-go go 1.19 require ( - github.com/PretendoNetwork/nex-go v1.0.25 - github.com/PretendoNetwork/nex-protocols-go v1.0.28 + github.com/PretendoNetwork/nex-go v1.0.26 + github.com/PretendoNetwork/nex-protocols-go v1.0.32 github.com/PretendoNetwork/plogger-go v1.0.2 ) diff --git a/go.sum b/go.sum index 213b492..ec27c85 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -github.com/PretendoNetwork/nex-go v1.0.25 h1:x324hqKItxZSq+8KFhdwjVusB9y05CciTmAOZ+i819U= -github.com/PretendoNetwork/nex-go v1.0.25/go.mod h1:qzc5s4iNrt1ubS9Axb38b2jPuEsiETN2mDijn+MthmI= -github.com/PretendoNetwork/nex-protocols-go v1.0.28 h1:Nn+qt0pqwALvnlYwfTk34uEt4w3LRRkTurLelsKWcyo= -github.com/PretendoNetwork/nex-protocols-go v1.0.28/go.mod h1:YXXNqT7mjE/fDX4ia/liLzrzJxzdSRIlwQ+2MA2LRls= +github.com/PretendoNetwork/nex-go v1.0.26 h1:lJqDS5F8s836xcQzCEI5hNvUesmTsh2NGDC4tZvG250= +github.com/PretendoNetwork/nex-go v1.0.26/go.mod h1:qzc5s4iNrt1ubS9Axb38b2jPuEsiETN2mDijn+MthmI= +github.com/PretendoNetwork/nex-protocols-go v1.0.32 h1:FdZwpzDdhNLSX1DVQIK91b8a+QI7Z6ow7hYlbMEjBYI= +github.com/PretendoNetwork/nex-protocols-go v1.0.32/go.mod h1:Pw1u2rsZGXuv45iM9y/7nZ5TBr1L5hctv9ylNXlW1ws= github.com/PretendoNetwork/plogger-go v1.0.2 h1:vWKEnEmJJzYwqLxLyiSsAvCrZV6qnnu/a0GQOjIfzY0= github.com/PretendoNetwork/plogger-go v1.0.2/go.mod h1:7kD6M4vPq1JL4LTuPg6kuB1OvUBOwQOtAvTaUwMbwvU= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= diff --git a/matchmake-extension/auto_matchmake_postpone.go b/matchmake-extension/auto_matchmake_postpone.go index a64b94c..3aaf733 100644 --- a/matchmake-extension/auto_matchmake_postpone.go +++ b/matchmake-extension/auto_matchmake_postpone.go @@ -8,7 +8,7 @@ import ( common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" ) -func autoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchmakeSession *match_making.MatchmakeSession, message string) { +func autoMatchmake_Postpone(err error, client *nex.Client, callID uint32, anyGathering *nex.DataHolder, message string) { server := commonMatchmakeExtensionProtocol.server if commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler == nil { logger.Warning("MatchmakeExtension::AutoMatchmake_Postpone missing CleanupSearchMatchmakeSessionHandler!") @@ -19,6 +19,13 @@ func autoMatchmake_Postpone(err error, client *nex.Client, callID uint32, matchm // so let's make sure the client is removed from the session common_globals.RemoveConnectionIDFromAllSessions(client.ConnectionID()) + var matchmakeSession *match_making.MatchmakeSession + anyGatheringDataType := anyGathering.TypeName() + + if anyGatheringDataType == "MatchmakeSession" { + matchmakeSession = anyGathering.ObjectData().(*match_making.MatchmakeSession) + } + searchMatchmakeSession := matchmakeSession.Copy().(*match_making.MatchmakeSession) commonMatchmakeExtensionProtocol.cleanupSearchMatchmakeSessionHandler(searchMatchmakeSession) sessionIndex := common_globals.SearchGatheringWithMatchmakeSession(searchMatchmakeSession) diff --git a/matchmaking-ext/end_participation.go b/matchmaking-ext/end_participation.go index 4185919..3dd8781 100644 --- a/matchmaking-ext/end_participation.go +++ b/matchmaking-ext/end_participation.go @@ -3,6 +3,7 @@ package match_making_ext import ( nex "github.com/PretendoNetwork/nex-go" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" + match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" match_making_ext "github.com/PretendoNetwork/nex-protocols-go/match-making-ext" "github.com/PretendoNetwork/nex-protocols-go/notifications" ) @@ -14,10 +15,10 @@ func endParticipation(err error, client *nex.Client, callID uint32, idGathering var deleteSession bool = false if client.PID() == matchmakeSession.Gathering.OwnerPID { - // Flag 0x10 tells the server to change the matchmake session owner if they disconnect + // This flag tells the server to change the matchmake session owner if they disconnect // If the flag is not set, delete the session // More info: https://nintendo-wiki.pretendo.network/docs/nex/protocols/match-making/types#flags - if matchmakeSession.Gathering.Flags & 0x10 == 0 { // DisconnectChangeOwner + if matchmakeSession.Gathering.Flags & match_making.GatheringFlags.DisconnectChangeOwner == 0 { deleteSession = true } else { changeSessionOwner(client.ConnectionID(), idGathering, callID) diff --git a/matchmaking/protocol.go b/matchmaking/protocol.go index 8d7ee8a..e948336 100644 --- a/matchmaking/protocol.go +++ b/matchmaking/protocol.go @@ -2,6 +2,7 @@ package matchmaking import ( nex "github.com/PretendoNetwork/nex-go" + _ "github.com/PretendoNetwork/nex-protocols-go" match_making "github.com/PretendoNetwork/nex-protocols-go/match-making" "github.com/PretendoNetwork/plogger-go" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/globals" diff --git a/secure-connection/connect.go b/secure-connection/connect.go index aef1848..8876495 100644 --- a/secure-connection/connect.go +++ b/secure-connection/connect.go @@ -1,6 +1,7 @@ package secureconnection import ( + "time" "github.com/PretendoNetwork/nex-go" ) @@ -10,26 +11,71 @@ func connect(packet nex.PacketInterface) { stream := nex.NewStreamIn(payload, server) - // TODO: Error check!! - ticketData, _ := stream.ReadBuffer() - requestData, _ := stream.ReadBuffer() + ticketData, err := stream.ReadBuffer() + if err != nil { + logger.Error(err.Error()) + server.TimeoutKick(packet.Sender()) + return + } + + requestData, err := stream.ReadBuffer() + if err != nil { + logger.Error(err.Error()) + server.TimeoutKick(packet.Sender()) + return + } serverKey := nex.DeriveKerberosKey(2, []byte(server.KerberosPassword())) ticket := nex.NewKerberosTicketInternalData() - ticket.Decrypt(nex.NewStreamIn(ticketData, server), serverKey) + err = ticket.Decrypt(nex.NewStreamIn(ticketData, server), serverKey) + if err != nil { + logger.Error(err.Error()) + server.TimeoutKick(packet.Sender()) + return + } + + ticketTime := ticket.Timestamp().Standard() + serverTime := time.Now().UTC() - // TODO: Check timestamp here + timeLimit := serverTime.Add(time.Minute * 2) + if ticketTime.After(timeLimit) { + logger.Error("Kerberos ticket expired") + server.TimeoutKick(packet.Sender()) + return + } sessionKey := ticket.SessionKey() - kerberos := nex.NewKerberosEncryption(sessionKey) + kerberos, err := nex.NewKerberosEncryption(sessionKey) + if err != nil { + logger.Error(err.Error()) + server.TimeoutKick(packet.Sender()) + return + } decryptedRequestData := kerberos.Decrypt(requestData) checkDataStream := nex.NewStreamIn(decryptedRequestData, server) - userPID := checkDataStream.ReadUInt32LE() - _ = checkDataStream.ReadUInt32LE() //CID of secure server station url - responseCheck := checkDataStream.ReadUInt32LE() + userPID, err := checkDataStream.ReadUInt32LE() + if err != nil { + logger.Error(err.Error()) + server.TimeoutKick(packet.Sender()) + return + } + + _, err = checkDataStream.ReadUInt32LE() // CID of secure server station url + if err != nil { + logger.Error(err.Error()) + server.TimeoutKick(packet.Sender()) + return + } + + responseCheck, err := checkDataStream.ReadUInt32LE() + if err != nil { + logger.Error(err.Error()) + server.TimeoutKick(packet.Sender()) + return + } responseValueStream := nex.NewStreamOut(server) responseValueStream.WriteUInt32LE(responseCheck + 1) From eaad0fcea87783e7cd788db46a95558769c28b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Thu, 15 Jun 2023 19:35:24 +0100 Subject: [PATCH 9/9] Fix time validation of Kerberos tickets We have to increase the ticket time and compare to the server time. Whoops. --- secure-connection/connect.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/secure-connection/connect.go b/secure-connection/connect.go index 8876495..cf941d3 100644 --- a/secure-connection/connect.go +++ b/secure-connection/connect.go @@ -38,8 +38,8 @@ func connect(packet nex.PacketInterface) { ticketTime := ticket.Timestamp().Standard() serverTime := time.Now().UTC() - timeLimit := serverTime.Add(time.Minute * 2) - if ticketTime.After(timeLimit) { + timeLimit := ticketTime.Add(time.Minute * 2) + if serverTime.After(timeLimit) { logger.Error("Kerberos ticket expired") server.TimeoutKick(packet.Sender()) return