Talk.java
//Progetto Ingegneria del Software
//Autore: Ignazio Coco
//Matricola: 616/000075
import java.io.*;
import java.net.*;
/**
 * Classe che implementa il lato client dell"applicazione
 * @author Ezio
 */
public class Talk {
    /**
     * Questo parametro permette di impostare il programma in modalità
     * di debug. Ciò comporta la visualizzazione di tutti i messaggi
     * durante la fase di esecuzione
     */    
    private static boolean debug=true;
    /**
     * identifica l"utente con cui si vuuole instaurare la connessione
     */    
    static String utente;
    /**
     * identifica l"indirizzo Ip dell"utente a cui ci vuole connettere
     */    
    static String indirizzoIp;
    /**
     * indentifica la porta dell"utente a cui ci si vuole connettere
     */    
    static int porta;
    /**
     * stream verso l"utente a cui ci si è connessi
     */    
    static DataOutputStream streamConnOut;
    /**
     * variabile usata per mantenere i riferimenti alle socket,
     * prima del server dei nomi, poi dell"utente con il quale si vuole
     * chattare
     */    
    static public Socket socket;
    /**
     * mantiene l"indirizzo Ip del server dei nomi
     */    
    static String indIp;
    /** Creates a new instance of Talk */
    public Talk() {
    }
    /**
     * metodo usato per disconnettersi dall"utente con cui si dialoga
     * @return Ritorna 0 o -1 nel caso in cui l"operazione abbia avuto
     * successo o meno
     */    
    static int disconnect() {
        try {
            socket.close();
            streamConnOut.close();
            return 0;
        }
        catch (IOException e) {
            if (debug) System.out.println("Errore durante il tentativo di disconnessione dal server");
            if (debug) System.out.println(e);
            return -1;
        }
    }
    /**
     * Avvia prima una connessione col server dei nomi, cercando di ottenere
     * l"ip associato all"utente.
     * Successivamente instaura la connessione verso l"utente
     * @param nomeUtente Il nome dell"utente a cui ci si vuole connettere
     * @return 0: l"operazione ha avuto esito positivo
     * -1: l"operazione ha generato un errore
     * -2: l"utente non è online
     */    
    static int connect(String nomeUtente) {
        if (debug) System.out.println("Inizio connect server nomi");
        if (debug) System.out.println("Instaurazione socket - server nomi");
        try {
            socket = new Socket(indIp, 5555);
        }
        catch (UnknownHostException e) { 
            if (debug) System.out.println("Errore host sconosciuto");
            if (debug) System.out.println(e);
            return -1;
        }
        catch (IOException e) { 
            if (debug) System.out.println("Errore I/O su socket - server nomi");
            if (debug) System.out.println(e);
            return -1;
        }
        if (debug) System.out.println("Apertura stream - server nomi");
        try {
            streamConnOut = new DataOutputStream(socket.getOutputStream());
            streamConnOut.writeBytes("retrieveIp:"+nomeUtente + "\n");
            DataInputStream is = new DataInputStream(socket.getInputStream());
            String mess = is.readLine();
            if ((mess.substring(0,3)).equals("###")) return -2;
            String tmp[] = mess.split(":");
            if (debug) System.out.println("Messaggio ricevuto: "+mess);
            indirizzoIp=tmp[1];
            porta=Integer.parseInt(tmp[2]);
            is.close();
            streamConnOut.close();
            socket.close();
        }
        catch (IOException e) { 
            if (debug) System.out.println("Errore I/O su stream - server nomi");
            if (debug) System.out.println(e);
            return -1;
        }
        if (debug) System.out.println("Inizio connect");
        if (debug) System.out.println("Instaurazione socket");
        try {
            socket = new Socket(indirizzoIp, porta);
        }
        catch (UnknownHostException e) { 
            if (debug) System.out.println("Errore host sconosciuto");
            if (debug) System.out.println(e);
            return -1;
        }
        catch (IOException e) { 
            if (debug) System.out.println("Errore I/O su socket");
            if (debug) System.out.println("IP:" + indirizzoIp + " Porta:" + porta);
            if (debug) System.out.println(e);
            return -1;
        }
        if (debug) System.out.println("Apertura stream");
        try {
            streamConnOut = new DataOutputStream(socket.getOutputStream());
            System.out.println("Connesso con " + utente + " IP:" + indirizzoIp + " porta:" + porta);
        }
        catch (IOException e) { 
            if (debug) System.out.println("Errore I/O su stream");
            if (debug) System.out.println(e);
            return -1;
        }
        if (debug) System.out.println("Connesso!");
        return 0;
    }
    /**
     * Metodo usato per inviare un messaggio
     * @param message il messaggio da inviare
     * @return 0: l"operazione ha avuto esito positivo
     * -1: l"operazione ha generato un errore
     */    
    static int sendMessage(String message) {
        try {
            streamConnOut.writeBytes(message + "\n");
            return 0;
        }
        catch (IOException e) {
            if (debug) System.out.println("Errore durante l"invio del messaggio");
            if (debug) System.out.println(e);
            return -1;
        }
    }
    /**
     * Il metodo principale del programma
     * @param args Argomenti da passare al programma, nell"ordine:
     * nome, indirizzo Ip del server dei nomi
     */    
    public static void main(String args[]) {
        utente=args[0];
        indIp=args[1];
        if (utente.equals("")) {
            System.out.println("Errore: deve inserire il nome dell"utente");
            System.exit(-1);
        }
        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        if (debug) System.out.println("Connessione...");
        int res = connect(utente);
        if (res==0) {
            if (debug) System.out.println("Connesione avvenuta correttamente");
        }
        else if (res==-2) {
            if (debug) System.out.println("Errore: impossibile trovare l"utente");
            System.exit(-1);
        }
        else {
            if (debug) System.out.println("Errore: impossibile connettersi al server dei nomi");
            System.exit(-1);
        }
        String message;
        if (debug) System.out.println("Inizio Chat");
        while (true) {
            try {
                System.out.print("Digita:: ");
                message = stdIn.readLine();
                if (message.equals("")) {
                    if (disconnect()==0) { if (debug) System.out.println("Disconnessione avvenuta in modo corretto");}
                    else if (debug) System.out.println("Errore invio messaggio");
                    System.exit(0);
                }
                if (sendMessage(message)==0) {
                    if (debug) System.out.println("Messaggio inviato correttamente");
                }
                else {
                    if (debug) System.out.println("Messaggio non inviato");
                    System.exit(-1);
                }
            }
            catch (IOException e) { 
                if (debug) System.out.println("Errore I/O in main");
                if (debug) System.out.println(e);
                System.exit( -1);
            }
        }
    }
}