use unique ID instead of ip

This commit is contained in:
Arnaud Vergnet 2021-01-05 22:00:30 +01:00
parent 1ab27f4f87
commit fcb678f4fe
12 changed files with 208 additions and 186 deletions

View file

@ -48,7 +48,7 @@ public class Message implements Serializable {
}
public UserInformation getCorrespondent() {
if (CurrentUser.getInstance().isLocalId(sender.id)) {
if (CurrentUser.getInstance().getId() != null && CurrentUser.getInstance().getId().equals(sender.id)) {
return recipient;
} else {
return sender;

View file

@ -81,8 +81,8 @@ public class DatabaseController {
@Language("SQL") String sql = "CREATE TABLE IF NOT EXISTS message " +
"(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
" timestamp DATETIME NOT NULL, " +
" sender INTEGER UNSIGNED NOT NULL, " +
" recipient INTEGER UNSIGNED NOT NULL, " +
" sender TEXT NOT NULL, " +
" recipient TEXT NOT NULL, " +
" text TEXT, " +
" file_path TEXT)";
@ -99,14 +99,30 @@ public class DatabaseController {
*/
private void createUserTable(@Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "CREATE TABLE IF NOT EXISTS user " +
"(id INTEGER UNSIGNED PRIMARY KEY NOT NULL," +
" username TINYTEXT NULLABLE )";
"(id TEXT PRIMARY KEY NOT NULL," +
" username TINYTEXT NULLABLE )";
Log.v(getClass().getSimpleName(), "Creating table user...");
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
executor.start();
}
/**
* Creates the table used to store users
*
* @param callback The function to call on success
* @param errorCallback The function to call on error
*/
private void createCurrentUserTable(@Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "CREATE TABLE IF NOT EXISTS current_user " +
"(id TEXT PRIMARY KEY NOT NULL," +
" username TINYTEXT NULLABLE )";
Log.v(getClass().getSimpleName(), "Creating table current user...");
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
executor.start();
}
/**
* Creates all needed tables if non-existent
*
@ -114,7 +130,7 @@ public class DatabaseController {
* @param errorCallback The function to call on error
*/
public void initTables(@Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
createMessageTable(() -> createUserTable(callback, errorCallback), errorCallback);
createMessageTable(() -> createCurrentUserTable(() -> createUserTable(callback, errorCallback), errorCallback), errorCallback);
}
/**
@ -143,6 +159,13 @@ public class DatabaseController {
executor.start();
}
private void dropCurrentUserTable(@Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "DROP TABLE IF EXISTS current_user";
Log.v(getClass().getSimpleName(), "Dropping table current_user...");
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
executor.start();
}
/**
* Destroys all tables
*
@ -150,7 +173,7 @@ public class DatabaseController {
* @param errorCallback The function to call on error
*/
private void dropTables(@Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
dropMessageTable(() -> dropUserTable(callback, errorCallback), errorCallback);
dropMessageTable(() -> dropUserTable(() -> dropCurrentUserTable(callback, errorCallback), errorCallback), errorCallback);
}
/**
@ -171,14 +194,14 @@ public class DatabaseController {
* @param errorCallback The function to call on error
*/
public void getAllUsers(UsersCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "SELECT * FROM user WHERE id != " + CurrentUser.getInstance().getId();
@Language("SQL") String sql = "SELECT * FROM user";
Log.v(getClass().getSimpleName(), "Fetching users from db... ");
QueryExecutor executor = new QueryExecutor(sql, res -> {
ArrayList<User> userList = new ArrayList<>();
while (res.next()) {
int id = res.getInt("id");
String id = res.getString("id");
String username = res.getString("username");
userList.add(new User(id, username));
}
@ -189,6 +212,26 @@ public class DatabaseController {
executor.start();
}
public void getCurrentUser(CurrentUserCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "SELECT * FROM current_user ";
Log.v(getClass().getSimpleName(), "Fetching current_user from db... ");
QueryExecutor executor = new QueryExecutor(sql, res -> {
UserInformation user = null;
int nbRows = 0;
if (res.next()) {
String id = res.getString("id");
String username = res.getString("username");
user = new UserInformation(id, username);
nbRows = 1;
}
Log.v(getClass().getSimpleName(), nbRows + " users fetched");
callback.onFetched(user);
}, errorCallback);
executor.start();
}
/**
* Adds a message to the database for this user.
@ -200,9 +243,8 @@ public class DatabaseController {
*/
public void addMessage(Message message, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
// Insert the correspondent if not already in the database
Log.v(getClass().getSimpleName(), "Inserting correpondent into db... ");
Log.v(getClass().getSimpleName(), "Inserting correspondent into db... ");
addUser(message.getCorrespondent(), () -> {
// Handle messages containing a file
String filePath = "NULL";
// TODO: Handle messages containing files:
@ -212,24 +254,16 @@ public class DatabaseController {
// filePath = ((FileMessage) message).getFileName();
}
// TODO: do this in the construction of the message instead?
int recipientId;
int senderId;
// if (CurrentUser.getInstance().isLocalId(message.getRecipient().id)) {
// recipientId = CurrentUser.getInstance().getId();
senderId = message.getSender().id;
// } else {
// senderId = CurrentUser.getInstance().getId();
recipientId = message.getRecipient().id;
// }
String recipientId = message.getRecipient().id;
String senderId = message.getSender().id;
// Insert the new message
@Language("SQL") String sql = "INSERT INTO message " +
"(timestamp, sender, recipient, text, file_path) " +
"VALUES (" +
message.getDate().getTime() + ", " +
senderId + ", " +
recipientId + ", " +
"'" + senderId + "', " +
"'" + recipientId + "', " +
"\"" + message.getText() + "\", " +
filePath +
")";
@ -251,10 +285,10 @@ public class DatabaseController {
@Language("SQL") String sql;
if (user.getUsername() != null) {
sql = "INSERT OR IGNORE INTO user (id, username) " +
"VALUES (" + user.id + ", \"" + user.getUsername() + "\")";
"VALUES ('" + user.id + "', '" + user.getUsername() + "')";
} else {
sql = "INSERT OR IGNORE INTO user (id) " +
"VALUES (" + user.id + ")";
"VALUES ('" + user.id + "')";
}
Log.v(getClass().getSimpleName(), "Adding user to db: " + user.id + " / " + user.getUsername());
@ -262,6 +296,21 @@ public class DatabaseController {
executor.start();
}
public void addCurrentUser(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql;
if (user.getUsername() != null) {
sql = "INSERT OR IGNORE INTO current_user (id, username) " +
"VALUES ('" + user.id + "', '" + user.getUsername() + "')";
} else {
sql = "INSERT OR IGNORE INTO current_user (id) " +
"VALUES ('" + user.id + "')";
}
Log.v(getClass().getSimpleName(), "Adding current_user to db: " + user.id + " / " + user.getUsername());
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
executor.start();
}
/**
* Gets the chat history for a given time frame
*
@ -272,22 +321,24 @@ public class DatabaseController {
* @param errorCallback The function to call on error
*/
public void getChatHistory(UserInformation user, Date from, Date to, HistoryCallback callback, ErrorCallback errorCallback) {
// TODO update to search in current_user table as well
@Language("SQL") String sql =
"SELECT timestamp, s.id AS sender_id, s.username AS sender_username, " +
"r.id AS recipient_id, r.username AS recipient_username, text, file_path " +
"FROM message JOIN user AS s ON sender = s.id " +
" JOIN user AS r ON recipient = r.id " +
"WHERE (s.id = " + user.id + " OR r.id = " + user.id + ") AND " +
"WHERE (s.id = '" + user.id + "' OR r.id = '" + user.id + "') AND " +
"timestamp > " + from.getTime() + " AND timestamp < " + to.getTime() + " " +
"ORDER BY timestamp";
System.out.println(sql);
Log.v(getClass().getSimpleName(), "Fetching chat history from db... ");
QueryExecutor executor = new QueryExecutor(sql, res -> {
ArrayList<Message> chatHistory = new ArrayList<>();
while (res.next()) {
int sId = res.getInt("sender_id");
String sId = res.getString("sender_id");
String sUsername = res.getString("sender_username");
int rId = res.getInt("recipient_id");
String rId = res.getString("recipient_id");
String rUsername = res.getString("recipient_username");
Date date = new Date(res.getTimestamp("timestamp").getTime());
String text = res.getString("text");
@ -307,25 +358,14 @@ public class DatabaseController {
}
public void updateUsername(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "UPDATE user SET username = '" + user.getUsername() + "' where id = " + user.id;
@Language("SQL") String sql = "UPDATE user SET username = '" + user.getUsername() + "' where id = '" + user.id + "'";
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
executor.start();
}
public void getUsername(int id, UsernameCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "SELECT username from user where id =" + id;
Log.v(getClass().getSimpleName(), "Fetching username from db... ");
QueryExecutor executor = new QueryExecutor(sql, res -> {
String username = null;
int nbRows = 0;
if (res.next()) {
username = res.getString("username");
nbRows = 1;
}
Log.v(getClass().getSimpleName(), nbRows + " username fetched");
callback.onUsernameFetched(username);
}, errorCallback);
public void updateCurrentUsername(UserInformation user, @Nullable DatabaseController.UpdateCallback callback, ErrorCallback errorCallback) {
@Language("SQL") String sql = "UPDATE current_user SET username = '" + user.getUsername() + "' where id = '" + user.id + "'";
UpdateExecutor executor = new UpdateExecutor(sql, callback, errorCallback);
executor.start();
}
@ -404,6 +444,10 @@ public class DatabaseController {
void onUsersFetched(ArrayList<User> users);
}
public interface CurrentUserCallback {
void onFetched(UserInformation user);
}
public interface UsernameCallback {
void onUsernameFetched(String username);
}

View file

@ -59,13 +59,4 @@ public class NetUtil {
final List<InetAddress> list = listAllLocalAddresses();
return list.stream().anyMatch((a) -> Arrays.equals(address.getAddress(), a.getAddress()));
}
public static int getIdFromIp(InetAddress ipAddr) {
byte[] addr = ipAddr.getAddress();
int id = 0;
for (byte b : addr) {
id = (id << 8) + b;
}
return id;
}
}

View file

@ -46,11 +46,9 @@ public class MainController implements Initializable {
private JFXSnackbar snackbar;
private UserList userList;
private boolean historyLoaded;
private boolean online;
public MainController() {
historyLoaded = false;
online = false;
currentUser = CurrentUser.getInstance();
currentUser.addObserver(propertyChangeEvent -> {
@ -65,13 +63,10 @@ public class MainController implements Initializable {
* If the current user becomes valid, start the chat.
* If it is invalid or not set, show the login screen.
* <p>
* If the history is not yet loaded or the user is not initialized, do nothing.
*
* @param newState The new user state
*/
private void onCurrentUserStateChange(CurrentUser.State newState) {
// Only do an action if the history is loaded
if (historyLoaded) {
if (newState == CurrentUser.State.VALID)
startChat();
else if (newState != CurrentUser.State.UNINITIALIZED) {
@ -81,18 +76,6 @@ public class MainController implements Initializable {
}
Platform.runLater(() -> showLogin(isError));
}
}
}
/**
* If the history loaded after the current user, fire the state change event again
*/
public void onHistoryLoaded() {
historyLoaded = true;
final CurrentUser.State userState = CurrentUser.getInstance().getState();
if (userState != CurrentUser.State.UNINITIALIZED) {
onCurrentUserStateChange(userState);
}
}
/**
@ -272,10 +255,10 @@ public class MainController implements Initializable {
private void initDb() {
final DatabaseController db = new DatabaseController();
db.initTables(() -> {
Log.v("INIT", "Current user: " + currentUser.getId());
currentUser.init(() -> {
userList.retrievedPreviousUsers(this::onHistoryLoaded, this::onInitError);
}, this::onInitError);
userList.retrievedPreviousUsers(
() -> currentUser.init(this::onInitError),
this::onInitError
);
}, this::onInitError);
}

View file

@ -1,6 +1,7 @@
package fr.insa.clavardator.ui.chat;
import fr.insa.clavardator.chat.Message;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.ListCell;
@ -29,8 +30,10 @@ public class MessageListItemCell extends ListCell<Message> {
if (item == null || empty) {
setGraphic(null);
} else {
setGraphic(view);
messageListItemController.setMessage(item);
Platform.runLater(() -> {
setGraphic(view);
messageListItemController.setMessage(item);
});
}
}
}

View file

@ -35,7 +35,7 @@ public class MessageListItemController implements Initializable {
button.setText(message.getText());
timestamp.setText(DateFormat.getTimeInstance().format(message.getDate()));
clearBackground();
if (CurrentUser.getInstance().isLocalId(message.getSender().id)) {
if (CurrentUser.getInstance().getId().equals(message.getSender().id)) {
container.setAlignment(Pos.CENTER_RIGHT);
button.getStyleClass().add("message-self");
} else {

View file

@ -1,29 +1,19 @@
package fr.insa.clavardator.users;
import fr.insa.clavardator.db.DatabaseController;
import fr.insa.clavardator.network.NetUtil;
import fr.insa.clavardator.util.ErrorCallback;
import fr.insa.clavardator.util.Log;
import org.jetbrains.annotations.Nullable;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import static fr.insa.clavardator.network.NetUtil.getIdFromIp;
import java.util.UUID;
public class CurrentUser extends User {
private static CurrentUser instance = null;
private State state;
private ArrayList<Integer> validIds;
private CurrentUser() {
super();
state = State.UNINITIALIZED;
validIds = new ArrayList<>();
}
/**
@ -35,48 +25,49 @@ public class CurrentUser extends User {
return instance;
}
public void init(@Nullable InitCallback callback, ErrorCallback errorCallback) {
try {
final List<InetAddress> addresses = NetUtil.listAllLocalAddresses();
// Save all addresses for this user
validIds = new ArrayList<>();
addresses.forEach(address -> validIds.add(getIdFromIp(address)));
if (validIds.size() > 0) {
// Set the first id as the main one
id = validIds.get(0);
private static String generateUniqueId() {
return UUID.randomUUID().toString();
}
public void init(ErrorCallback errorCallback) {
final DatabaseController db = new DatabaseController();
db.getCurrentUser((user) -> {
if (user == null) {
id = generateUniqueId();
Log.v(getClass().getSimpleName(), "No previous user found, generating id: " + id);
db.addCurrentUser(
new UserInformation(this),
() -> setState(State.NONE),
errorCallback);
} else {
errorCallback.onError(new SocketException("No valid IP found"));
return;
id = user.id;
if (user.getUsername() != null) {
Log.v(getClass().getSimpleName(), "Last user found : " + id + " / " + getUsername());
setUsername(user.getUsername());
} else {
Log.v(getClass().getSimpleName(), "No username found, asking user");
setState(State.NONE);
}
}
final DatabaseController db = new DatabaseController();
// Make sure the user is in the db then set its username
db.addUser(new UserInformation(this), () -> {
db.getUsername(id, username -> {
if (username != null) {
Log.v(getClass().getSimpleName(), "Last username found : " + username);
setUsername(username);
} else {
Log.v(getClass().getSimpleName(), "No last username found, asking user...");
setState(State.NONE);
}
if (callback != null) {
callback.onFinish();
}
}, errorCallback);
}, errorCallback);
} catch (SocketException e) {
errorCallback.onError(e);
}
}, errorCallback);
}
@Override
public void setUsername(String newUsername) {
Log.v(this.getClass().getSimpleName(),
"Username changed from " + getUsername() + " to " + newUsername);
super.setUsername(newUsername);
final DatabaseController db = new DatabaseController();
db.updateCurrentUsername(new UserInformation(this),
null,
e -> Log.e(getClass().getSimpleName(), "Unable to update the username", e));
Log.v(this.getClass().getSimpleName(),
"Username changed to " + getUsername());
setState(State.VALID);
}
public State getState() {
return state;
}
public void setState(State state) {
Log.v(this.getClass().getSimpleName(),
"State changed from " + this.state.toString() + " to " + state.toString());
@ -84,14 +75,6 @@ public class CurrentUser extends User {
this.state = state;
}
public State getState() {
return state;
}
public boolean isLocalId(int id) {
return validIds.contains(id);
}
public enum State {
UNINITIALIZED,
VALID,

View file

@ -2,6 +2,7 @@ package fr.insa.clavardator.users;
import fr.insa.clavardator.chat.ChatHistory;
import fr.insa.clavardator.chat.Message;
import fr.insa.clavardator.db.DatabaseController;
import fr.insa.clavardator.errors.UsernameTakenException;
import fr.insa.clavardator.network.PeerConnection;
import fr.insa.clavardator.util.ErrorCallback;
@ -19,16 +20,21 @@ public class PeerUser extends User implements Comparable<PeerUser> {
private State state = State.DISCONNECTED;
private transient PeerConnection connection;
public PeerUser(int id, String username) {
public PeerUser(String id, String username) {
super(id, username);
history = new ChatHistory(this);
}
public PeerUser(int id) {
public PeerUser(String id) {
super(id);
history = new ChatHistory(this);
}
public PeerUser() {
super();
history = new ChatHistory(this);
}
/**
* Asynchronously connects to the user and receives its information (id, username)
*
@ -127,6 +133,7 @@ public class PeerUser extends User implements Comparable<PeerUser> {
UserInformation userInfo = (UserInformation) msg;
final String receivedUsername = userInfo.getUsername();
if (!receivedUsername.equals(CurrentUser.getInstance().getUsername())) {
setId(userInfo.id);
setUsername(receivedUsername);
callback.onUserConnected();
subscribeToMessages(e -> {
@ -162,7 +169,7 @@ public class PeerUser extends User implements Comparable<PeerUser> {
msg -> {
Log.v(this.getClass().getSimpleName(), "Received message from " + id);
if (msg instanceof UserInformation) {
assert ((UserInformation) msg).id == getId();
assert ((UserInformation) msg).id.equals(getId());
final String receivedUsername = ((UserInformation) msg).getUsername();
Log.v(this.getClass().getSimpleName(), "Message username: " + receivedUsername);
if (CurrentUser.getInstance().getUsername().equals(receivedUsername)) {
@ -171,8 +178,7 @@ public class PeerUser extends User implements Comparable<PeerUser> {
setUsername(receivedUsername);
}
} else if (msg instanceof Message) {
assert ((Message) msg).getRecipient().id != id;
assert CurrentUser.getInstance().isLocalId(((Message) msg).getRecipient().id);
assert !((Message) msg).getRecipient().id.equals(id);
Log.v(this.getClass().getSimpleName(), "Message text: " + ((Message) msg).getText());
history.addMessage((Message) msg, errorCallback);
@ -200,6 +206,15 @@ public class PeerUser extends User implements Comparable<PeerUser> {
setState(State.DISCONNECTED);
}
@Override
protected void setUsername(String newUsername) {
super.setUsername(newUsername);
final DatabaseController db = new DatabaseController();
db.updateUsername(new UserInformation(this),
null,
e -> Log.e(getClass().getSimpleName(), "Unable to update the username", e));
}
/**
* Close the connection to this user
*/

View file

@ -9,7 +9,7 @@ import java.io.Serializable;
public class User implements Serializable {
private String username;
protected int id;
protected String id;
// Make this class observable
protected final transient PropertyChangeSupport pcs = new PropertyChangeSupport(this);
@ -23,20 +23,24 @@ public class User implements Serializable {
public User() {
}
public User(int id) {
public User(String id) {
this.id = id;
}
public User(int id, String username) {
public User(String id, String username) {
this.id = id;
this.username = username;
}
public int getId() {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
@ -44,8 +48,6 @@ public class User implements Serializable {
protected void setUsername(String newUsername) {
pcs.firePropertyChange("username", this.username, newUsername);
this.username = newUsername;
final DatabaseController db = new DatabaseController();
db.updateUsername(new UserInformation(this), null, e -> Log.e(getClass().getSimpleName(), "Unable to update the username", e));
}
@Override

View file

@ -6,10 +6,10 @@ import java.io.Serializable;
* Class used to serialize useful user information
*/
public class UserInformation implements Serializable {
public final int id;
public final String id;
private final String username;
public UserInformation(int id, String username) {
public UserInformation(String id, String username) {
this.id = id;
this.username = username;
}

View file

@ -7,16 +7,17 @@ import fr.insa.clavardator.util.ErrorCallback;
import fr.insa.clavardator.util.Log;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import static fr.insa.clavardator.network.NetUtil.getIdFromIp;
public class UserList {
private final Map<Integer, PeerUser> inactiveUsers = new HashMap<>();
private final Map<Integer, PeerUser> activeUsers = new HashMap<>();
private final Map<String, PeerUser> inactiveUsers = new HashMap<>();
private final Map<String, PeerUser> activeUsers = new HashMap<>();
private final ArrayList<PeerUser> pendingUsers = new ArrayList<>();
private UserConnectionCallback newUsersObservers = null;
@ -57,9 +58,8 @@ public class UserList {
*/
public void discoverActiveUsers(ErrorCallback errorCallback) {
netDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
int id = getIdFromIp(ipAddr);
Log.v(this.getClass().getSimpleName(), "Discovered new user: " + id);
final PeerUser user = createNewUser(id);
Log.v(this.getClass().getSimpleName(), "Discovered new user: " + data);
final PeerUser user = createNewPendingUser(data.trim());
if (user != null) {
user.createConnection(ipAddr, () -> onUserConnectionSuccess(user), errorCallback);
}
@ -72,14 +72,14 @@ public class UserList {
*/
public void startDiscoveryListening() {
netDiscoverer.startDiscoveryListening(
"CLAVARDATOR_RESPONSE",
CurrentUser.getInstance().getId(),
null,
Throwable::printStackTrace);
}
public void retrievedPreviousUsers(UserListLoadedCallback onFinish, ErrorCallback errorCallback) {
db.getAllUsers(users -> {
users.forEach(user -> createNewUser(user.id, user.getUsername()));
users.forEach(user -> createNewInactiveUser(user.id, user.getUsername()));
onFinish.onLoaded();
}, errorCallback);
}
@ -92,9 +92,9 @@ public class UserList {
public void startUserListening(ErrorCallback errorCallback) {
connectionListener.acceptConnection(
(clientSocket) -> {
final int id = getIdFromIp(clientSocket.getInetAddress());
Log.v(this.getClass().getSimpleName(), "new connection from user: " + id);
final PeerUser user = createNewUser(id);
Log.v(this.getClass().getSimpleName(),
"new connection from user at address: " + clientSocket.getInetAddress().toString());
final PeerUser user = createNewPendingUser();
if (user != null) {
user.acceptConnection(clientSocket, () ->
onUserConnectionSuccess(user), errorCallback);
@ -113,6 +113,12 @@ public class UserList {
user.addObserver(evt -> userChangeObserver(user, evt));
}
private PeerUser createNewPendingUser() {
PeerUser user = new PeerUser();
addUserToPendingList(user);
return user;
}
/**
* Creates a new user from its id and puts it in the inactive user list.
* We first try to fetch it from active and inactive users to prevent duplicates.
@ -121,7 +127,7 @@ public class UserList {
* @param id The new user's id.
* @return A new PeerUser, or null if the user is already connected
*/
private PeerUser createNewUser(int id) {
private PeerUser createNewPendingUser(String id) {
// If already connected, warn and return
if (activeUsers.containsKey(id)) {
Log.w(getClass().getSimpleName(),
@ -135,7 +141,7 @@ public class UserList {
if (user == null) {
// Username is set on TCP connection start or db fetch
user = new PeerUser(id);
inactiveUsers.put(id, user);
addUserToPendingList(user);
}
return user;
}
@ -147,15 +153,17 @@ public class UserList {
*
* @param id The new user's id.
* @param username The new user's username.
* @return A new PeerUser, or null if the user is already connected
*/
private PeerUser createNewUser(int id, String username) {
final PeerUser user = createNewUser(id);
if (user != null) {
user.setUsername(username);
notifyNewUserObservers(user);
private void createNewInactiveUser(String id, String username) {
final PeerUser user = new PeerUser(id, username);
inactiveUsers.put(id, user);
notifyNewUserObservers(user);
}
private void addUserToPendingList(PeerUser user) {
if (!pendingUsers.contains(user)) {
pendingUsers.add(user);
}
return user;
}
/**
@ -164,7 +172,7 @@ public class UserList {
* @param user The user to move
*/
private void moveUserToActiveList(PeerUser user) {
final int id = user.id;
final String id = user.id;
if (!inactiveUsers.containsKey(id)) {
if (activeUsers.containsKey(id)) {
Log.w(getClass().getSimpleName(), "Tried to set state " + PeerUser.State.CONNECTED + " on an already connected user: user id " + id);
@ -183,7 +191,7 @@ public class UserList {
* @param user The user to move
*/
private void moveUserToInactiveList(PeerUser user) {
final int id = user.id;
final String id = user.id;
if (!activeUsers.containsKey(id)) {
if (inactiveUsers.containsKey(id)) {
Log.w(getClass().getSimpleName(), "Tried to set state " + PeerUser.State.DISCONNECTED + " on an already disconnected user: user id " + id);

View file

@ -28,53 +28,53 @@ public class DatabaseTest {
latch2.countDown();
}, Assertions::fail);
db.getChatHistory(new UserInformation(1, "Yohan"), new Date(0), new Date(), history -> {
db.getChatHistory(new UserInformation("1", "Yohan"), new Date(0), new Date(), history -> {
assertEquals(history.size(), 0);
latch2.countDown();
}, Assertions::fail);
latch2.await();
CountDownLatch latch8 = new CountDownLatch(1);
db.addUser(new UserInformation(3, null), latch8::countDown, Assertions::fail);
db.addUser(new UserInformation("3", null), latch8::countDown, Assertions::fail);
latch8.await();
CountDownLatch latch3 = new CountDownLatch(5);
db.addMessage(new Message(new UserInformation(1, "Yohan"), new UserInformation(2, "Arnaud"),
db.addMessage(new Message(new UserInformation("1", "Yohan"), new UserInformation("2", "Arnaud"),
new Date(1609843556860L), "Coucou Arnaud !"), latch3::countDown, Assertions::fail);
db.addMessage(new Message(new UserInformation(2, "Arnaud"), new UserInformation(1, "Yohan"),
db.addMessage(new Message(new UserInformation("2", "Arnaud"), new UserInformation("1", "Yohan"),
new Date(1609843556861L), "Coucou Yohan !"), latch3::countDown, Assertions::fail);
db.addMessage(new Message(new UserInformation(1, "Yohan"), new UserInformation(2, "Arnaud"),
db.addMessage(new Message(new UserInformation("1", "Yohan"), new UserInformation("2", "Arnaud"),
new Date(1609843556862L), "Ça va ?"), latch3::countDown, Assertions::fail);
db.addMessage(new Message(new UserInformation(2, "Arnaud"), new UserInformation(1, "Yohan"),
db.addMessage(new Message(new UserInformation("2", "Arnaud"), new UserInformation("1", "Yohan"),
new Date(1609843556863L), "Ouais et toi ?"), latch3::countDown, Assertions::fail);
db.addMessage(new Message(new UserInformation(1, "Yohan"), new UserInformation(2, "Arnaud"),
db.addMessage(new Message(new UserInformation("1", "Yohan"), new UserInformation("2", "Arnaud"),
new Date(1609843556864L), "Super !"), latch3::countDown, Assertions::fail);
latch3.await();
CountDownLatch latch4 = new CountDownLatch(2);
db.getAllUsers(users -> {
assertEquals(3, users.size());
assertEquals(3, users.get(0).getId());
assertEquals(1, users.get(1).getId());
assertEquals(2, users.get(2).getId());
assertEquals("3", users.get(0).getId());
assertEquals("1", users.get(1).getId());
assertEquals("2", users.get(2).getId());
assertNull(users.get(0).getUsername());
assertEquals("Yohan", users.get(1).getUsername());
assertEquals("Arnaud", users.get(2).getUsername());
latch4.countDown();
}, Assertions::fail);
db.getChatHistory(new UserInformation(1, "Yohan"), new Date(0), new Date(), history -> {
db.getChatHistory(new UserInformation("1", "Yohan"), new Date(0), new Date(), history -> {
assertEquals(5, history.size());
assertEquals("Coucou Arnaud !", history.get(0).getText());
assertEquals(1, history.get(0).getSender().id);
assertEquals(2, history.get(0).getRecipient().id);
assertEquals("1", history.get(0).getSender().id);
assertEquals("2", history.get(0).getRecipient().id);
assertEquals("Yohan", history.get(0).getSender().getUsername());
assertEquals("Arnaud", history.get(0).getRecipient().getUsername());
assertEquals("Ouais et toi ?", history.get(3).getText());
assertEquals(2, history.get(3).getSender().id);
assertEquals(1, history.get(3).getRecipient().id);
assertEquals("2", history.get(3).getSender().id);
assertEquals("1", history.get(3).getRecipient().id);
assertEquals("Arnaud", history.get(3).getSender().getUsername());
assertEquals("Yohan", history.get(3).getRecipient().getUsername());
latch4.countDown();
@ -82,16 +82,9 @@ public class DatabaseTest {
latch4.await();
CountDownLatch latch5 = new CountDownLatch(1);
db.updateUsername(new UserInformation(2, "Toto"), latch5::countDown, Assertions::fail);
db.updateUsername(new UserInformation("2", "Toto"), latch5::countDown, Assertions::fail);
latch5.await();
CountDownLatch latch6 = new CountDownLatch(1);
db.getUsername(2, username -> {
assertEquals("Toto", username);
latch6.countDown();
}, Assertions::fail);
latch6.await();
CountDownLatch latch7 = new CountDownLatch(1);
db.resetTables(latch7::countDown, Assertions::fail);
latch7.await();