diff --git a/globals/utils.go b/globals/utils.go index d6284d0..2cb65a1 100644 --- a/globals/utils.go +++ b/globals/utils.go @@ -167,10 +167,15 @@ func SendNotificationEvent(endpoint *nex.PRUDPEndPoint, event notifications_type var messagePacket nex.PRUDPPacketInterface - if target.DefaultPRUDPVersion == 0 { + switch target.DefaultPRUDPVersion { + case 0: messagePacket, _ = nex.NewPRUDPPacketV0(server, target, nil) - } else { + case 1: messagePacket, _ = nex.NewPRUDPPacketV1(server, target, nil) + case 2: + messagePacket, _ = nex.NewPRUDPPacketLite(server, target, nil) + default: + Logger.Errorf("PRUDP version %d is not supported", target.DefaultPRUDPVersion) } messagePacket.SetType(constants.DataPacket) diff --git a/match-making/database/disconnect_participant.go b/match-making/database/disconnect_participant.go index a0d37d3..49464a2 100644 --- a/match-making/database/disconnect_participant.go +++ b/match-making/database/disconnect_participant.go @@ -49,7 +49,7 @@ func DisconnectParticipant(manager *common_globals.MatchmakingManager, connectio // * If the gathering is a PersistentGathering and the gathering isn't set to leave when disconnecting, ignore and continue // // TODO - Is the match_making.GatheringFlags.PersistentGathering check correct here? - if uint32(gathering.Flags) & match_making.GatheringFlags.PersistentGathering != 0 || (gatheringType == "PersistentGathering" && uint32(gathering.Flags) & match_making.GatheringFlags.PersistentGatheringLeaveParticipation == 0) { + if uint32(gathering.Flags)&match_making.GatheringFlags.PersistentGathering != 0 || (gatheringType == "PersistentGathering" && uint32(gathering.Flags)&match_making.GatheringFlags.PersistentGatheringLeaveParticipation == 0) { continue } @@ -67,7 +67,7 @@ func DisconnectParticipant(manager *common_globals.MatchmakingManager, connectio } // * If the gathering is a persistent gathering and allows zero users, only remove the participant from the gathering - if uint32(gathering.Flags) & (match_making.GatheringFlags.PersistentGathering | match_making.GatheringFlags.PersistentGatheringAllowZeroUsers) != 0 { + if uint32(gathering.Flags)&(match_making.GatheringFlags.PersistentGathering|match_making.GatheringFlags.PersistentGatheringAllowZeroUsers) != 0 { continue } @@ -87,7 +87,7 @@ func DisconnectParticipant(manager *common_globals.MatchmakingManager, connectio // * 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 uint32(gathering.Flags) & match_making.GatheringFlags.DisconnectChangeOwner == 0 { + if uint32(gathering.Flags)&match_making.GatheringFlags.DisconnectChangeOwner == 0 { nexError = UnregisterGathering(manager, connection.PID(), uint32(gathering.ID)) if nexError != nil { common_globals.Logger.Error(nexError.Error()) @@ -99,8 +99,8 @@ func DisconnectParticipant(manager *common_globals.MatchmakingManager, connectio oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = gathering.ID + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gathering.ID) common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, common_globals.RemoveDuplicates(participants)) @@ -125,8 +125,8 @@ func DisconnectParticipant(manager *common_globals.MatchmakingManager, connectio oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = gathering.ID + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gathering.ID) // TODO - Should the notification actually be sent to all participants? common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, common_globals.RemoveDuplicates(participants)) @@ -144,14 +144,14 @@ func DisconnectParticipant(manager *common_globals.MatchmakingManager, connectio oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = gathering.ID - oEvent.Param2 = types.NewUInt32(uint32(connection.PID())) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gathering.ID) + oEvent.Param2 = types.UInt64(connection.PID()) var participantEndedTargets []uint64 // * When the VerboseParticipants or VerboseParticipantsEx flags are set, all participant notification events are sent to everyone - if uint32(gathering.Flags) & (match_making.GatheringFlags.VerboseParticipants | match_making.GatheringFlags.VerboseParticipantsEx) != 0 { + if uint32(gathering.Flags)&(match_making.GatheringFlags.VerboseParticipants|match_making.GatheringFlags.VerboseParticipantsEx) != 0 { participantEndedTargets = common_globals.RemoveDuplicates(participants) } else { participantEndedTargets = []uint64{uint64(gathering.OwnerPID)} diff --git a/match-making/database/end_gathering_participation.go b/match-making/database/end_gathering_participation.go index 82921c1..4781d8c 100644 --- a/match-making/database/end_gathering_participation.go +++ b/match-making/database/end_gathering_participation.go @@ -35,7 +35,7 @@ func EndGatheringParticipation(manager *common_globals.MatchmakingManager, gathe } // * If the gathering is a persistent gathering and allows zero users, only remove the participant from the gathering - if uint32(gathering.Flags) & (match_making.GatheringFlags.PersistentGathering | match_making.GatheringFlags.PersistentGatheringAllowZeroUsers) != 0 { + if uint32(gathering.Flags)&(match_making.GatheringFlags.PersistentGathering|match_making.GatheringFlags.PersistentGatheringAllowZeroUsers) != 0 { return nil } @@ -49,7 +49,7 @@ func EndGatheringParticipation(manager *common_globals.MatchmakingManager, gathe // * 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 uint32(gathering.Flags) & match_making.GatheringFlags.DisconnectChangeOwner == 0 { + if uint32(gathering.Flags)&match_making.GatheringFlags.DisconnectChangeOwner == 0 { nexError = UnregisterGathering(manager, connection.PID(), gatheringID) if nexError != nil { return nexError @@ -60,8 +60,8 @@ func EndGatheringParticipation(manager *common_globals.MatchmakingManager, gathe oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gatheringID) common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, common_globals.RemoveDuplicates(newParticipants)) @@ -88,8 +88,8 @@ func EndGatheringParticipation(manager *common_globals.MatchmakingManager, gathe oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gatheringID) // TODO - Should the notification actually be sent to all participants? common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, common_globals.RemoveDuplicates(participants)) @@ -106,15 +106,15 @@ func EndGatheringParticipation(manager *common_globals.MatchmakingManager, gathe oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) - oEvent.Param2 = types.NewUInt32(uint32((connection.PID()))) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gatheringID) + oEvent.Param2 = types.UInt64(connection.PID()) oEvent.StrParam = types.NewString(message) var participationEndedTargets []uint64 // * When the VerboseParticipants or VerboseParticipantsEx flags are set, all participant notification events are sent to everyone - if uint32(gathering.Flags) & (match_making.GatheringFlags.VerboseParticipants | match_making.GatheringFlags.VerboseParticipantsEx) != 0 { + if uint32(gathering.Flags)&(match_making.GatheringFlags.VerboseParticipants|match_making.GatheringFlags.VerboseParticipantsEx) != 0 { participationEndedTargets = common_globals.RemoveDuplicates(participants) } else { participationEndedTargets = []uint64{uint64(gathering.OwnerPID)} diff --git a/match-making/database/join_gathering.go b/match-making/database/join_gathering.go index 0be3b02..92438b9 100644 --- a/match-making/database/join_gathering.go +++ b/match-making/database/join_gathering.go @@ -36,7 +36,7 @@ func JoinGathering(manager *common_globals.MatchmakingManager, gatheringID uint3 } if maxParticipants != 0 { - if uint32(len(participants)) + uint32(vacantParticipants) > maxParticipants { + if uint32(len(participants))+uint32(vacantParticipants) > maxParticipants { return 0, nex.NewError(nex.ResultCodes.RendezVous.SessionFull, "change_error") } } @@ -72,7 +72,7 @@ func JoinGathering(manager *common_globals.MatchmakingManager, gatheringID uint3 var participantJoinedTargets []uint64 // * When the VerboseParticipants or VerboseParticipantsEx flags are set, all participant notification events are sent to everyone - if flags & (match_making.GatheringFlags.VerboseParticipants | match_making.GatheringFlags.VerboseParticipantsEx) != 0 { + if flags&(match_making.GatheringFlags.VerboseParticipants|match_making.GatheringFlags.VerboseParticipantsEx) != 0 { participantJoinedTargets = common_globals.RemoveDuplicates(totalParticipants) } else { // * If the new participant is the same as the owner, then we are creating a new gathering. @@ -89,16 +89,16 @@ func JoinGathering(manager *common_globals.MatchmakingManager, gatheringID uint3 oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID() - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) - oEvent.Param2 = types.NewUInt32(uint32(connection.PID())) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) + oEvent.Param1 = types.UInt64(gatheringID) + oEvent.Param2 = types.UInt64(connection.PID()) oEvent.StrParam = types.NewString(joinMessage) - oEvent.Param3 = types.NewUInt32(uint32(len(totalParticipants))) + oEvent.Param3 = types.UInt64(len(totalParticipants)) common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, participantJoinedTargets) // * This flag also sends a recap of all currently connected players on the gathering to the participant that is connecting - if flags & match_making.GatheringFlags.VerboseParticipantsEx != 0 { + if flags&match_making.GatheringFlags.VerboseParticipantsEx != 0 { // TODO - Should this actually be deduplicated? for _, participant := range common_globals.RemoveDuplicates(participants) { notificationCategory := notifications.NotificationCategories.Participation @@ -106,11 +106,11 @@ func JoinGathering(manager *common_globals.MatchmakingManager, gatheringID uint3 oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID() - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) - oEvent.Param2 = types.NewUInt32(uint32(participant)) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) + oEvent.Param1 = types.UInt64(gatheringID) + oEvent.Param2 = types.UInt64(participant) oEvent.StrParam = types.NewString(joinMessage) - oEvent.Param3 = types.NewUInt32(uint32(len(totalParticipants))) + oEvent.Param3 = types.UInt64(len(totalParticipants)) // * Send the notification to the joining participant common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, []uint64{uint64(connection.PID())}) diff --git a/match-making/database/join_gathering_with_participants.go b/match-making/database/join_gathering_with_participants.go index f40984a..8f1e551 100644 --- a/match-making/database/join_gathering_with_participants.go +++ b/match-making/database/join_gathering_with_participants.go @@ -5,11 +5,11 @@ import ( "slices" "github.com/PretendoNetwork/nex-go/v2" - "github.com/PretendoNetwork/nex-protocols-go/v2/match-making/constants" "github.com/PretendoNetwork/nex-go/v2/types" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals" "github.com/PretendoNetwork/nex-protocols-common-go/v2/match-making/tracking" match_making "github.com/PretendoNetwork/nex-protocols-go/v2/match-making" + "github.com/PretendoNetwork/nex-protocols-go/v2/match-making/constants" notifications "github.com/PretendoNetwork/nex-protocols-go/v2/notifications" notifications_types "github.com/PretendoNetwork/nex-protocols-go/v2/notifications/types" pqextended "github.com/PretendoNetwork/pq-extended" @@ -30,7 +30,7 @@ func JoinGatheringWithParticipants(manager *common_globals.MatchmakingManager, g } } - if uint32(len(oldParticipants) + 1 + len(additionalParticipants)) > maxParticipants { + if uint32(len(oldParticipants)+1+len(additionalParticipants)) > maxParticipants { return 0, nex.NewError(nex.ResultCodes.RendezVous.SessionFull, "change_error") } @@ -71,7 +71,7 @@ func JoinGatheringWithParticipants(manager *common_globals.MatchmakingManager, g var participantJoinedTargets []uint64 // * When the VerboseParticipants or the VerboseParticipantsEx flags are set, all participant notification events are sent to everyone - if flags & (match_making.GatheringFlags.VerboseParticipants | match_making.GatheringFlags.VerboseParticipantsEx) != 0 { + if flags&(match_making.GatheringFlags.VerboseParticipants|match_making.GatheringFlags.VerboseParticipantsEx) != 0 { participantJoinedTargets = common_globals.RemoveDuplicates(participants) } else { participantJoinedTargets = []uint64{ownerPID} @@ -89,9 +89,9 @@ func JoinGatheringWithParticipants(manager *common_globals.MatchmakingManager, g oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID() - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) - oEvent.Param2 = types.NewUInt32(uint32(participant)) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) + oEvent.Param1 = types.UInt64(gatheringID) + oEvent.Param2 = types.UInt64(participant) // * Send the notification to the participant common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, []uint64{participant}) @@ -100,23 +100,23 @@ func JoinGatheringWithParticipants(manager *common_globals.MatchmakingManager, g for _, participant := range newParticipants { // * If the new participant is the same as the owner, then we are creating a new gathering. // * We don't need to send the new participant notification event in that case - if flags & (match_making.GatheringFlags.VerboseParticipants | match_making.GatheringFlags.VerboseParticipantsEx) != 0 || uint64(connection.PID()) != ownerPID { + if flags&(match_making.GatheringFlags.VerboseParticipants|match_making.GatheringFlags.VerboseParticipantsEx) != 0 || uint64(connection.PID()) != ownerPID { notificationCategory := notifications.NotificationCategories.Participation notificationSubtype := notifications.NotificationSubTypes.Participation.NewParticipant oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID() - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) - oEvent.Param2 = types.NewUInt32(uint32(participant)) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) + oEvent.Param1 = types.UInt64(gatheringID) + oEvent.Param2 = types.UInt64(participant) oEvent.StrParam = types.NewString(joinMessage) - oEvent.Param3 = types.NewUInt32(uint32(len(participants))) + oEvent.Param3 = types.UInt64(len(participants)) common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, participantJoinedTargets) } // * This flag also sends a recap of all currently connected players on the gathering to the participant that is connecting - if flags & match_making.GatheringFlags.VerboseParticipantsEx != 0 { + if flags&match_making.GatheringFlags.VerboseParticipantsEx != 0 { // TODO - Should this actually be deduplicated? for _, oldParticipant := range common_globals.RemoveDuplicates(oldParticipants) { notificationCategory := notifications.NotificationCategories.Participation @@ -124,11 +124,11 @@ func JoinGatheringWithParticipants(manager *common_globals.MatchmakingManager, g oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID() - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) - oEvent.Param1 = types.NewUInt32(gatheringID) - oEvent.Param2 = types.NewUInt32(uint32(oldParticipant)) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(notificationCategory, notificationSubtype)) + oEvent.Param1 = types.UInt64(gatheringID) + oEvent.Param2 = types.UInt64(oldParticipant) oEvent.StrParam = types.NewString(joinMessage) - oEvent.Param3 = types.NewUInt32(uint32(len(participants))) + oEvent.Param3 = types.UInt64(len(participants)) // * Send the notification to the joining participant common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, []uint64{participant}) diff --git a/match-making/database/migrate_gathering_ownership.go b/match-making/database/migrate_gathering_ownership.go index ff1c573..ec1072f 100644 --- a/match-making/database/migrate_gathering_ownership.go +++ b/match-making/database/migrate_gathering_ownership.go @@ -34,8 +34,8 @@ func MigrateGatheringOwnership(manager *common_globals.MatchmakingManager, conne oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = gathering.ID + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gathering.ID) common_globals.SendNotificationEvent(connection.Endpoint().(*nex.PRUDPEndPoint), oEvent, uniqueParticipants) return 0, nil @@ -62,8 +62,8 @@ func MigrateGatheringOwnership(manager *common_globals.MatchmakingManager, conne oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = gathering.ID - oEvent.Param2 = types.NewUInt32(uint32(newOwner)) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Param1 = types.UInt64(gathering.ID) + oEvent.Param2 = types.UInt64(newOwner) // TODO - StrParam doesn't have this value on some servers // * https://github.com/kinnay/NintendoClients/issues/101 diff --git a/match-making/protocol.go b/match-making/protocol.go index fb94a38..5ff4577 100644 --- a/match-making/protocol.go +++ b/match-making/protocol.go @@ -37,8 +37,8 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS matchmaking.gatherings ( id bigserial PRIMARY KEY, - owner_pid numeric(10), - host_pid numeric(10), + owner_pid numeric(20), + host_pid numeric(20), min_participants integer, max_participants integer, participation_policy bigint, @@ -49,7 +49,7 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma registered boolean NOT NULL DEFAULT true, type text NOT NULL DEFAULT '', started_time timestamp, - participants numeric(10)[] NOT NULL DEFAULT array[]::numeric(10)[] + participants numeric(20)[] NOT NULL DEFAULT array[]::numeric(20)[] )`) if err != nil { common_globals.Logger.Error(err.Error()) @@ -65,7 +65,7 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.register_gathering ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), gathering_id bigint )`) if err != nil { @@ -76,10 +76,10 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.join_gathering ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), gathering_id bigint, - new_participants numeric(10)[] NOT NULL DEFAULT array[]::numeric(10)[], - total_participants numeric(10)[] NOT NULL DEFAULT array[]::numeric(10)[] + new_participants numeric(20)[] NOT NULL DEFAULT array[]::numeric(20)[], + total_participants numeric(20)[] NOT NULL DEFAULT array[]::numeric(20)[] )`) if err != nil { common_globals.Logger.Error(err.Error()) @@ -89,9 +89,9 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.leave_gathering ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), gathering_id bigint, - total_participants numeric(10)[] NOT NULL DEFAULT array[]::numeric(10)[] + total_participants numeric(20)[] NOT NULL DEFAULT array[]::numeric(20)[] )`) if err != nil { common_globals.Logger.Error(err.Error()) @@ -101,9 +101,9 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.disconnect_gathering ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), gathering_id bigint, - total_participants numeric(10)[] NOT NULL DEFAULT array[]::numeric(10)[] + total_participants numeric(20)[] NOT NULL DEFAULT array[]::numeric(20)[] )`) if err != nil { common_globals.Logger.Error(err.Error()) @@ -113,7 +113,7 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.unregister_gathering ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), gathering_id bigint )`) if err != nil { @@ -124,10 +124,10 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.change_host ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), gathering_id bigint, - old_host_pid numeric(10), - new_host_pid numeric(10) + old_host_pid numeric(20), + new_host_pid numeric(20) )`) if err != nil { common_globals.Logger.Error(err.Error()) @@ -137,10 +137,10 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.change_owner ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), gathering_id bigint, - old_owner_pid numeric(10), - new_owner_pid numeric(10) + old_owner_pid numeric(20), + new_owner_pid numeric(20) )`) if err != nil { common_globals.Logger.Error(err.Error()) diff --git a/match-making/unregister_gathering.go b/match-making/unregister_gathering.go index 421fc68..9082565 100644 --- a/match-making/unregister_gathering.go +++ b/match-making/unregister_gathering.go @@ -43,7 +43,7 @@ func (commonProtocol *CommonProtocol) unregisterGathering(err error, packet nex. oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID().Copy().(types.PID) oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = idGathering + oEvent.Param1 = types.UInt64(idGathering) common_globals.SendNotificationEvent(endpoint, oEvent, common_globals.RemoveDuplicates(participants)) diff --git a/match-making/update_session_host.go b/match-making/update_session_host.go index 24e6744..5d98f0d 100644 --- a/match-making/update_session_host.go +++ b/match-making/update_session_host.go @@ -47,7 +47,7 @@ func (commonProtocol *CommonProtocol) updateSessionHost(err error, packet nex.Pa return nil, nexError } } else { - if uint32(gathering.Flags) & match_making.GatheringFlags.ParticipantsChangeOwner == 0 { + if uint32(gathering.Flags)&match_making.GatheringFlags.ParticipantsChangeOwner == 0 { commonProtocol.manager.Mutex.Unlock() return nil, nex.NewError(nex.ResultCodes.RendezVous.InvalidOperation, "change_error") } @@ -75,9 +75,9 @@ func (commonProtocol *CommonProtocol) updateSessionHost(err error, packet nex.Pa oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID() - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = gid - oEvent.Param2 = types.NewUInt32(uint32(connection.PID())) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gid) + oEvent.Param2 = types.UInt64(connection.PID()) // TODO - StrParam doesn't have this value on some servers // * https://github.com/kinnay/NintendoClients/issues/101 diff --git a/match-making/update_session_host_v1.go b/match-making/update_session_host_v1.go index 3cfa1b8..afc3459 100644 --- a/match-making/update_session_host_v1.go +++ b/match-making/update_session_host_v1.go @@ -35,7 +35,7 @@ func (commonProtocol *CommonProtocol) updateSessionHostV1(err error, packet nex. return nil, nex.NewError(nex.ResultCodes.RendezVous.PermissionDenied, "change_error") } - if uint32(gathering.Flags) & match_making.GatheringFlags.ParticipantsChangeOwner == 0 { + if uint32(gathering.Flags)&match_making.GatheringFlags.ParticipantsChangeOwner == 0 { nexError = database.UpdateSessionHost(commonProtocol.manager, uint32(gid), gathering.OwnerPID, connection.PID()) if nexError != nil { commonProtocol.manager.Mutex.Unlock() @@ -71,9 +71,9 @@ func (commonProtocol *CommonProtocol) updateSessionHostV1(err error, packet nex. oEvent := notifications_types.NewNotificationEvent() oEvent.PIDSource = connection.PID() - oEvent.Type = types.NewUInt32(notifications.BuildNotificationType(category, subtype)) - oEvent.Param1 = gid - oEvent.Param2 = types.NewUInt32(uint32(connection.PID())) // TODO - This assumes a legacy client. Will not work on the Switch + oEvent.Type = types.UInt32(notifications.BuildNotificationType(category, subtype)) + oEvent.Param1 = types.UInt64(gid) + oEvent.Param2 = types.UInt64(connection.PID()) // TODO - StrParam doesn't have this value on some servers // * https://github.com/kinnay/NintendoClients/issues/101 diff --git a/matchmake-extension/database/update_notification_data.go b/matchmake-extension/database/update_notification_data.go index df00d86..66f8c4a 100644 --- a/matchmake-extension/database/update_notification_data.go +++ b/matchmake-extension/database/update_notification_data.go @@ -2,8 +2,8 @@ package database import ( "github.com/PretendoNetwork/nex-go/v2" - notifications_types "github.com/PretendoNetwork/nex-protocols-go/v2/notifications/types" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals" + notifications_types "github.com/PretendoNetwork/nex-protocols-go/v2/notifications/types" ) // UpdateNotificationData updates the notification data of the specified user and type diff --git a/matchmake-extension/protocol.go b/matchmake-extension/protocol.go index 9e008df..a1d7f20 100644 --- a/matchmake-extension/protocol.go +++ b/matchmake-extension/protocol.go @@ -11,37 +11,37 @@ import ( ) type CommonProtocol struct { - endpoint nex.EndpointInterface - protocol matchmake_extension.Interface - manager *common_globals.MatchmakingManager - PersistentGatheringCreationMax int - CanJoinMatchmakeSession func(manager *common_globals.MatchmakingManager, pid types.PID, matchmakeSession match_making_types.MatchmakeSession) *nex.Error - CleanupSearchMatchmakeSession func(matchmakeSession *match_making_types.MatchmakeSession) - CleanupMatchmakeSessionSearchCriterias func(searchCriterias types.List[match_making_types.MatchmakeSessionSearchCriteria]) - OnAfterOpenParticipation func(packet nex.PacketInterface, gid types.UInt32) - OnAfterCloseParticipation func(packet nex.PacketInterface, gid types.UInt32) - OnAfterCreateMatchmakeSession func(packet nex.PacketInterface, anyGathering match_making_types.GatheringHolder, message types.String, participationCount types.UInt16) - OnAfterGetSimplePlayingSession func(packet nex.PacketInterface, listPID types.List[types.PID], includeLoginUser types.Bool) - OnAfterAutoMatchmakePostpone func(packet nex.PacketInterface, anyGathering match_making_types.GatheringHolder, message types.String) - OnAfterAutoMatchmakeWithParamPostpone func(packet nex.PacketInterface, autoMatchmakeParam match_making_types.AutoMatchmakeParam) - OnAfterAutoMatchmakeWithSearchCriteriaPostpone func(packet nex.PacketInterface, lstSearchCriteria types.List[match_making_types.MatchmakeSessionSearchCriteria], anyGathering match_making_types.GatheringHolder, strMessage types.String) - OnAfterGetPlayingSession func(packet nex.PacketInterface, lstPID types.List[types.PID]) - OnAfterCreateCommunity func(packet nex.PacketInterface, community match_making_types.PersistentGathering, strMessage types.String) - OnAfterFindCommunityByGatheringID func(packet nex.PacketInterface, lstGID types.List[types.UInt32]) - OnAfterFindOfficialCommunity func(packet nex.PacketInterface, isAvailableOnly types.Bool, resultRange types.ResultRange) - OnAfterFindCommunityByParticipant func(packet nex.PacketInterface, pid types.PID, resultRange types.ResultRange) - OnAfterUpdateProgressScore func(packet nex.PacketInterface, gid types.UInt32, progressScore types.UInt8) - OnAfterCreateMatchmakeSessionWithParam func(packet nex.PacketInterface, createMatchmakeSessionParam match_making_types.CreateMatchmakeSessionParam) - OnAfterUpdateApplicationBuffer func(packet nex.PacketInterface, gid types.UInt32, applicationBuffer types.Buffer) - OnAfterJoinMatchmakeSession func(packet nex.PacketInterface, gid types.UInt32, strMessage types.String) - OnAfterJoinMatchmakeSessionWithParam func(packet nex.PacketInterface, joinMatchmakeSessionParam match_making_types.JoinMatchmakeSessionParam) - OnAfterModifyCurrentGameAttribute func(packet nex.PacketInterface, gid types.UInt32, attribIndex types.UInt32, newValue types.UInt32) - OnAfterBrowseMatchmakeSession func(packet nex.PacketInterface, searchCriteria match_making_types.MatchmakeSessionSearchCriteria, resultRange types.ResultRange) - OnAfterJoinMatchmakeSessionEx func(packet nex.PacketInterface, gid types.UInt32, strMessage types.String, dontCareMyBlockList types.Bool, participationCount types.UInt16) - OnAfterGetSimpleCommunity func(packet nex.PacketInterface, gatheringIDList types.List[types.UInt32]) - OnAfterUpdateNotificationData func(packet nex.PacketInterface, uiType types.UInt32, uiParam1 types.UInt32, uiParam2 types.UInt32, strParam types.String) - OnAfterGetFriendNotificationData func(packet nex.PacketInterface, uiType types.Int32) - OnAfterGetlstFriendNotificationData func(packet nex.PacketInterface, lstTypes types.List[types.UInt32]) + endpoint nex.EndpointInterface + protocol matchmake_extension.Interface + manager *common_globals.MatchmakingManager + PersistentGatheringCreationMax int + CanJoinMatchmakeSession func(manager *common_globals.MatchmakingManager, pid types.PID, matchmakeSession match_making_types.MatchmakeSession) *nex.Error + CleanupSearchMatchmakeSession func(matchmakeSession *match_making_types.MatchmakeSession) + CleanupMatchmakeSessionSearchCriterias func(searchCriterias types.List[match_making_types.MatchmakeSessionSearchCriteria]) + OnAfterOpenParticipation func(packet nex.PacketInterface, gid types.UInt32) + OnAfterCloseParticipation func(packet nex.PacketInterface, gid types.UInt32) + OnAfterCreateMatchmakeSession func(packet nex.PacketInterface, anyGathering match_making_types.GatheringHolder, message types.String, participationCount types.UInt16) + OnAfterGetSimplePlayingSession func(packet nex.PacketInterface, listPID types.List[types.PID], includeLoginUser types.Bool) + OnAfterAutoMatchmakePostpone func(packet nex.PacketInterface, anyGathering match_making_types.GatheringHolder, message types.String) + OnAfterAutoMatchmakeWithParamPostpone func(packet nex.PacketInterface, autoMatchmakeParam match_making_types.AutoMatchmakeParam) + OnAfterAutoMatchmakeWithSearchCriteriaPostpone func(packet nex.PacketInterface, lstSearchCriteria types.List[match_making_types.MatchmakeSessionSearchCriteria], anyGathering match_making_types.GatheringHolder, strMessage types.String) + OnAfterGetPlayingSession func(packet nex.PacketInterface, lstPID types.List[types.PID]) + OnAfterCreateCommunity func(packet nex.PacketInterface, community match_making_types.PersistentGathering, strMessage types.String) + OnAfterFindCommunityByGatheringID func(packet nex.PacketInterface, lstGID types.List[types.UInt32]) + OnAfterFindOfficialCommunity func(packet nex.PacketInterface, isAvailableOnly types.Bool, resultRange types.ResultRange) + OnAfterFindCommunityByParticipant func(packet nex.PacketInterface, pid types.PID, resultRange types.ResultRange) + OnAfterUpdateProgressScore func(packet nex.PacketInterface, gid types.UInt32, progressScore types.UInt8) + OnAfterCreateMatchmakeSessionWithParam func(packet nex.PacketInterface, createMatchmakeSessionParam match_making_types.CreateMatchmakeSessionParam) + OnAfterUpdateApplicationBuffer func(packet nex.PacketInterface, gid types.UInt32, applicationBuffer types.Buffer) + OnAfterJoinMatchmakeSession func(packet nex.PacketInterface, gid types.UInt32, strMessage types.String) + OnAfterJoinMatchmakeSessionWithParam func(packet nex.PacketInterface, joinMatchmakeSessionParam match_making_types.JoinMatchmakeSessionParam) + OnAfterModifyCurrentGameAttribute func(packet nex.PacketInterface, gid types.UInt32, attribIndex types.UInt32, newValue types.UInt32) + OnAfterBrowseMatchmakeSession func(packet nex.PacketInterface, searchCriteria match_making_types.MatchmakeSessionSearchCriteria, resultRange types.ResultRange) + OnAfterJoinMatchmakeSessionEx func(packet nex.PacketInterface, gid types.UInt32, strMessage types.String, dontCareMyBlockList types.Bool, participationCount types.UInt16) + OnAfterGetSimpleCommunity func(packet nex.PacketInterface, gatheringIDList types.List[types.UInt32]) + OnAfterUpdateNotificationData func(packet nex.PacketInterface, uiType types.UInt32, uiParam1 types.UInt64, uiParam2 types.UInt64, strParam types.String) + OnAfterGetFriendNotificationData func(packet nex.PacketInterface, uiType types.Int32) + OnAfterGetlstFriendNotificationData func(packet nex.PacketInterface, lstTypes types.List[types.UInt32]) } // SetDatabase defines the matchmaking manager to be used by the common protocol @@ -93,7 +93,7 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS matchmaking.community_participations ( id bigserial PRIMARY KEY, - user_pid numeric(10), + user_pid numeric(20), gathering_id bigint, participation_count bigint, UNIQUE (user_pid, gathering_id) @@ -105,10 +105,10 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS matchmaking.notifications ( id bigserial PRIMARY KEY, - source_pid numeric(10), + source_pid numeric(20), type bigint, - param_1 bigint, - param_2 bigint, + param_1 numeric(20), + param_2 numeric(20), param_str text, active boolean NOT NULL DEFAULT true, UNIQUE (source_pid, type) @@ -121,7 +121,7 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.participate_community ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), community_gid bigint, gathering_id bigint, participation_count bigint @@ -134,7 +134,7 @@ func (commonProtocol *CommonProtocol) SetManager(manager *common_globals.Matchma _, err = manager.Database.Exec(`CREATE TABLE IF NOT EXISTS tracking.notification_data ( id bigserial PRIMARY KEY, date timestamp, - source_pid numeric(10), + source_pid numeric(20), type bigint, param_1 bigint, param_2 bigint, @@ -165,8 +165,8 @@ func NewCommonProtocol(protocol matchmake_extension.Interface) *CommonProtocol { endpoint := protocol.Endpoint().(*nex.PRUDPEndPoint) commonProtocol := &CommonProtocol{ - endpoint: endpoint, - protocol: protocol, + endpoint: endpoint, + protocol: protocol, PersistentGatheringCreationMax: 4, // * Default of 4 active persistent gatherings per user } diff --git a/matchmake-extension/update_notification_data.go b/matchmake-extension/update_notification_data.go index 96ff6e4..3c1d5e5 100644 --- a/matchmake-extension/update_notification_data.go +++ b/matchmake-extension/update_notification_data.go @@ -13,7 +13,7 @@ import ( notifications_types "github.com/PretendoNetwork/nex-protocols-go/v2/notifications/types" ) -func (commonProtocol *CommonProtocol) updateNotificationData(err error, packet nex.PacketInterface, callID uint32, uiType types.UInt32, uiParam1 types.UInt32, uiParam2 types.UInt32, strParam types.String) (*nex.RMCMessage, *nex.Error) { +func (commonProtocol *CommonProtocol) updateNotificationData(err error, packet nex.PacketInterface, callID uint32, uiType types.UInt32, uiParam1 types.UInt64, uiParam2 types.UInt64, strParam types.String) (*nex.RMCMessage, *nex.Error) { if err != nil { common_globals.Logger.Error(err.Error()) return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, err.Error()) diff --git a/nat-traversal/request_probe_initiation_ext.go b/nat-traversal/request_probe_initiation_ext.go index c94def2..b51a3fc 100644 --- a/nat-traversal/request_probe_initiation_ext.go +++ b/nat-traversal/request_probe_initiation_ext.go @@ -49,10 +49,15 @@ func (commonProtocol *CommonProtocol) requestProbeInitiationExt(err error, packe var messagePacket nex.PRUDPPacketInterface - if target.DefaultPRUDPVersion == 0 { + switch target.DefaultPRUDPVersion { + case 0: messagePacket, _ = nex.NewPRUDPPacketV0(server, target, nil) - } else { + case 1: messagePacket, _ = nex.NewPRUDPPacketV1(server, target, nil) + case 2: + messagePacket, _ = nex.NewPRUDPPacketLite(server, target, nil) + default: + common_globals.Logger.Errorf("PRUDP version %d is not supported", target.DefaultPRUDPVersion) } messagePacket.SetType(constants.DataPacket) diff --git a/ticket-granting/generate_ticket.go b/ticket-granting/generate_ticket.go index 15863cb..677e42f 100644 --- a/ticket-granting/generate_ticket.go +++ b/ticket-granting/generate_ticket.go @@ -8,12 +8,15 @@ import ( common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals" ) -func generateTicket(source, target *nex.Account, sessionKeyLength int, endpoint *nex.PRUDPEndPoint) ([]byte, *nex.Error) { +func generateTicket(source, target *nex.Account, sourceKey []byte, sessionKeyLength int, endpoint *nex.PRUDPEndPoint) ([]byte, *nex.Error) { if source == nil || target == nil { return []byte{}, nex.NewError(nex.ResultCodes.Authentication.Unknown, "Source or target account is nil") } - sourceKey := nex.DeriveKerberosKey(source.PID, []byte(source.Password)) + if sourceKey == nil { + sourceKey = nex.DeriveKerberosKey(source.PID, []byte(source.Password)) + } + targetKey := nex.DeriveKerberosKey(target.PID, []byte(target.Password)) sessionKey := make([]byte, sessionKeyLength) diff --git a/ticket-granting/login.go b/ticket-granting/login.go index 2c9a127..b326385 100644 --- a/ticket-granting/login.go +++ b/ticket-granting/login.go @@ -15,6 +15,7 @@ func (commonProtocol *CommonProtocol) login(err error, packet nex.PacketInterfac connection := packet.Sender().(*nex.PRUDPConnection) endpoint := connection.Endpoint().(*nex.PRUDPEndPoint) + server := endpoint.Server var errorCode *nex.Error @@ -33,9 +34,14 @@ func (commonProtocol *CommonProtocol) login(err error, packet nex.PacketInterfac targetAccount, errorCode = endpoint.AccountDetailsByUsername(commonProtocol.SecureServerAccount.Username) } + if errorCode == nil && sourceAccount.RequiresTokenAuth { + common_globals.Logger.Error("Source account requires token authentication") + errorCode = nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, "Source account requires token authentication") + } + var encryptedTicket []byte if errorCode == nil { - encryptedTicket, errorCode = generateTicket(sourceAccount, targetAccount, commonProtocol.SessionKeyLength, endpoint) + encryptedTicket, errorCode = generateTicket(sourceAccount, targetAccount, nil, commonProtocol.SessionKeyLength, endpoint) } var retval types.QResult @@ -53,15 +59,14 @@ func (commonProtocol *CommonProtocol) login(err error, packet nex.PacketInterfac pbufResponse = types.NewBuffer(encryptedTicket) strReturnMsg = commonProtocol.BuildName.Copy().(types.String) - specialProtocols := types.NewList[types.UInt8]() - specialProtocols = commonProtocol.SpecialProtocols + specialProtocols := types.List[types.UInt8](commonProtocol.SpecialProtocols) pConnectionData.StationURL = commonProtocol.SecureStationURL pConnectionData.SpecialProtocols = specialProtocols pConnectionData.StationURLSpecialProtocols = commonProtocol.StationURLSpecialProtocols pConnectionData.Time = types.NewDateTime(0).Now() - if endpoint.LibraryVersions().Main.GreaterOrEqual("v3.5.0") { + if server.LibraryVersions.Main.GreaterOrEqual("3.5.0") { pConnectionData.StructureVersion = 1 } } diff --git a/ticket-granting/login_ex.go b/ticket-granting/login_ex.go index 3a3db0c..fc72151 100644 --- a/ticket-granting/login_ex.go +++ b/ticket-granting/login_ex.go @@ -1,6 +1,8 @@ package ticket_granting import ( + "encoding/hex" + "github.com/PretendoNetwork/nex-go/v2" "github.com/PretendoNetwork/nex-go/v2/types" common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals" @@ -20,6 +22,7 @@ func (commonProtocol *CommonProtocol) loginEx(err error, packet nex.PacketInterf connection := packet.Sender().(*nex.PRUDPConnection) endpoint := connection.Endpoint().(*nex.PRUDPEndPoint) + server := endpoint.Server sourceAccount, errorCode := endpoint.AccountDetailsByUsername(string(strUserName)) @@ -33,9 +36,14 @@ func (commonProtocol *CommonProtocol) loginEx(err error, packet nex.PacketInterf targetAccount, errorCode = endpoint.AccountDetailsByUsername(commonProtocol.SecureServerAccount.Username) } + var sourceKey []byte + if errorCode == nil && sourceAccount.RequiresTokenAuth { + sourceKey, errorCode = commonProtocol.SourceKeyFromToken(sourceAccount, oExtraData) + } + var encryptedTicket []byte if errorCode == nil { - encryptedTicket, errorCode = generateTicket(sourceAccount, targetAccount, commonProtocol.SessionKeyLength, endpoint) + encryptedTicket, errorCode = generateTicket(sourceAccount, targetAccount, sourceKey, commonProtocol.SessionKeyLength, endpoint) } var retval types.QResult @@ -43,6 +51,7 @@ func (commonProtocol *CommonProtocol) loginEx(err error, packet nex.PacketInterf pbufResponse := types.NewBuffer([]byte{}) pConnectionData := types.NewRVConnectionData() strReturnMsg := types.NewString("") + pSourceKey := types.NewString("") // * If any errors are triggered, return them in %retval% if errorCode != nil { @@ -54,15 +63,18 @@ func (commonProtocol *CommonProtocol) loginEx(err error, packet nex.PacketInterf pbufResponse = types.NewBuffer(encryptedTicket) strReturnMsg = commonProtocol.BuildName.Copy().(types.String) - specialProtocols := types.NewList[types.UInt8]() - specialProtocols = commonProtocol.SpecialProtocols + if server.LibraryVersions.Main.GreaterOrEqual("4.0.0") && sourceKey != nil { + pSourceKey = types.String(hex.EncodeToString(sourceKey)) + } + + specialProtocols := types.List[types.UInt8](commonProtocol.SpecialProtocols) pConnectionData.StationURL = commonProtocol.SecureStationURL pConnectionData.SpecialProtocols = specialProtocols pConnectionData.StationURLSpecialProtocols = commonProtocol.StationURLSpecialProtocols pConnectionData.Time = types.NewDateTime(0).Now() - if endpoint.LibraryVersions().Main.GreaterOrEqual("v3.5.0") { + if server.LibraryVersions.Main.GreaterOrEqual("3.5.0") { pConnectionData.StructureVersion = 1 } } @@ -75,6 +87,10 @@ func (commonProtocol *CommonProtocol) loginEx(err error, packet nex.PacketInterf pConnectionData.WriteTo(rmcResponseStream) strReturnMsg.WriteTo(rmcResponseStream) + if server.LibraryVersions.Main.GreaterOrEqual("4.0.0") { + pSourceKey.WriteTo(rmcResponseStream) + } + rmcResponseBody := rmcResponseStream.Bytes() rmcResponse := nex.NewRMCSuccess(endpoint, rmcResponseBody) diff --git a/ticket-granting/protocol.go b/ticket-granting/protocol.go index 535cd07..3d5a9bb 100644 --- a/ticket-granting/protocol.go +++ b/ticket-granting/protocol.go @@ -18,6 +18,7 @@ type CommonProtocol struct { allowInsecureLoginMethod bool SessionKeyLength int // TODO - Use server SessionKeyLength? SecureServerAccount *nex.Account + SourceKeyFromToken func(sourceAccount *nex.Account, loginData types.DataHolder) ([]byte, *nex.Error) ValidateLoginData func(pid types.PID, loginData types.DataHolder) *nex.Error OnAfterLogin func(packet nex.PacketInterface, strUserName types.String) OnAfterLoginEx func(packet nex.PacketInterface, strUserName types.String, oExtraData types.DataHolder) diff --git a/ticket-granting/request_ticket.go b/ticket-granting/request_ticket.go index 68ee740..fbb1bf9 100644 --- a/ticket-granting/request_ticket.go +++ b/ticket-granting/request_ticket.go @@ -15,6 +15,9 @@ func (commonProtocol *CommonProtocol) requestTicket(err error, packet nex.Packet connection := packet.Sender() endpoint := connection.Endpoint().(*nex.PRUDPEndPoint) + server := endpoint.Server + + var errorCode *nex.Error sourceAccount, errorCode := endpoint.AccountDetailsByPID(idSource) @@ -23,14 +26,20 @@ func (commonProtocol *CommonProtocol) requestTicket(err error, packet nex.Packet targetAccount, errorCode = endpoint.AccountDetailsByPID(idTarget) } + if errorCode == nil && sourceAccount.RequiresTokenAuth { + common_globals.Logger.Error("Source account requires token authentication") + errorCode = nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, "Source account requires token authentication") + } + var encryptedTicket []byte if errorCode == nil { - encryptedTicket, errorCode = generateTicket(sourceAccount, targetAccount, commonProtocol.SessionKeyLength, endpoint) + encryptedTicket, errorCode = generateTicket(sourceAccount, targetAccount, nil, commonProtocol.SessionKeyLength, endpoint) } // * If any errors are triggered, return them in %retval% retval := types.NewQResultSuccess(nex.ResultCodes.Core.Unknown) bufResponse := types.NewBuffer(encryptedTicket) + pSourceKey := types.NewString("") if errorCode != nil { retval = types.NewQResultError(errorCode.ResultCode) @@ -42,6 +51,10 @@ func (commonProtocol *CommonProtocol) requestTicket(err error, packet nex.Packet retval.WriteTo(rmcResponseStream) bufResponse.WriteTo(rmcResponseStream) + if server.LibraryVersions.Main.GreaterOrEqual("4.0.0") { + pSourceKey.WriteTo(rmcResponseStream) + } + rmcResponseBody := rmcResponseStream.Bytes() rmcResponse := nex.NewRMCSuccess(endpoint, rmcResponseBody)