Handle user connection and disconnection

This commit is contained in:
Yohan Simard 2020-12-16 11:51:31 +01:00
parent 6f6492e8c0
commit 965cfdbf19
2 changed files with 95 additions and 6 deletions

View file

@ -40,9 +40,9 @@ public class ConnectionListener {
private static class Acceptor extends Thread {
private boolean shouldStop = false;
NewConnectionCallback callback;
ErrorCallback errorCallback;
ServerSocket server;
private final NewConnectionCallback callback;
private final ErrorCallback errorCallback;
private ServerSocket server;
public Acceptor(NewConnectionCallback callback, ErrorCallback errorCallback) {
this.callback = callback;

View file

@ -1,10 +1,12 @@
package fr.insa.clavardator.users;
import fr.insa.clavardator.db.DatabaseController;
import fr.insa.clavardator.network.ConnectionListener;
import fr.insa.clavardator.network.NetDiscoverer;
import fr.insa.clavardator.util.ErrorCallback;
import fr.insa.clavardator.util.Log;
import java.beans.PropertyChangeEvent;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
@ -21,6 +23,7 @@ public class UserList {
private final DatabaseController db = new DatabaseController();
private final NetDiscoverer netDiscoverer = new NetDiscoverer();
private final ConnectionListener connectionListener = new ConnectionListener();
public UserList() {
}
@ -35,17 +38,24 @@ public class UserList {
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
int id = getIdFromIp(ipAddr);
Log.v(this.getClass().getSimpleName(), "Discovered new user: " + id);
// If already connected, do not modify
if (activeUsers.containsKey(id)) {
return;
}
PeerUser user = inactiveUsers.get(id);
if (user == null) {
// Username is set on TCP connection start
user = new PeerUser(id, "");
inactiveUsers.put(id, user);
}
PeerUser finalUser = user;
user.connect(ipAddr, () -> notifyConnectionObservers(finalUser), errorCallback);
user.connect(ipAddr, () -> {
notifyConnectionObservers(finalUser);
finalUser.addObserver(evt -> userChangeObserver(finalUser, evt));
}, errorCallback);
}, errorCallback);
}
@ -56,10 +66,89 @@ public class UserList {
Throwable::printStackTrace);
}
private int getIdFromIp(InetAddress ipAddr) {
return ipAddr.hashCode();
public void startUserListening(ErrorCallback errorCallback) {
connectionListener.acceptConnection(clientSocket -> {
int id = getIdFromIp(clientSocket.getInetAddress());
Log.v(this.getClass().getSimpleName(), "new connection from user: " + id);
// If already connected, warn and return
if (activeUsers.containsKey(id)) {
Log.w(getClass().getSimpleName(), "An already connected user tried to initiate a new connection: user id " + id);
return;
}
// Get the user if already existing
PeerUser user = inactiveUsers.get(id);
// else create it
if (user == null) {
// Username is set on TCP connection start
user = new PeerUser(id, "");
inactiveUsers.put(id, user);
}
PeerUser finalUser = user;
user.connect(clientSocket, () -> {
notifyConnectionObservers(finalUser);
finalUser.addObserver(evt -> userChangeObserver(finalUser, evt));
}, errorCallback);
}, errorCallback);
}
private void userChangeObserver(PeerUser user, PropertyChangeEvent evt) {
int id = user.id;
if (evt.getPropertyName().equals("state")) {
PeerUser.State oldState = (PeerUser.State) evt.getOldValue();
PeerUser.State newState = (PeerUser.State) evt.getNewValue();
if ((oldState == PeerUser.State.DISCONNECTED || oldState == PeerUser.State.CONNECTING) &&
newState == PeerUser.State.CONNECTED) {
// Connection handling
if (!inactiveUsers.containsKey(id)) {
if (activeUsers.containsKey(id)) {
Log.e(getClass().getSimpleName(), "Tried to set state CONNECTED on an already connected user: user id " + id);
return;
} else {
Log.e(getClass().getSimpleName(), "Tried to set state CONNECTED on an unknown user: user id " + id);
return;
}
}
inactiveUsers.remove(id);
activeUsers.put(id, user);
notifyConnectionObservers(user);
} else if (oldState == PeerUser.State.CONNECTED &&
(newState == PeerUser.State.DISCONNECTED || newState == PeerUser.State.CONNECTING)) {
// Disconnection
if (!activeUsers.containsKey(id)) {
if (inactiveUsers.containsKey(id)) {
Log.e(getClass().getSimpleName(), "Tried to set state DISCONNECTED on an already disconnected user: user id " + id);
return;
} else {
Log.e(getClass().getSimpleName(), "Tried to set state DISCONNECTED on an unknown user: user id " + id);
return;
}
}
activeUsers.remove(id);
inactiveUsers.put(id, user);
notifyDisconnectionObservers(user);
}
}
}
private int getIdFromIp(InetAddress ipAddr) {
byte[] addr = ipAddr.getAddress();
int id = 0;
for (byte b : addr) {
id = (id << 8) + b;
}
return id;
}
public void addActiveUsersObserver(UserConnectionCallback connectionCallback, UserDisconnectionCallback disconnectionCallback) {
userConnectionObservers.add(connectionCallback);
userDisconnectionObservers.add(disconnectionCallback);