Contents

###############################################################################
Programma della conferenza distribuita

Copyright (C) 19aa  
Autori: Andrea Lanzi, Giampaolo Fresi Roglia

Questo programma e' software  libero; e' lecito ridistribuirlo e/o
modificarlo secondo i  termini della Licenza Pubblica Generica GNU
come pubblicata  dalla Free Software Foundation;   o la versione 2
della licenza o (a scelta) una versione successiva.

Questo programma e' distribuito  nella speranza che sia utile,  ma
SENZA  ALCUNA GARANZIA;  senza  neppure la  garanzia  implicita di
COMMERCIABILITA' o di APPLICABILITA' PER UN PARTICOLARE SCOPO.  Si
veda la Licenza Pubblica Generica GNU per avere maggiori dettagli.
Ognuno dovrebbe avere  ricevuto una copia  della Licenza Pubblica
Generica GNU insieme a questo programma; in  caso contrario, la si
puo' ottenere dalla Free Software  Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, Stati Uniti.
Gli autori possono essere contattati ai seguenti indirizzi:

Andrea Lanzi           : shadow.net@tiscalinet.it
Giampaolo Fresi Roglia : gian_fresi@iol.it

###############################################################################

#include "client_subs.h"
#include "messages.h"

/******************************************************************************/
// IL SEGNALE SIGPIPE VIENE IGNORATO
void ignora()
{
   signal(SIGPIPE, ignora);
}
/******************************************************************************/

int main (int argc, char *argv[])
{
  int iscr=0, iscr_p=0, fine=0, ris, n; 
  #ifdef UNBUFFERED	
     int invio = 0;
  #endif
  int coord_sock, serv_sock, clilen;
  int newsockfd=0;
  char scel, scel2;
  char buf[MAX_DIM];
  char *str_ind;
  unsigned long indirizzo;
  int porta;
  struct sockaddr_in cli_addr;
  char *SERV_HOST_ADDR;
  int SERV_TCP_PORT;
  
  int ADD_GUEST = _ADD_GUEST;
  int TALK = _TALK;
  int ACK = _ACK;
   
  fd_set afds,rfds;
   
  signal(SIGPIPE, ignora);
  
  // MENU DEI COMANDI DELL'UTENTE
  menu();
  if (argc!=3){
  
     printf("\nLanciare client con indirizzo del server e numero di porta\n ");
     exit(0) ;
  }
  
  //ASSEGNAZIONE DELL''INDIRIZZO E PORTA DEL SERVER
  
  SERV_HOST_ADDR=argv[1];
  SERV_TCP_PORT=atoi(argv[2]);
  
  FD_ZERO(&afds);
  FD_SET (0, &afds);
  while (! fine) 
    {
      bcopy( (char*) &afds, (char*) &rfds, sizeof(rfds) ) ;
      if ((select(FOPEN_MAX, &rfds, NULL, NULL, NULL)) < 0)
      {
         perror ("select");
         exit(0);
      }
      
      // GESTIONE DELLO STANDARD INPUT DA PARTE DELLA SELECT    
      if (FD_ISSET(0, &rfds))
      {
      	 read(0, &scel, sizeof(scel));
         scel2 = scel;
         while(scel2 != 10)
            read(0, &scel2, sizeof(scel2));
         switch (scel) 
	 {
         
         // ISCRIZIONE DEL CLIENT
	 case '1': 
	     if (! iscr)
	     { 
	        if ((iscrizione( SERV_HOST_ADDR, SERV_TCP_PORT, &coord_sock, 
                   &serv_sock)) < 0) 
                   menu();
                    
                else
                {   
                   iscr=1;
                   FD_SET(coord_sock, &afds); //SOCKET CON IL COORDINATORE
                   FD_SET(serv_sock, &afds);  //SOCKET IN ASCOLTO
                }
	     }        
	     break;
         
        //ISCRIZIONE A PARLARE 
	case '2':  
	    if (iscr && (! iscr_p))
	    {
	       if ( iscr_parl(coord_sock) < 0 ) 
                  perror("iscrizione a parlare"); 
               else iscr_p=1;
	    }
	    break;
            
        //RINUNCIA A PARLARE          
	case '3':
	    if (iscr_p)
	    {
	       if ((rinuncia(coord_sock)) < 0) 
                  exit(0); 
               else	iscr_p=0;
	    }
            break;
        
        // DISCONNESSIONE DEL CLIENT          
	case '4':
	    if (iscr)
	    {
	       if ((disconnetti(coord_sock)) < 0) 
	       {
		  perror("disconnetti");
		  exit(0);
	       } 
               else 
               {
                  iscr=0;
                  FD_CLR(serv_sock, &afds);
                  close(serv_sock);
                  FD_CLR(coord_sock, &afds);
                  close(coord_sock);
               }//fineif
	    }
	    break;
      
        // USCITA DAL MENU
        case '5':
            exit(0);
	default:
            menu(); 
        }//fine switch
      }
      
      //GESTIONE DELLA SOCKET CON L'ORATORE
      else if(FD_ISSET(newsockfd, &rfds))
      {
         n=read(newsockfd,buf,MAX_DIM);
         buf[n]='\0' ;
         
         // GESTIONE DI FINE MESSAGGIO
         #ifdef UNBUFFERED
            if (n>0)
	    {
               if(buf[n-1]!=10)
                  invio = 0;
               else	invio++;
	    }
               if ((n<=0)||(invio==2))
         #else
            if((strcmp(buf,"\n")==0)||(n<=0))
         #endif
                  
         {
            FD_CLR(newsockfd, &afds);
            close( newsockfd );
            printf("Fine messaggio\n");
            newsockfd = 0;
         }
         write(1,buf,n);
      }
      //GESTIONE DELLA SOCKET DEL COORDINATORE CON LA SELECT
      else if (FD_ISSET(coord_sock, &rfds))
      {
      	 // SE LA LETTURA DA ERRORI LA CONNESSIONE CON IL COORDINATORE 
         // E' CADUTA 
         if(read(coord_sock, &ris, sizeof(ris))<=0)
         {
            printf("perso contatto coordinatore\nesco\n");
            perror("read");
            exit(-1);
         }
         // SE INVECE SI E' CONNESSO O DISCONNESSO UN PARTECIPANTE 
         // VIENE NOTIFICATO
         if (iscr_p==0)
         {
            read(coord_sock, &indirizzo, sizeof(indirizzo));
            read(coord_sock, &porta, sizeof(porta));
            bzero((char *) &cli_addr, sizeof(cli_addr));
            cli_addr.sin_addr.s_addr = indirizzo;
            str_ind=inet_ntoa(cli_addr.sin_addr);
            if(ris==ADD_GUEST)
               printf("Connessione di: %s:%d\n",str_ind, porta);
            else
               printf("Disconnessione di: %s:%d\n",str_ind, porta);

         }
         else 
         {
            // IL COORDINATORE HA DATO LA PAROLA AL CLIENT	
            if (ris == TALK)
            {
               if (newsockfd != 0)
               {
                  FD_CLR(newsockfd, &afds);
                  close(newsockfd);
                  printf("Fine messaggio\n");
                  newsockfd = 0;
               }
               printf("\nRicevo il diritto di parola dal coordinatore\n");
               write(coord_sock, &ACK, sizeof(ACK));
               printf("Invio ACK al coordinatore\n");
               if ((gest_conv(coord_sock)) < 0)
               {
                   perror("gest_conv");
                   exit(0);
               }
               iscr_p=0;
            }
            else     
            // VIENE NOTIFICATO AGGIUNTA O DISCONNESSIONE DI 
            // UN NUOVO PARTECIPANTE 
            {
               read(coord_sock, &indirizzo, sizeof(indirizzo));
               read(coord_sock, &porta, sizeof(porta));
               bzero((char *) &cli_addr, sizeof(cli_addr));
               cli_addr.sin_addr.s_addr = indirizzo;
               str_ind=inet_ntoa(cli_addr.sin_addr);
               if(ris==ADD_GUEST)
                  printf("Connessione di: %s:%d\n",str_ind, porta);
               else
                  printf("Disconnessione di: %s:%d\n",str_ind, porta);
            }
                 
         }
      }
      
      //GESTIONE DELLA SOCKET PASSIVA IN ASCOLTO VERSO L''ORATORE
      else if(FD_ISSET(serv_sock, &rfds))
      {
       //CREAZIONE DELLA SOCKET CON L''ORATORE
       clilen = sizeof( cli_addr ) ;
       newsockfd = accept(serv_sock, (struct sockaddr *) &cli_addr, &clilen ) ;
       printf("\nAccetto la connessione dall'oratore corrente\n");
       FD_SET(newsockfd, &afds);
      }
   }
  exit(0);
}          

/*********************************************************************************************/