123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- package controller;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.InetAddress;
- import java.net.Socket;
- import java.net.URISyntaxException;
- import java.net.UnknownHostException;
- import java.sql.SQLException;
- import java.text.DateFormat;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Calendar;
- import java.util.Date;
-
- import javax.swing.JOptionPane;
- import javax.websocket.DeploymentException;
-
- import model.Chat;
- import model.LocalUser;
- import model.Message;
- import model.Msg_Text;
- import model.RemoteUser;
- import view.Interface;
- import websocket.Appel;
-
- public class Controller {
-
- /*** CONSTANTES ***/
- final int NB_SECOND_WAITING_RESPONSE_BROADCAST = 1;
-
- // TO REMOVE when we use broadcast
- final static int portUDPlistening_remoteUsr1 = 31001;
- final static int portUDPlistening_remoteUsr2 = 31002;
- final static int portUDPlistening_remoteUsr3 = 31003;
- final static int portUDPlistening_local = 31004;
- final static int [] tabBroadcast = {portUDPlistening_remoteUsr1,portUDPlistening_remoteUsr2,portUDPlistening_remoteUsr3,portUDPlistening_local};
-
- public Boolean interfaceRunning = false;
- /*** ATTRIBUTS ***/
- protected LocalUser myUser;
- protected Interface view;
- private TListeningUDP udp_connect_thread;
- private TListeningTCPConnection tcp_connect_thread;
- private Historique histoire;
- protected Chat activeChat;
-
- /**
- * Constructor of Controller
- * @parametres
- * @param portUDPsend : int => le numéro de port pour envoyer ces informations lors d'un changements ou d'une nouvelle connexion
- * @param portUDPlistening : int => le numéro de port pour recevoir les informations des nouveaux utilisateurs ou les changements
- * @param portTCP : int => le numéro de port pour commencer une nouvelle conversation
- * @throws IOException
- * @descrition
- * <p>
- * On récupère l'adresse de la machine, on demande un pseudo à l'utilisateur que l'on vérifie
- * Une fois validé l'utilisateur devient actif :
- * - écoute UDP pour les pseudos
- * - écoute TCP pour de nouvelles conversation
- * - notification aux autres utilisateurs actifs
- * </p>
- */
- private Controller(int portUDPsend,int portUDPlistening,int portTCP,Historique histoire) throws IOException {
- this.histoire= histoire;
-
- // Récupération de l'adresse IP local
- InetAddress addIP = null;
- try
- {
- addIP = InetAddress.getLocalHost();
- }
- catch(UnknownHostException e) {
- JOptionPane.showMessageDialog(null ,"Could not find local address!");
- }
-
- // Création de l'utilisateur
- this.myUser = new LocalUser("Unknown",addIP,portUDPsend,portUDPlistening,portTCP);
-
- try {
- this.myUser.setPseudo(this.initPseudo()); // Initialisation du pseudo manuel
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- // Création des threads d'écoutes
- this.udp_connect_thread = new TListeningUDP("UDP Listening thread",this);
- this.udp_connect_thread.start();
- this.tcp_connect_thread = new TListeningTCPConnection("TCP main Listening thread",this);
- this.tcp_connect_thread.start();
-
- // Notification des utilisateurs distants
- notify_remote_users();
-
- // Création de l'interface
- interfaceRunning =true;
- view=Interface.createAndShowGUI(this);
- }
-
- /**
- * Constructor of Controller
- * @parametres
- * @param portUDPsend : int => le numéro de port pour envoyé ces informations lors d'un changements ou d'une nouvelle connexion
- * @param portUDPlistening : int => le numéro de port pour recevoir les informations des nouveaux utilisateurs ou les changements
- * @param portTCP : int => le numéro de port pour commencer une nouvelle conversation
- * @descrition
- * <p>
- * On récupère l'adresse de la machine, on demande un pseudo à l'utilisateur que l'on vérifie
- * Une fois validé l'utilisateur devient actif :
- * - écoute UDP pour les pseudos
- * - écoute TCP pour de nouvelles conversation
- * - notification aux autres utilisateurs actifs
- * </p>
- */
- private Controller(int portUDPsend,int portUDPlistening,int portTCP,String pseudo,Historique histoire) throws IOException{
-
- this.histoire=histoire;
-
- // Récupération de l'adresse IP local
- InetAddress addIP = null;
- try
- {
- addIP = InetAddress.getLocalHost();
-
- }
- catch(UnknownHostException e) {
- JOptionPane.showMessageDialog(null ,"Could not find local address!");
- }
-
- // Création de l'utilisateur
- this.myUser = new LocalUser(pseudo,addIP,portUDPsend,portUDPlistening,portTCP);
- try {
- if(this.validatePseudo(pseudo)) {
-
-
- this.udp_connect_thread = new TListeningUDP("UDP Listening thread",this);
- this.udp_connect_thread.start();
-
- this.tcp_connect_thread = new TListeningTCPConnection("TCP main Listening thread",this);
- this.tcp_connect_thread.start();
-
-
- // Notification des utilisateurs distants
- notify_remote_users();
-
- // Création de l'interface
- interfaceRunning =true;
- view=Interface.createAndShowGUI(this);
- }
- else {
- System.out.println("Unavailable "+pseudo);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
-
- /*** GETTERS ***/
- public LocalUser getMyUser() {
- return myUser;
- }
- public Interface getview() {
- return view;
- }
- public TListeningUDP getUdp_connect_thread() {
- return udp_connect_thread;
- }
- public TListeningTCPConnection getTcp_connect_thread() {
- return tcp_connect_thread;
- }
- public Historique getHistory() {
- return histoire;
- }
-
- /*** SETTERS ***/
- public void setMyUser(LocalUser myUser) {
- this.myUser = myUser;
- }
- public void setview(Interface view) {
- this.view = view;
- }
- public void setUdp_connect_thread(TListeningUDP udp_connect_thread) {
- this.udp_connect_thread = udp_connect_thread;
- }
- public void setTcp_connect_thread(TListeningTCPConnection tcp_connect_thread) {
- this.tcp_connect_thread = tcp_connect_thread;
- }
- public void setHistory(Historique histoire) {
- this.histoire=histoire;
- }
-
- /**************************** Initialisation pseudo et découverte utilisateur distant (+notification utilisateurs distants) **********************************/
-
- /** initPseudo
- * <p>
- * Demande à l'utilisateur de rentrer un pseudo et valide de ce dernier en demandant aux
- * utilisateurs distants leurs informations
- * </p>
- */
- public String initPseudo() throws IOException {
- String tmpPseudo = JOptionPane.showInputDialog(null, "Enter nickname:"); // Read user input
-
- while(!(this.validatePseudo(tmpPseudo))) { // On demande aux autres utilisateurs de nous envoyer leurs informations et on test si le pseudo est déjà utilisé
- tmpPseudo = JOptionPane.showInputDialog(null, "Enter another nickname:"); // Read user input
- }
-
- //sc1.close();
- JOptionPane.showMessageDialog(null ,"Your nickname : " + tmpPseudo + " is valid !");
-
- return tmpPseudo;
- }
-
- /** changePseudo
- * <p>
- * Demande à l'utilisateur de rentrer un pseudo et valide de ce dernier en demandant aux
- * utilisateurs distants leurs informations.
- * On regarde si le pseudo est bien différent de l'ancien
- * </p>
- */
- public void changePseudo() throws IOException {
- String oldPseudo = this.myUser.getPseudo(); //Saves the old one for comparison
-
- String tmpPseudo = view.ChangePseudotextField.getText(); // Read user input
-
- if(!(this.validatePseudo(tmpPseudo)) || tmpPseudo.equals(oldPseudo)) {
- view.Pseudolabel.setText("Already exists, enter another nickname. Your current username is: " + oldPseudo); // Read user input
- tmpPseudo = view.ChangePseudotextField.getText(); // Read user input
- }
- else {
- this.myUser.setPseudo(tmpPseudo);
- JOptionPane.showMessageDialog(null ,"Your new nickname : " + tmpPseudo + " is valid !");
- this.notify_remote_users();
- }
- }
-
-
- /** validatePseudo
- * <p>
- * *tmpPseudo : String => Le pseudo à valider
- *</p><p>
- * Envoi en broadcast (pour l'instant envoi sur les ports de notre ordinateur) d'une demande d'information
- *</p><p>
- * On attend les réponses pendant 5 secondes
- *</p><p>
- * On valide le pseudo en fonction des pseudos reçu
- *</p><p>
- * On en profite pour ajouter les utilisateurs répondant à notre liste d'utilisateur distant (RemoteUser)
- * </p>
- */
- public Boolean validatePseudo(String tmpPseudo) throws IOException {
- Boolean valid = true;
-
- DatagramSocket dgramSocket = new DatagramSocket(this.myUser.getPortUDPsend(),this.myUser.getAddIP());
-
- // Création du message à envoyer
- String toSend = this.myUser.getAddIP().getHostAddress()+":"+this.myUser.getPortUDPsend()+":info";
-
- // Broadcast du message
- broadcast(dgramSocket,toSend);
-
- /*** For 5 seconds wait for answer : validate pseudo & add to userlist ***/
- byte[] buffer = new byte[256];
- DatagramPacket inPacket;
- String response = null;
- String[] tabresponse= new String [4];
- dgramSocket.setSoTimeout(1000);
- Boolean arecu;
- int nbReponse =0;
- System.out.println("("+myUser.getPseudo()+") Waiting for pseudo validation ...");
- Date oldDate = new Date();
- Date newDate = new Date();
-
- while( (newDate.getTime()-oldDate.getTime()) < NB_SECOND_WAITING_RESPONSE_BROADCAST*1000 && valid) {
- nbReponse++;
- inPacket= new DatagramPacket(buffer, buffer.length);
- arecu=true;
- try{
- dgramSocket.receive(inPacket);
- }catch (Exception e) {
- arecu=false;
- }
-
- buffer = inPacket.getData();
- response = new String(buffer);
- if(arecu) {
- // On découpe la réponse en tableau de string ([adresseIP,tcpPort,nickname])
- tabresponse = response.split(":");
- // Si reception on ajoute l'utilisateur à notre liste d'utilisateur distant
- this.myUser.addRemoteUser(InetAddress.getByName(tabresponse[0]),Integer.parseInt(tabresponse[1]),tabresponse[2]);
- valid= (tmpPseudo.compareTo(tabresponse[2])!=0); // On regarde la différence entre notre pseudo et le pseudo reçu
- }
- newDate = new Date();
- }
-
-
- dgramSocket.close();
- if(!valid) {
- JOptionPane.showMessageDialog(null ,"Nickname : "+tmpPseudo +" is taken !");
- }
- return valid;
- }
-
- /***broadcast
- *
- * @param dgramSocket
- * @param toSend
- * @param broadcastIP
- * @throws IOException
- * <p>
- * Simulation of broadcast with port given (tabBroadcast)
- * <p>
- */
- public void broadcast(DatagramSocket dgramSocket,String toSend) throws IOException {
- InetAddress broadcastIP = InetAddress.getLocalHost();
- DatagramPacket outPacket = null;
- int tabBroadcastSize = tabBroadcast.length;
- for(int i=0;i<tabBroadcastSize;i++) {
- if(tabBroadcast[i]!=myUser.getPortUDPlistening()) {
- outPacket= new DatagramPacket(toSend.getBytes(), toSend.length(),broadcastIP, tabBroadcast[i]);
- dgramSocket.send(outPacket);
- }
- }
- }
-
- /** notify_remote_users
- * <p>
- * En utilisant le port UDP d'envoi, on envoie en broadcast les informations nous concernant
- * </p>
- * @throws IOException
- */
- public void notify_remote_users() throws IOException {
- DatagramSocket dgramSocket= null;
- try {
- dgramSocket= new DatagramSocket(this.myUser.getPortUDPsend(),this.myUser.getAddIP());
- } catch (IOException e) {
- e.printStackTrace();
- }
- // Send to other active user (simulation of broadcast)
- String toSend = this.myUser.getAddIP().getHostAddress()+":"+this.myUser.getPortTCP()+":"+this.myUser.getPseudo()+":notify";
- broadcast(dgramSocket,toSend);
- dgramSocket.close();
- }
-
-
- /**************************** Gestion des sessions **********************************/
-
- public Chat openSession(RemoteUser rm) {
- Chat c = myUser.addChats(rm); // Create chat and add it to myUser
-
- /*** Create socket send => ask connection to server of rm ***/
- Socket link=null;
- try {
- // Connection => server tcp rm
- System.out.println("("+this.myUser.getPseudo()+") Connecting to "+c.getRemoteUser().getPortTCP()+" of " + c.getRemoteUser().getPseudo());
- link=new Socket(c.getRemoteUser().getAddIP(),c.getRemoteUser().getPortTCP()/*, InetAddress.getLocalHost() ,myUser.getPortTCP()*/);
- c.setSocket(link);
- // Sending data for identification (TO REMOVE IF != IP)
- sendInfoProcess(Integer.toString(myUser.getPortTCP()), c); // tell rm session STOP
- }catch(IOException e) {
- System.out.println("Error linking to TCP server of "+ c.getRemoteUser().getPortTCP());
- }
-
-
- /*** recup history and put it in model ***/
- try {
- try {
- c.addListMessage(this.getHistory().retrieveMessage(getMyUser(), c.getRemoteUser()));
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- } catch (SQLException e) {
- System.out.println("souci avec le retrieveMsgSQL");
- e.printStackTrace();
- }
- return c;
- }
-
-
-
- public String askOpenSession(int index) {
- String history="";
- RemoteUser rm = myUser.getRemoteUsersList().get(index);
- Chat c;
-
- /*** Recup or create chat ***/
- if(myUser.getChatIndexOf(rm)!=-1) { // if already a chat open
- c = myUser.getChats().get(myUser.getChatIndexOf(rm));
- JOptionPane.showMessageDialog(null ,"Active session with "+c.getRemoteUser().getPseudo()+" loading history");
- }
- else { // else create it
- c=openSession(rm);
- JOptionPane.showMessageDialog(null ,"New session with "+rm.getPseudo());
- }
-
- // Look for history
-
- int nbMessage = c.getMessages().size();
- for(int i=0;i<nbMessage;i++) {
- history+="\n("+c.getMessages().get(i).getDate()+")\n"+c.getMessages().get(i).getAutor().getPseudo()+" : "+c.getMessages().get(i).getMessage();
- }
- this.activeChat = c;
-
- return history;
- }
-
-
-
-
-
- public void askCloseSession() {
- closeSession(this.activeChat);
- this.activeChat = null;
- }
- public void closeSession(Chat c) {
- sendInfoProcess("end", c); // tell rm session STOP
- JOptionPane.showMessageDialog(null ,"Close session with "+c.getRemoteUser().getPseudo());
- this.myUser.closeChat(c);
- }
-
- /**************************** Gestion des messages **********************************/
-
- public void askToSend(String textMessage){
- sendMessage(new Msg_Text(myUser,textMessage), this.activeChat);
- }
- public void sendMessage(Message msg,Chat c) {
- /*** Init send process ***/
- PrintWriter out=null;
- try {
- out = new PrintWriter(c.getUserSocket().getOutputStream(),true);
- } catch (IOException e) {
- e.printStackTrace();
- }
- c.addMessage(msg);
-
- // TODO check if instance of Msg_Text or anything else and threat it given a type
- String message = (String) msg.getMessage();
-
- // Sauvegarde dans la base de données
- DateFormat dateFormat = new SimpleDateFormat("yyyy MM dd HH mm ss");
- Date date=new Date();
- this.getHistory().saveMessage(getMyUser(), c.getRemoteUser(),message ,dateFormat.format(date));
-
- // Send message
- out.println(message);
-
- }
-
- public void sendInfoProcess(String msg,Chat c) {
- PrintWriter out=null;
- try {
- out = new PrintWriter(c.getUserSocket().getOutputStream(),true);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- out.println(msg);
-
- }
- /*
- public String askNewMessage() {
- String message = "";
- return message;
- }*/
-
-
- public String [] askUpdateActiveUsers() {
- String[] pseudotab = new String[myUser.getRemoteUsersList().size()];
- int size = myUser.getRemoteUsersList().size();
- for(int i=0; i < size; i++) {
- pseudotab[i] = myUser.getRemoteUsersList().get(i).getPseudo();
- }
- return pseudotab;
- }
-
- public void askForClose() {
- interfaceRunning = false;
- close();
- }
- public void close() {
- if(interfaceRunning) {
- myUser.closeAllChat();
- tcp_connect_thread.close();
- udp_connect_thread.close();
- }
-
- }
-
- public static void main(String[] args) throws IOException, InterruptedException {
-
- System.out.println("start program");
-
- Historique histoire=new Historique();
-
- /** Création des utilisateurs **/
- ArrayList<Controller> lstCtr = new ArrayList<Controller>();
-
- // REMOTE USERS
- Controller ctr1 = new Controller(31011,portUDPlistening_remoteUsr1,31021,"Theau",histoire);
- lstCtr.add(ctr1);
- Controller ctr2 = new Controller(31012,portUDPlistening_remoteUsr2,31022,"Leonie",histoire);
- lstCtr.add(ctr2);
- Controller ctr3 = new Controller(31013,portUDPlistening_remoteUsr3,31023,"Alexandre",histoire);
- lstCtr.add(ctr3);
-
- // LOCAL USER
- Controller ctr = new Controller(31014,portUDPlistening_local,31024,histoire);
- lstCtr.add(ctr);
-
- Appel app=new Appel();
- app.test();
-
- /** Loop **/
- Boolean running = isRunning(lstCtr);
- while(running) {
- running = isRunning(lstCtr);
- }
-
- System.out.println("Fin de la boucle");//TOREMOVE
-
- /** End - Close thread and socket for every controller**/
- closeThreads(lstCtr);
- System.out.println("end program");
- JOptionPane.showMessageDialog(null ,"END");
- }
-
- static boolean isRunning(ArrayList<Controller> lstCtr){
- boolean isRunning=false;
- for(Controller ctr : lstCtr) {
- isRunning|=ctr.interfaceRunning;
- }
- return isRunning;
- }
-
- static void closeThreads(ArrayList<Controller> lstCtr) {
- for(Controller ctr : lstCtr) {
- ctr.close();
- }
- }
-
- }
-
|