Handle user connection and disconnection
This commit is contained in:
parent
6f6492e8c0
commit
965cfdbf19
2 changed files with 95 additions and 6 deletions
|
@ -40,9 +40,9 @@ public class ConnectionListener {
|
||||||
|
|
||||||
private static class Acceptor extends Thread {
|
private static class Acceptor extends Thread {
|
||||||
private boolean shouldStop = false;
|
private boolean shouldStop = false;
|
||||||
NewConnectionCallback callback;
|
private final NewConnectionCallback callback;
|
||||||
ErrorCallback errorCallback;
|
private final ErrorCallback errorCallback;
|
||||||
ServerSocket server;
|
private ServerSocket server;
|
||||||
|
|
||||||
public Acceptor(NewConnectionCallback callback, ErrorCallback errorCallback) {
|
public Acceptor(NewConnectionCallback callback, ErrorCallback errorCallback) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package fr.insa.clavardator.users;
|
package fr.insa.clavardator.users;
|
||||||
|
|
||||||
import fr.insa.clavardator.db.DatabaseController;
|
import fr.insa.clavardator.db.DatabaseController;
|
||||||
|
import fr.insa.clavardator.network.ConnectionListener;
|
||||||
import fr.insa.clavardator.network.NetDiscoverer;
|
import fr.insa.clavardator.network.NetDiscoverer;
|
||||||
import fr.insa.clavardator.util.ErrorCallback;
|
import fr.insa.clavardator.util.ErrorCallback;
|
||||||
import fr.insa.clavardator.util.Log;
|
import fr.insa.clavardator.util.Log;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -21,6 +23,7 @@ public class UserList {
|
||||||
|
|
||||||
private final DatabaseController db = new DatabaseController();
|
private final DatabaseController db = new DatabaseController();
|
||||||
private final NetDiscoverer netDiscoverer = new NetDiscoverer();
|
private final NetDiscoverer netDiscoverer = new NetDiscoverer();
|
||||||
|
private final ConnectionListener connectionListener = new ConnectionListener();
|
||||||
|
|
||||||
public UserList() {
|
public UserList() {
|
||||||
}
|
}
|
||||||
|
@ -35,17 +38,24 @@ public class UserList {
|
||||||
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
|
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
|
||||||
int id = getIdFromIp(ipAddr);
|
int id = getIdFromIp(ipAddr);
|
||||||
Log.v(this.getClass().getSimpleName(), "Discovered new user: " + id);
|
Log.v(this.getClass().getSimpleName(), "Discovered new user: " + id);
|
||||||
|
|
||||||
// If already connected, do not modify
|
// If already connected, do not modify
|
||||||
if (activeUsers.containsKey(id)) {
|
if (activeUsers.containsKey(id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerUser user = inactiveUsers.get(id);
|
PeerUser user = inactiveUsers.get(id);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
// Username is set on TCP connection start
|
// Username is set on TCP connection start
|
||||||
user = new PeerUser(id, "");
|
user = new PeerUser(id, "");
|
||||||
|
inactiveUsers.put(id, user);
|
||||||
}
|
}
|
||||||
PeerUser finalUser = user;
|
PeerUser finalUser = user;
|
||||||
user.connect(ipAddr, () -> notifyConnectionObservers(finalUser), errorCallback);
|
user.connect(ipAddr, () -> {
|
||||||
|
notifyConnectionObservers(finalUser);
|
||||||
|
finalUser.addObserver(evt -> userChangeObserver(finalUser, evt));
|
||||||
|
}, errorCallback);
|
||||||
|
|
||||||
}, errorCallback);
|
}, errorCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +66,89 @@ public class UserList {
|
||||||
Throwable::printStackTrace);
|
Throwable::printStackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getIdFromIp(InetAddress ipAddr) {
|
public void startUserListening(ErrorCallback errorCallback) {
|
||||||
return ipAddr.hashCode();
|
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) {
|
public void addActiveUsersObserver(UserConnectionCallback connectionCallback, UserDisconnectionCallback disconnectionCallback) {
|
||||||
userConnectionObservers.add(connectionCallback);
|
userConnectionObservers.add(connectionCallback);
|
||||||
userDisconnectionObservers.add(disconnectionCallback);
|
userDisconnectionObservers.add(disconnectionCallback);
|
||||||
|
|
Loading…
Reference in a new issue