ChatApp-AL-NM/Implementation/src/Protocoles/UDPEchange.java

358 lines
15 KiB
Java

package src.Protocoles;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import src.Controller.*;
/**
* <p>
* Classe representant les echanges UDP entre utilisateurs.
* </p>
*/
public class UDPEchange {
private static Boolean Connecte = true;
// True si l'utilisateur peut se connecter avec ce nom d'utilisateur , False sinon
/**
* Getter
* @return le boolean connecte (True s'il peut se connecter avec ce nom d'utilisateur , False sinon)
*/
public static Boolean getConnecte() {
return Connecte;
}
/**
* Setter
* @param value La nouvelle valeur du boolean de connexion
*/
public static void setConnecte(Boolean value) {
Connecte = value ;
}
private static Boolean PseudoValide = true;
// True si l'utilisateur a (ou demande) un pseudo valide , False sinon
/**
* Getter
* @return le boolean PseudoValide (True s'il peut utiliser ce pseudo , False sinon)
*/
public static Boolean getPseudoValide() {
return PseudoValide;
}
/**
* Setter
* @param value La nouvelle valeur du boolean concernant le pseudo valide
*/
public static void setPseudoValide(Boolean value) {
PseudoValide = value ;
}
public static InetAddress getCurrentIp() {
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) networkInterfaces
.nextElement();
Enumeration<InetAddress> nias = ni.getInetAddresses();
while(nias.hasMoreElements()) {
InetAddress ia= (InetAddress) nias.nextElement();
if (!ia.isLinkLocalAddress()
&& !ia.isLoopbackAddress()
&& ia instanceof Inet4Address) {
return ia;
}
}
}
} catch (Exception e) {
System.out.println("unable to get current IP " + e.getMessage());
}
return null;
}
/**
* <p>
* Méthode permettant d'envoyer un message à tout les utilisateurs
* a l'aide du protocole UDP
* </p>
* @param broadcastMessage correspond au message a transmettre aux utilisateurs
*/
public static void EnvoiBroadcast(String broadcastMessage) throws IOException {
int port = 1234 ;
// Envoie en broadcast à tous les utilsateurs
for (InetAddress broadcastAddr : listAllBroadcastAddresses()) {
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
byte[]buffer = broadcastMessage.getBytes();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length, broadcastAddr,port);
socket.send(packet);
socket.close();
System.out.println("Broadcast sent with address " + broadcastAddr.toString());
System.out.println("***********Message envoye***********");
System.out.println("Dest Ip: " + broadcastAddr.toString());
System.out.println("Dest port: " + String.valueOf(port));
System.out.println("Contenu: ");
System.out.println(broadcastMessage);
System.out.println("************************************");
}
}
/**
* <p>
* Methode permettant la reception de messages d'utilisateurs
* a l'aide du protocole UDP
* </p>
* @param app L'application de chat de l'utilisateur qui receptionne le message
*/
public static void ecouteUDP(ChatApp app)
{
DatagramSocket socket = null;
ExecutorService exec = Executors.newFixedThreadPool(1000);
try {
socket = new DatagramSocket(1234);
} catch (SocketException e1) {
e1.printStackTrace();
}
byte buffer[] = new byte[1024];
System.out.println("Ecoute sur le port: 1234");
while(true)
{
DatagramPacket data = new DatagramPacket(buffer,buffer.length);
try {
socket.receive(data);
} catch (IOException e) {
e.printStackTrace();
}
// Un thread est lance à chaque reception d'un message
System.out.println("Message recu!");
exec.submit(new RunnerUDP(data,app));
}
}
/**
* <p>
* Methode permettant d'envoyer un message a utilisateur en particulier
* a l'aide du protocole UDP
* </p>
* @param Adress l'addresse de l'utilisateur
* @param Message correspond au message à transmettre a l'utilisateur
*/
public static void envoiUnicast( InetAddress Adress , String Message ) throws IOException {
DatagramSocket socket = new DatagramSocket();
byte[]buffer = Message.getBytes();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length, Adress, 1234 );
socket.send(packet);
socket.close();
System.out.println("***********Message envoye***********");
System.out.println("Dest Ip: " + Adress.toString());
System.out.println("Dest port: " + String.valueOf(1234));
System.out.println("Contenu: ");
System.out.println(Message);
System.out.println("************************************");
}
/**
* <p>
* Methode permettant de recuperer la liste des adresses de broadcast, chacune associer à une interface de la machine
* </p>
*/
static List<InetAddress> listAllBroadcastAddresses() throws SocketException {
List<InetAddress> broadcastList = new ArrayList<>();
Enumeration<NetworkInterface> interfaces
= NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
networkInterface.getInterfaceAddresses().stream()
.map(a -> a.getBroadcast())
.filter(Objects::nonNull)
.forEach(broadcastList::add);
}
return broadcastList;
}
}
/**
* <p>
* Classe implementant l'interface Runnable.
* Contient les traitements a executer dans un thread lancer par des methodes de la class UDPEchange
* </p>
*/
class RunnerUDP implements Runnable {
final DatagramPacket data ;
ChatApp app ;
public RunnerUDP(DatagramPacket data, ChatApp app) {
this.data= data;
this.app = app ;
}
/**
* <p>
* Methode qui redefinie les traitements qui seront executes dans le thread:
* Met à jour la liste des utilisateurs actifs
* </p>
*
*/
@Override
public void run() {
System.out.println("Thread started");
String received = new String(data.getData(), 0, data.getLength());
System.out.println("***********Message recu***********");
System.out.println(received);
System.out.println("**********************************");
String Type = received.split("\n")[0];
//****************************************************************************************************
//****************************************************************************************************
//****************************************Demande de connexion****************************************
//****************************************************************************************************
//****************************************
if (Type.equals("Connexion")) { // un utilisateur vient d'arriver sur le reseau
System.out.println("Reception d'une demande de connexion");
Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! u.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String reponse = "Reponse Connexion\n";
if (!( app.getActifUsers() ).verifierUnicite(u.getPseudo())) {
System.out.println("Pseudo deja present dans la liste");
reponse += "false\n";
}
else {
System.out.println("Ajout d'un nouvel utilisateur dans la liste des Utilisateurs");
( app.getActifUsers() ).addList(u);
reponse += "true\n";
}
reponse += app.getMe().toString();
try {
UDPEchange.envoiUnicast(u.getIp(),reponse);
}catch(IOException e)
{
System.out.println("Echec de l'envoi du message");
}
( app.getActifUsers() ).afficherListeUtilisateurs();
}
}
//*******************************************************************************************************
//*******************************************************************************************************
//****************************************Reponse d'une connexion****************************************
//*******************************************************************************************************
//*******************************************************************************************************
if (Type.equals("Reponse Connexion")) { // Un utilisateur te repond suite à ta demande de connexion
if((received.split("\n")[1]).equals("true")) {
Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[2]);
app.getActifUsers().addList(u);
app.getActifUsers().afficherListeUtilisateurs();
}
else {
System.out.println("Pseudo deja pris");
UDPEchange.setConnecte(false);
}
}
//*******************************************************************************************************************
//*******************************************************************************************************************
//****************************************Demande de modification d'un pseudo****************************************
//*******************************************************************************************************************
//*******************************************************************************************************************
if (Type.equals("Demande Modification Pseudo")) {
Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String nouveau = received.split("\n")[2] ;
String Message = "";
if(( app.getActifUsers() ).verifierUnicite(nouveau)) {
Message = "Bon Choix Pseudo\n" + nouveau ;
}
else {
Message = "Mauvais Choix Pseudo\n" ;
}
System.out.println(Message);
try {
UDPEchange.envoiUnicast(Source.getIp(),Message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
//************************************************************************************************************
//************************************************************************************************************
//**************************************** Modification pseudo reussi ****************************************
//************************************************************************************************************
//************************************************************************************************************
if (Type.equals("Modification pseudo reussi")) {
Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String nouveau = received.split("\n")[2] ;
if(app.getActifUsers().appartient(Source)) { // On verifie d'abord que Source appartient bien a la liste des utilisateurs actifs
app.getActifUsers().modifierList(Source.getPseudo(), nouveau);
}
{
// Suite a une perte d'un message lors d'une connexion l'utilisateur Source n'apparait pas dans la liste
app.getActifUsers().addList(Source);
}
}
}
//*********************************************************************************************************
//*********************************************************************************************************
//****************************************Mauvais choix d'un pseudo****************************************
//*********************************************************************************************************
//*********************************************************************************************************
if (Type.equals("Mauvais Choix Pseudo")) {
System.out.println("Ce choix de pseudo est déjà pris il te faut en choisir un autre");
UDPEchange.setPseudoValide(false);
}
//******************************************************************************************************************
//******************************************************************************************************************
//****************************************Bon choix d'un pseudo*****************************************************
//******************************************************************************************************************
//******************************************************************************************************************
if (Type.equals("Bon Choix Pseudo")) {
// Il n'y a rien a faire ici
}
//*********************************************************************************************************
//*********************************************************************************************************
//****************************************Demande d'une deconnexion****************************************
//*********************************************************************************************************
//*********************************************************************************************************
if (Type.equals("Deconnexion")) {
( app.getActifUsers() ).supprimerList(Utilisateur.stringToUtilisateur(received.split("\n")[1]));
}
}
}