/// <summary> /// Attempts to log in to the server. /// Must be authenticated. /// </summary> /// <param name="displayName">Display name to log in with</param> /// <param name="useServerDisplayName">Use the server's copy of the user's display name if it has one</param> /// <param name="acceptingTrades">Whether to accept trades from other users</param> public void SendLogin(string displayName, bool useServerDisplayName = false, bool acceptingTrades = true) { if (!authenticator.Authenticated) { return; } // Create and pack a new LoginPacket LoginPacket packet = new LoginPacket { SessionId = authenticator.SessionId, DisplayName = displayName, UseServerDisplayName = useServerDisplayName, AcceptingTrades = acceptingTrades }; Any packedPacket = ProtobufPacketHelper.Pack(packet); RaiseLogEntry(new LogEventArgs("Sending LoginPacket", LogLevel.DEBUG)); // Send it on its way netClient.Send(MODULE_NAME, packedPacket.ToByteArray()); }
/// <summary> /// Handles incoming <see cref="LoginPacket"/>s, attempting to log in users. /// </summary> /// <param name="connectionId">Original connection ID</param> /// <param name="packet">Incoming packet</param> /// <exception cref="UserNoLongerExistsException">User no longer exists for some reason even though we just checked like a second ago</exception> private void handleLoginPacket(string connectionId, LoginPacket packet) { // Make sure the client is authenticated if (!authenticator.IsAuthenticated(connectionId, packet.SessionId)) { RaiseLogEntry(new LogEventArgs(string.Format("Failed login attempt for session {0}: Invalid session", packet.SessionId))); // Fail the login attempt due to an invalid session sendFailedLoginResponsePacket(connectionId, LoginFailureReason.SessionId, "Session is not valid, it may have expired. Try reconnecting."); // Stop here return; } // Try get the username from their session if (!authenticator.TryGetUsername(connectionId, packet.SessionId, out string username)) { RaiseLogEntry(new LogEventArgs(string.Format("Failed login attempt for session {0}: Couldn't get username", packet.SessionId))); // Fail the login attempt due to an invalid session/username sendFailedLoginResponsePacket(connectionId, LoginFailureReason.InternalServerError, "Server failed to get the username associated with the session. Try reconnecting."); // Stop here return; } // Passed authentication checks, time to accept the login attempt // Try to get the user by their username if (TryGetUserUuid(username, out string uuid)) { // Try to log them in if (!TryLogIn(uuid)) { // This shouldn't happen because we just got their UUID but ok. throw new UserNoLongerExistsException(uuid); } } else { // Otherwise create a new user uuid = CreateUser(username, packet.DisplayName, true); } // Check if they want to use the display name stored on the server string displayName = packet.DisplayName; if (packet.UseServerDisplayName) { // Try to get the display name stored server-side if (!TryGetDisplayName(uuid, out displayName)) { // This should never happen because we just made sure that the user existed no more than 30 lines ago, but just in case... throw new UserNoLongerExistsException(uuid); } } else { // Check the length of their username without markup if (TextHelper.StripRichText(packet.DisplayName).Length > maxDisplayNameLength) { // Fail the login attempt due to display name length sendFailedLoginResponsePacket(connectionId, LoginFailureReason.DisplayName, "Display name is too long."); // Stop here return; } // Update the user's display name on the server with the one they've provided UpdateUser(uuid, TextHelper.SanitiseRichText(packet.DisplayName)); } // Set whether they are accepting trades UpdateUser(uuid, acceptingTrades: packet.AcceptingTrades); // Add their UUID/Session ID pair to connectedUsers lock (connectedUsersLock) { // Remove an existing session, if it exists connectedUsers.Remove(connectionId); // Add this session with the freshly-logged in UUID connectedUsers.Add(connectionId, uuid); } // Log the event RaiseLogEntry(new LogEventArgs(string.Format("User {0} successfully logged in as \"{1}\" (SessionID: {2}, UUID: {3})", username, displayName, packet.SessionId, uuid))); // Send a successful login response sendSuccessfulLoginResponsePacket(connectionId, uuid, displayName); // Send a sync packet with the current user list sendSyncPacket(connectionId); // Raise the OnLogin event OnLogin?.Invoke(this, new ServerLoginEventArgs(connectionId, uuid)); }