Shorten event names, refactor, prepare compatibility verification
This commit is contained in:
@ -1,19 +1,23 @@
|
||||
package envoy.server.processors;
|
||||
|
||||
import static envoy.data.User.UserStatus.ONLINE;
|
||||
import static envoy.event.HandshakeRejection.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.persistence.NoResultException;
|
||||
|
||||
import envoy.data.LoginCredentials;
|
||||
import envoy.data.Message.MessageStatus;
|
||||
import envoy.data.User;
|
||||
import envoy.data.User.UserStatus;
|
||||
import envoy.event.HandshakeRejectionEvent;
|
||||
import envoy.event.MessageStatusChangeEvent;
|
||||
import envoy.server.data.Message;
|
||||
import envoy.event.HandshakeRejection;
|
||||
import envoy.event.MessageStatusChange;
|
||||
import envoy.server.Startup;
|
||||
import envoy.server.data.PersistenceManager;
|
||||
import envoy.server.data.User;
|
||||
import envoy.server.net.ConnectionManager;
|
||||
import envoy.server.net.ObjectWriteProxy;
|
||||
import envoy.util.EnvoyLog;
|
||||
@ -29,126 +33,98 @@ import envoy.util.EnvoyLog;
|
||||
* @author Maximilian Käfer
|
||||
* @since Envoy Server Standalone v0.1-alpha
|
||||
*/
|
||||
public class LoginCredentialProcessor implements ObjectProcessor<LoginCredentials> {
|
||||
public final class LoginCredentialProcessor implements ObjectProcessor<LoginCredentials> {
|
||||
|
||||
private final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
||||
private final ConnectionManager connectionManager = ConnectionManager.getInstance();
|
||||
|
||||
private static final Logger logger = EnvoyLog.getLogger(LoginCredentialProcessor.class);
|
||||
// private static final Pattern versionPattern =
|
||||
// Pattern.compile("v(?<major>\\d).(?<minor>\\d)(?:-(?<suffix>\\w+))?");
|
||||
|
||||
@Override
|
||||
public void process(LoginCredentials input, long socketID, ObjectWriteProxy writeProxy) throws IOException {
|
||||
public void process(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
|
||||
|
||||
// Cache this write proxy for user-independant notifications
|
||||
UserStatusChangeProcessor.setWriteProxy(writeProxy);
|
||||
logger.info(String.format("Received login credentials %s from socket ID %d", input, socketID));
|
||||
|
||||
envoy.server.data.User user = getUser(input, socketID, writeProxy);
|
||||
|
||||
// Not logged in successfully
|
||||
if (user == null) {
|
||||
logger.info("Rejecting handshake on socket " + socketID);
|
||||
return;
|
||||
// TODO: Verify compatibility
|
||||
if (Startup.MIN_CLIENT_VERSION.compareTo(credentials.getClientVersion()) <= 0
|
||||
&& Startup.MAX_CLIENT_VERSION.compareTo(credentials.getClientVersion()) >= 0) {
|
||||
// writeProxy.write(socketID, new HandshakeRejectionEvent("Wrong version"));
|
||||
// return;
|
||||
}
|
||||
|
||||
// Acquire a user object (or reject the handshake if that's impossible)
|
||||
User user = null;
|
||||
if (!credentials.isRegistration()) {
|
||||
try {
|
||||
user = persistenceManager.getUserByName(credentials.getIdentifier());
|
||||
|
||||
// Checking if user is already online
|
||||
if (connectionManager.isOnline(user.getID())) {
|
||||
logger.warning(user + " is already online!");
|
||||
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
|
||||
return;
|
||||
}
|
||||
// Evaluating the correctness of the password hash
|
||||
if (!Arrays.equals(credentials.getPasswordHash(), user.getPasswordHash())) {
|
||||
logger.info(user + " has entered the wrong password.");
|
||||
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
|
||||
return;
|
||||
}
|
||||
} catch (NoResultException e) {
|
||||
logger.info("The requested user does not exist.");
|
||||
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// Checking that no user already has this identifier
|
||||
PersistenceManager.getInstance().getUserByName(credentials.getIdentifier());
|
||||
|
||||
// This code only gets executed if this user already exists
|
||||
logger.info("The requested user already exists.");
|
||||
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
|
||||
return;
|
||||
} catch (NoResultException e) {
|
||||
// Creation of a new user
|
||||
user = new User();
|
||||
user.setName(credentials.getIdentifier());
|
||||
user.setLastSeen(LocalDateTime.now());
|
||||
user.setStatus(ONLINE);
|
||||
user.setPasswordHash(credentials.getPasswordHash());
|
||||
user.setContacts(new HashSet<>());
|
||||
persistenceManager.addContact(user);
|
||||
logger.info("Registered new " + user);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(user + " successfully authenticated.");
|
||||
|
||||
connectionManager.registerUser(user.getID(), socketID);
|
||||
|
||||
// Notifies contacts of this users online-going and updates his status in the
|
||||
// database
|
||||
user.setStatus(UserStatus.ONLINE);
|
||||
// Change status and notify contacts about it
|
||||
user.setStatus(ONLINE);
|
||||
UserStatusChangeProcessor.updateUserStatus(user);
|
||||
|
||||
// Complete handshake
|
||||
logger.fine("Sending user...");
|
||||
// Complete the handshake
|
||||
writeProxy.write(socketID, user.toCommon());
|
||||
logger.fine("Acquiring pending messages for the client...");
|
||||
List<Message> pendingMessages = PersistenceManager.getInstance().getPendingMessages(user);
|
||||
for (Message msg : pendingMessages)
|
||||
|
||||
final var pendingMessages = PersistenceManager.getInstance().getPendingMessages(user);
|
||||
logger.fine("Sending " + pendingMessages.size() + " pending messages to " + user + "...");
|
||||
for (var msg : pendingMessages) {
|
||||
final var msgCommon = msg.toCommon();
|
||||
if (msg.getStatus() == MessageStatus.SENT) {
|
||||
logger.info("Sending message " + msg.toCommon());
|
||||
writeProxy.write(socketID, msg.toCommon());
|
||||
msg.setReceivedDate(new Date());
|
||||
msg.setStatus(MessageStatus.RECEIVED);
|
||||
if (connectionManager.isOnline(msg.getSender().getID())) {
|
||||
var evt = new MessageStatusChangeEvent(msg.toCommon());
|
||||
logger.info("Sending messageStatusChangeEvent to sender " + evt);
|
||||
writeProxy.write(connectionManager.getSocketID(msg.getSender().getID()), evt);
|
||||
}
|
||||
writeProxy.write(socketID, msgCommon);
|
||||
msg.received();
|
||||
if (connectionManager.isOnline(msg.getSender().getID()))
|
||||
writeProxy.write(connectionManager.getSocketID(msg.getSender().getID()), new MessageStatusChange(msgCommon));
|
||||
PersistenceManager.getInstance().updateMessage(msg);
|
||||
} else {
|
||||
var evt = new MessageStatusChangeEvent(msg.toCommon());
|
||||
logger.info("Sending messageStatusChangeEvent " + evt);
|
||||
writeProxy.write(socketID, evt);
|
||||
}
|
||||
} else writeProxy.write(socketID, new MessageStatusChange(msgCommon));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<LoginCredentials> getInputClass() { return LoginCredentials.class; }
|
||||
|
||||
private envoy.server.data.User getUser(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
|
||||
return credentials.isRegistration() ? newUser(credentials, socketID, writeProxy) : checkForExistingUser(credentials, socketID, writeProxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param credentials the input to evaluate
|
||||
* @param socketID the socket ID at which the client performing the handshake
|
||||
* is connected
|
||||
* @param writeProxy the {@link ObjectWriteProxy} to use if login was not
|
||||
* successful
|
||||
* @return the database user matching the login credentials
|
||||
* @throws IOException if sending the failed login back to the client failed
|
||||
* @since Envoy Server Standalone v0.1-alpha
|
||||
*/
|
||||
private envoy.server.data.User checkForExistingUser(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
|
||||
try {
|
||||
envoy.server.data.User user = persistenceManager.getUserByName(credentials.getIdentifier());
|
||||
|
||||
// Checking if user is already online
|
||||
if (connectionManager.isOnline(user.getID())) {
|
||||
writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.INTERNAL_ERROR));
|
||||
return null;
|
||||
}
|
||||
// Evaluating the correctness of the password hash
|
||||
if (!Arrays.equals(credentials.getPasswordHash(), user.getPasswordHash())) {
|
||||
writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD_OR_USER));
|
||||
return null;
|
||||
}
|
||||
return user;
|
||||
} catch (NoResultException e) {
|
||||
// Checking if user exists
|
||||
writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.INTERNAL_ERROR));
|
||||
} catch (InputMismatchException e) {
|
||||
// Checking if the given password hash is correct
|
||||
writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD_OR_USER));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param credentials the credentials upon which to create the new {@link User}
|
||||
* @param socketID the socketID at which the client performing the handshake
|
||||
* is connected
|
||||
* @param writeProxy the write proxy used to notify the client about handshake
|
||||
* rejection
|
||||
* @return the newly created {@link User}
|
||||
* @throws IOException if sending the failed login back to the client failed
|
||||
* @since Envoy Server Standalone v0.1-alpha
|
||||
*/
|
||||
private envoy.server.data.User newUser(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
|
||||
try {
|
||||
// Checking that no user already has this identifier
|
||||
PersistenceManager.getInstance().getUserByName(credentials.getIdentifier());
|
||||
// this code only gets executed if this user already exists
|
||||
writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.INTERNAL_ERROR));
|
||||
return null;
|
||||
} catch (NoResultException e) {
|
||||
// Creation of a new user
|
||||
envoy.server.data.User user;
|
||||
user = new envoy.server.data.User();
|
||||
user.setName(credentials.getIdentifier());
|
||||
user.setLastSeen(new Date());
|
||||
user.setStatus(User.UserStatus.ONLINE);
|
||||
user.setPasswordHash(credentials.getPasswordHash());
|
||||
user.setContacts(new HashSet<>());
|
||||
persistenceManager.addContact(user);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user