/* Programma:     cliente_chat
*  Autore:        FF
*  Data:          08/02/2006
*  Descr.:        Esempio di cliente TCP che chiede una connessione
*                 a un servente per scmbiare messaggi con altri clienti; 
*                 determina l'IP del servente dal nome; usa select
*                 per gestire il mutiplexing fra tastiera e socket di rete
*/
#include "utilsock.h"
/* utilsock.h contiene tutte le inclusioni delle altre librerie necessarie
*  e le funzioni di lettura e scrittura dal socket
*/
#include <netdb.h>
#include <sys/select.h>
#define MAX        256

int main(int argc, char *argv[])
{
    int sd,l;
    struct sockaddr_in serv_ind;
    struct hostent *ipserv;    
    in_port_t porta;
    char msg[MAX];
    int msglun=MAX;
    fd_set setl,setw,sete;
    printf("\033[2J\033[H");
    // controlla argomenti
    if (argc !=3) {
        printf("\nErrore\n");
           printf("Esempio di connessione: \n");
        printf("./client nome_servente porta (>1023)\n");
        printf("Premere Invio\n");
        getchar();
        exit(-1);
    }
    ipserv=gethostbyname(argv[1]);    // trova IP servente in base al nome
    // crea socket 
    if ( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Errore in creazione socket");
        exit(-1);
    }
    // indirizzo IP
    memset((void *)&serv_ind, 0, sizeof(serv_ind)); // pulizia ind
    serv_ind.sin_family = AF_INET;                  // ind di tipo INET 
    porta = atoi(argv[2]);
    serv_ind.sin_port = htons(porta);               // porta a cui collegarsi
    memcpy(&serv_ind.sin_addr.s_addr,ipserv->h_addr,ipserv->h_length);
    // copiato ip servente dalla struct ipserv a serv_ind.sin_addr
    // stabilisce la connessione
    if (connect(sd, (struct sockaddr *)&serv_ind, sizeof(serv_ind)) < 0) {
        perror("Errore nella connessione");
        exit(-1);
    }
    printf("Connessione stabilita con %s\n",inet_ntoa(serv_ind.sin_addr));
    printf("Per terminare digitare il messaggio: /ciao\n");    
    while (1)
    {
           FD_ZERO (&setl);      // azzera i set; solo setl viene davvero usato
           FD_ZERO (&setw);
           FD_ZERO (&sete);
           FD_SET(fileno(stdin),&setl); // aggiunge descrittore di stdin in setl
           FD_SET(sd,&setl);
           if (select(FD_SETSIZE,&setl,&setw,&sete, NULL)<0) {
              perror("Errore nella select");
              exit(1);
           }
           if (FD_ISSET(fileno(stdin),&setl)) {    // tastiera
              for(l=0;((msg[l]=getchar())!='\n' && l<MAX-1);l++);
              msg[l]='\0';
            if (strcmp("/ciao",msg)==0) {
                printf("Fine\n");
                break;
            }    
            scrivisock(sd,msg,MAX);
            printf("<---- OK\n");
        }
           if (FD_ISSET (sd,&setl)) {          
            if ( (read(sd,msg,msglun))<=0 ) {
                perror("Errore nella read");
                exit(-1);
            }    
             printf("%s\n",msg); 
        }
    } 
    close(sd);
    exit(0);
}

