Merge remote-tracking branch 'origin/master'

This commit is contained in:
Arnaud Vergnet 2020-12-02 12:16:39 +01:00
commit 725c809436
8 changed files with 163 additions and 82 deletions

View file

@ -2,7 +2,6 @@ package fr.insa.clavardator;
import fr.insa.clavardator.network.NetDiscoverer;
import fr.insa.clavardator.ui.MainController;
import fr.insa.clavardator.util.ErrorHandler;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
@ -36,12 +35,10 @@ public class MainApp extends Application {
stage.show();
// Network discovery test
ErrorHandler.getInstance().addObserver(evt -> ((Exception)evt.getNewValue()).printStackTrace());
NetDiscoverer.discoverActiveUsers("Broadcast",
(ipAddr, data) -> System.out.println("User detected at address : " + ipAddr.toString())
);
NetDiscoverer.startDiscoveryListening("Yohan", null);
(ipAddr, data) -> System.out.println("User detected at address : " + ipAddr.toString()),
Throwable::printStackTrace);
NetDiscoverer.startDiscoveryListening("Yohan", null, Throwable::printStackTrace);
}
@Override

View file

@ -1,6 +1,6 @@
package fr.insa.clavardator.network;
import fr.insa.clavardator.util.ErrorHandler;
import fr.insa.clavardator.util.ErrorCallback;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
@ -26,28 +26,41 @@ public class NetDiscoverer {
/**
* Discovers all active users in the network, and call the callback for each of them
*
* @param callback function to call when a new user is discovered
* @param broadcastMessage The message to send as broadcast
* @param callback function to call when a new user is discovered
* @param errorCallback function to call on error
*/
public static void discoverActiveUsers(String broadcastMessage, ResponseReceivedCallback callback) {
ResponseListener receiver = new ResponseListener(callback);
BroadcastSender sender = new BroadcastSender(broadcastMessage);
public static void discoverActiveUsers(String broadcastMessage, ResponseReceivedCallback callback, ErrorCallback errorCallback) {
ResponseListener receiver = new ResponseListener(callback, errorCallback);
BroadcastSender sender = new BroadcastSender(broadcastMessage, errorCallback);
receiver.start();
sender.start();
}
/**
* Starts to listen for discovery broadcasts and answers them
*
* @param responseMessage The message to send in response to broadcasts
* @param onBroadcastReceived The function to call on success
* @param errorCallback The function to call on error
*/
public static void startDiscoveryListening(String responseMessage, @Nullable BroadcastReceivedCallback onBroadcastReceived) {
public static void startDiscoveryListening(String responseMessage, @Nullable BroadcastReceivedCallback onBroadcastReceived, @Nullable ErrorCallback errorCallback) {
BroadcastListener listener = new BroadcastListener((ipAddr, data) -> {
if (onBroadcastReceived != null)
onBroadcastReceived.onBroadcastReceived(ipAddr, data);
new ResponseSender(ipAddr, responseMessage).start();
}
);
ResponseSender sender = new ResponseSender(ipAddr, responseMessage, errorCallback);
sender.start();
}, e -> {
if (errorCallback != null)
errorCallback.onError(e);
});
listener.start();
}
/**
* Stop network discovery and listening
*/
public static void stopDiscovery() {
shouldStop = true;
if (broadcastListener != null)
@ -58,15 +71,18 @@ public class NetDiscoverer {
private static class BroadcastSender extends Thread {
String broadcastMessage;
private final String broadcastMessage;
private final ErrorCallback errorCallback;
/**
* Constructs and starts a thread that sends a broadcast over the network
* Constructs a thread that sends a broadcast over the network
*
* @param broadcastMessage The message to send
* @param errorCallback The function to call on error
*/
public BroadcastSender(String broadcastMessage) {
public BroadcastSender(String broadcastMessage, ErrorCallback errorCallback) {
this.broadcastMessage = broadcastMessage;
this.errorCallback = errorCallback;
}
@Override
@ -81,22 +97,30 @@ public class NetDiscoverer {
}
} catch (IOException e) {
ErrorHandler.getInstance().notifyError(e);
errorCallback.onError(e);
}
}
}
private static class BroadcastListener extends Thread {
BroadcastReceivedCallback callback;
private final BroadcastReceivedCallback callback;
private final ErrorCallback errorCallback;
public BroadcastListener(BroadcastReceivedCallback callback) {
/**
* Constructs a thread that sends a broadcast over the network, using all available interfaces
*
* @param callback The function to call on success
* @param errorCallback The function to call on error
*/
public BroadcastListener(BroadcastReceivedCallback callback, ErrorCallback errorCallback) {
this.callback = callback;
this.errorCallback = errorCallback;
}
@Override
public void run() {
while (!shouldStop) {
try {
try {
while (!shouldStop) {
broadcastListener = new DatagramSocket(null);
broadcastListener.setOption(StandardSocketOptions.SO_REUSEPORT, true);
broadcastListener.setOption(StandardSocketOptions.SO_REUSEADDR, true);
@ -108,27 +132,31 @@ public class NetDiscoverer {
broadcastListener.receive(receivedPacket);
// System.out.println("broadcast received from " + receivedPacket.getAddress().toString());
callback.onBroadcastReceived(receivedPacket.getAddress(), new String(receivedPacket.getData()));
} catch (IOException e) {
if (!shouldStop) {
ErrorHandler.getInstance().notifyError(e);
}
}
} catch (IOException e) {
if (!shouldStop) {
errorCallback.onError(e);
}
}
}
}
private static class ResponseSender extends Thread {
String message;
InetAddress address;
private final String message;
private final InetAddress address;
private final ErrorCallback errorCallback;
/**
* Constructs and starts a thread that sends a broadcast over the network
* Constructs a thread that sends a UDP response
*
* @param message The message to send
* @param address The address of the remote host
* @param message The message to send
* @param errorCallback The function to call on error
*/
public ResponseSender(InetAddress address, String message) {
public ResponseSender(InetAddress address, String message, ErrorCallback errorCallback) {
this.address = address;
this.message = message;
this.errorCallback = errorCallback;
}
@Override
@ -139,22 +167,30 @@ public class NetDiscoverer {
responseSocket.send(new DatagramPacket(buf, buf.length, address, RESPONSE_PORT));
// System.out.println("Response sent to " + address.toString());
} catch (IOException e) {
ErrorHandler.getInstance().notifyError(e);
errorCallback.onError(e);
}
}
}
private static class ResponseListener extends Thread {
ResponseReceivedCallback callback;
private final ResponseReceivedCallback callback;
private final ErrorCallback errorCallback;
public ResponseListener(ResponseReceivedCallback callback) {
/**
* Constructs a thread that receives all UDP responses, until stopDiscovery() is called
*
* @param callback The function to call on success
* @param errorCallback The function to call on error
*/
public ResponseListener(ResponseReceivedCallback callback, ErrorCallback errorCallback) {
this.callback = callback;
this.errorCallback = errorCallback;
}
@Override
public void run() {
while (!shouldStop) {
try {
try {
while (!shouldStop) {
responseListener = new DatagramSocket(null);
responseListener.setOption(StandardSocketOptions.SO_REUSEPORT, true);
responseListener.setOption(StandardSocketOptions.SO_REUSEADDR, true);
@ -165,10 +201,10 @@ public class NetDiscoverer {
responseListener.receive(receivedPacket);
// System.out.println("response received from " + receivedPacket.getAddress().toString());
callback.onResponseReceived(receivedPacket.getAddress(), new String(receivedPacket.getData()));
} catch (IOException e) {
if (!shouldStop) {
ErrorHandler.getInstance().notifyError(e);
}
}
} catch (IOException e) {
if (!shouldStop) {
errorCallback.onError(e);
}
}
}
@ -177,7 +213,7 @@ public class NetDiscoverer {
static List<InetAddress> listAllBroadcastAddresses() throws SocketException {
List<InetAddress> broadcastList = new ArrayList<>();
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
@ -192,12 +228,11 @@ public class NetDiscoverer {
}
public interface ResponseReceivedCallback {
void onResponseReceived(InetAddress ipAddr, String data);
}
private interface BroadcastReceivedCallback {
void onBroadcastReceived(InetAddress ipAddr, String data);
}
public interface ResponseReceivedCallback {
void onResponseReceived(InetAddress ipAddr, String data);
}
}

View file

@ -1,9 +1,12 @@
package fr.insa.clavardator.network;
import fr.insa.clavardator.chat.Message;
import fr.insa.clavardator.util.ErrorHandler;
import fr.insa.clavardator.util.ErrorCallback;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.InetAddress;
@ -12,76 +15,107 @@ import java.net.Socket;
public class PeerConnection {
public static final short PORT = 31598;
private Socket socket;
private final ObjectOutputStream outputStream;
private final ObjectInputStream inputStream;
public PeerConnection(InetAddress ipAddr) {
try {
socket = new Socket(ipAddr, PORT);
} catch (IOException e) {
ErrorHandler.getInstance().notifyError(e);
}
public PeerConnection(InetAddress ipAddr) throws IOException {
Socket socket = new Socket(ipAddr, PORT);
outputStream = new ObjectOutputStream(socket.getOutputStream());
inputStream = new ObjectInputStream(socket.getInputStream());
}
/**
* @param message
* @param callback
* Sends a message to the peer
*
* @param message The message to send
* @param callback The function to call on success
* @param errorCallback The function to call on error
*/
public void sendMessage(Message message, MessageSentCallback callback) {
Sender sender = new Sender(message, callback);
public void sendMessage(Message message, MessageSentCallback callback, ErrorCallback errorCallback) {
Sender sender = new Sender(message, callback, errorCallback);
sender.start();
}
public void receiveMessage(MessageReceivedCallback callback) {
Receiver receiver = new Receiver(callback);
/**
* Receives a message from the peer
*
* @param callback The function to call on success
* @param errorCallback The function to call on error
*/
public void receiveMessage(MessageReceivedCallback callback, ErrorCallback errorCallback) {
Receiver receiver = new Receiver(callback, errorCallback);
receiver.start();
}
private class Sender extends Thread {
Serializable message;
MessageSentCallback callback;
private final Serializable message;
private final MessageSentCallback callback;
private final ErrorCallback errorCallback;
/**
* Constructs and starts a thread that sends a message using the socket of the outer class
* @param messsage The message to send
* @param callback The function to call once finished
* Constructs a thread that sends a message using the socket of the outer class
*
* @param messsage The message to send
* @param callback The function to call on success
* @param errorCallback The function to call on error
*/
public Sender(Serializable messsage, MessageSentCallback callback) {
public Sender(Serializable messsage, @Nullable MessageSentCallback callback, @Nullable ErrorCallback errorCallback) {
this.message = messsage;
this.callback = callback;
this.errorCallback = errorCallback;
}
@Override
synchronized public void run() {
try {
// TODO: store the oos in Peer connection?
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message);
outputStream.writeObject(message);
if (callback != null)
callback.onMessageSent();
} catch (IOException e) {
ErrorHandler.getInstance().notifyError(e);
if (errorCallback != null)
errorCallback.onError(e);
}
callback.onMessageSent();
}
}
private class Receiver extends Thread {
MessageReceivedCallback callback;
private final MessageReceivedCallback callback;
private final ErrorCallback errorCallback;
public Receiver(MessageReceivedCallback callback) {
/**
* Constructs a thread that receives a message using the socket of the outer class
*
* @param callback The function to call on success
* @param errorCallback The function to call on error
*/
public Receiver(@NotNull MessageReceivedCallback callback, @Nullable ErrorCallback errorCallback) {
this.callback = callback;
this.errorCallback = errorCallback;
}
@Override
public void run() {
//TODO
// callback.onMessageReceived();
try {
Object msg = inputStream.readObject();
if (msg.getClass().isInstance(Message.class)) {
callback.onMessageReceived((Message) msg);
} else {
if (errorCallback != null)
errorCallback.onError(new ClassCastException("The message received is not a valid Message object"));
}
} catch (IOException | ClassNotFoundException e) {
if (errorCallback != null)
errorCallback.onError(e);
}
}
}
public interface MessageReceivedCallback {
public interface MessageReceivedCallback {
void onMessageReceived(Message msg);
}
public interface MessageSentCallback {
void onMessageSent();
}

View file

@ -11,9 +11,9 @@ import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListView;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
@ -65,7 +65,7 @@ public class UserListController implements Initializable {
new PeerUser("Dodo1"),
new ActiveUser("Coucou2", InetAddress.getLocalHost())
);
} catch (UnknownHostException e) {
} catch (IOException e) {
e.printStackTrace();
}
if (activeList != null) {

View file

@ -3,6 +3,7 @@ package fr.insa.clavardator.users;
import fr.insa.clavardator.chat.Message;
import fr.insa.clavardator.network.PeerConnection;
import java.io.IOException;
import java.net.InetAddress;
@ -10,7 +11,7 @@ public class ActiveUser extends PeerUser {
private transient PeerConnection connection;
public ActiveUser(String username, InetAddress ipAddr) {
public ActiveUser(String username, InetAddress ipAddr) throws IOException {
super(username);
connection = new PeerConnection(ipAddr);
}
@ -19,6 +20,7 @@ public class ActiveUser extends PeerUser {
* @param message
*/
public void sendMessage(Message message) {
// connection.sendMessage(message);
}

View file

@ -2,9 +2,11 @@ package fr.insa.clavardator.users;
import fr.insa.clavardator.db.DatabaseController;
import fr.insa.clavardator.network.NetDiscoverer;
import fr.insa.clavardator.util.ErrorCallback;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.util.ArrayList;
import java.util.function.Predicate;
@ -47,12 +49,17 @@ public class UserList {
/**
*
*/
public void discoverActiveUsers() {
public void discoverActiveUsers(ErrorCallback errorCallback) {
NetDiscoverer.discoverActiveUsers("CLAVARDATOR_BROADCAST", (ipAddr, data) -> {
ActiveUser newUser = new ActiveUser("", ipAddr); // TODO find username
ActiveUser newUser = null;
try {
newUser = new ActiveUser("", ipAddr); // TODO find username
} catch (IOException e) {
errorCallback.onError(e);
}
activeUsers.add(newUser);
pcs.firePropertyChange("activeUsers", null, newUser);
});
}, errorCallback);
}
}

View file

@ -0,0 +1,5 @@
package fr.insa.clavardator.util;
public interface ErrorCallback {
void onError(Exception e);
}

View file

@ -3,6 +3,7 @@ package fr.insa.clavardator.util;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
@Deprecated
public class ErrorHandler {
private ErrorHandler() {}