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 "messages.h"
#include "server_subs.h"


/*****************************************************************************/
// STAMPA LA PORTA D'ASCOLTO DELL'ORATORE CORRENTE 
char *resolv(int fd, struct element vector[])
{
 char *string=NULL;
 char *add;
 struct in_addr sin_addr;
 string=(char*)malloc(40);
 sin_addr.s_addr = vector[fd].pos_guest -> address;
 add = inet_ntoa(sin_addr);
 sprintf(string,"\nOratore corrente=%s:%d\n",add,vector[fd].pos_guest -> port);
 return string;
}
/*****************************************************************************/
//GESTIONE DELLE VARIE OPERAZIONI DA PARTE DEI CLIENT
int check( int logfd, int fd, int *or_fd, int *numcli, struct element vector[], 
struct guest **joiners, struct fifo*FIFO_list)

{
   
   //DEFINITI IN MESSAGES.H
   
   int LOGON = _LOGON;
   int LOGOFF = _LOGOFF;
   int REQ_TALK = _REQ_TALK;
   int NOT_TALK = _NOT_TALK;
   int TALK = _TALK;
   int ACK = _ACK;
   
   #ifdef UNBUFFERED
      static int invio = 0;
   #endif
   
   char *add;
   char buf[80] ;   	//BUFFER PER LA LETTURA          
   int nread, ris, port, n;
   struct guest *temp;

     if(fd == *or_fd)          // GESTIONE ORATORE CORRENTE
     {
        nread = read(fd,buf,80);
        buf[nread] = '\0';
        if(nread <= 0)        // ERRORE NELLA LETTURA CON L''ORATORE CORRENTE
        {

           printf("E' caduto l'oratore corrente\n");
           
           printf("Notifico la caduta dell'oratore\n");
           
            //NOTIFICA LA CADUTA DELL''ORATORE CORRENTE	
           notify_rem(*joiners, vector, fd);
           
           //ELIMINA L''ORATORE DALLA STRUTTURA 
           rem_guest(numcli, fd, vector, FIFO_list, joiners);
            
           // VIENE DATA LA PAROLA AL PROSSIMO CLIENT PRENOTATO
           if(FIFO_list -> first!=NULL)
           {
              printf("Do' la parola all'oratore seguente\n");
              *or_fd = (*FIFO_list).first -> sockfd;
              rem_fifo(*or_fd, vector,FIFO_list);
              printf("Invio TALK\n");
              write(*or_fd, &TALK, sizeof(TALK));
              read(*or_fd, &ris, sizeof(ris));
              printf("ricevo ACK\n");
              n = *numcli-1;
              write(*or_fd, &n, sizeof(n));
              temp = *joiners;
              
              printf("invio indirizzi all'oratore\n");
        
              add = resolv(*or_fd, vector);        
              
              //SCRITTURA SUL FILE DI LOG
              write( logfd, add, strlen(add));

              // VENGONO INVIATI GLI INDIRIZZI DEI PARTECIPANTI 
              // ALL''ORATORE CORRENTE
              while(temp!=NULL)
              {
                 if(temp->fd!=(*or_fd))
                 {
                    write(*or_fd, &temp->address, sizeof(temp->address));
                    write(*or_fd, &temp->port, sizeof(temp->port));
                 }
                 temp=temp->next;
              }//fine while
              
           }
           else  // SE NON CI SONO ALTRI PARTECIPANTI PRENOTATI
              *or_fd=0;
           return -1;
        }
        #ifdef UNBUFFERED
        if(buf[nread-1]!=10)
           invio = 0;
        else
           invio++;
        write(logfd,buf,nread) ;
        if(invio==2)
        #else
        write(logfd,buf,nread) ;	
        if(nread==1)
        #endif
        
        // FINE MESSAGGIO ENTER SU RIGA VUOTA
        {
           printf("L'oratore corrente ha terminato l'intervento\n");
           
           //CONTROLLO SE CI SONO PARTECIPANTI PRENOTATI PER PARLARE
           if(FIFO_list->first==NULL)
           {
              *or_fd=0;
           }
           else //SE CI SONO PARTECIPANTI ISCRITTI A PARLARE 
              	//DO LA PAROLA AL PROSSIMO
           {

              printf("Do' la parola all'oratore seguente\n");
              
              *or_fd=FIFO_list->first->sockfd;
              rem_fifo(*or_fd, vector, FIFO_list);

              printf("Invio TALK\n");

              write(*or_fd, &TALK, sizeof(TALK));
              read(*or_fd, &ris, sizeof(ris));

              printf("Ricevuto ACK\n");

              n=*numcli-1;
              write(*or_fd, &n, sizeof(n));
              
              //INVIO GLI INDIRIZZI DEI PARTECIPANTI ALL''ORATORE CORRENTE
              temp=*joiners;
              
              printf("Invio indirizzi all'oratore\n");
              
              add = resolv(*or_fd, vector);        

              // SCRITTURA SUL FILE DI LOG
              write(logfd,add, strlen(add));

              while(temp!=NULL)
              {
                 if(temp->fd!=*or_fd)
                 {
                    write(*or_fd, &temp->address, sizeof(temp->address));
                    write(*or_fd, &temp->port, sizeof(temp->port));
                 }
                 temp=temp->next;
              }//fine while	
           }
        }
     }
     else // GESTIONE DI ALTRE OPERAZIONI DEI CLIENT
     {
     // ricezione dei dati 
     nread = read(fd,&ris, sizeof(ris));
     if(nread<=0)
     {
     
        printf("Notifico la caduta di un partecipante\n");
     
        notify_rem(*joiners, vector, fd);
      	rem_guest(numcli, fd,vector,FIFO_list, joiners);
        return -1;
     }
     if(ris == LOGON )      // UN CLIENT SI VUOLE ISCRIVERE
     {		//iscrizione alla conferenza
        
        printf("Ricevo richiesta di LOGON\n");
        
        read(fd, &port, sizeof(port));
        
        printf("Invio ACK\n");
        
        write( fd, &ACK, sizeof(ACK));
        add_guest(numcli, fd, port , vector , joiners);
        
        printf("Notifico aggiunta partecipante\n");
        
        notify_add(*joiners, vector, fd);
     }
     if(ris == LOGOFF)
     {  // USCITA  DALLA CONFERENZA
        
        printf("Ricevo richiesta di LOGOFF\n");
        
        printf("Invio ACK\n");
        
        write( fd, &ACK, sizeof(ACK)) ;
        
        printf("Notifico rimozione partecipante\n");
        
        notify_rem(*joiners, vector, fd);
        rem_guest(numcli, fd,vector, FIFO_list, joiners);
        if (*numcli==0)
           *joiners=NULL;
        return -1;
     }          
     
     if(ris ==REQ_TALK)           
     // RICHIESTA DI PARLARE DA PARTE DI UNO DEI PARTECIPANTI
     {		// conferma a parlare
        
        printf("Ricevo richiesta a parlare\n");
        
        printf("Invio ACK\n");
        
        write( fd, &ACK, sizeof(ACK));
        // SE NON CI SONO ORATORI CORRENTI O ISCRITTI GLI VIENE 
        // DATA SUBITO LA PAROLA
        if(*or_fd==0)
        {
           *or_fd=fd;
           
           printf("Invio TALK\n");
           
           write(fd, &TALK, sizeof(TALK));
           read(fd, &ris, sizeof(ris));
           
           printf("Ricevo ACK\n");
           
           n=*numcli-1;
           write(fd, &n, sizeof(n));
           
           temp=*joiners;
           
           printf("Invio indirizzi all'oratore\n");
           
           add = resolv(*or_fd, vector);        
           
           //SCRITTURA SUL FILE DI LOG
           write(logfd,add, strlen(add));

           while(temp!=NULL)
           {
              if(temp->fd!=fd)
              {
                 write(fd, &temp->address, sizeof(temp->address));
                 write(fd, &temp->port, sizeof(temp->port));
              }
              temp=temp->next;
           }//fine while
        }
        else // SE C''E'' UN ORATORE CORRENTE IL NUOVO CLIENT 
             // VIENE INSERITO NELLA LISTA PER PARLARE
           add_fifo(fd, FIFO_list, vector);
     }	   
     
     //RINUNCIA A PARLARE
     if(ris == NOT_TALK )
     { 	
        
        printf("Ricevo rinuncia a parlare\n");
        
        write( fd, &ACK, sizeof(ACK)) ;
        
        printf("Invio ACK\n");
        
        rem_fifo(fd, vector, FIFO_list);
     }	   
     }
     return 0;

}
/******************************************************************************/

// SOCKET PASSIVA PER L''ASCOLTO DELLE CONNESSIONI
int passive_socket(int port, int backlog)
{


        int sockfd;
        struct sockaddr_in serv_addr ;
        
	
        /*   Apre una socket TCP                                           */
        
	if( ( sockfd = socket( AF_INET, SOCK_STREAM, 0) ) < 0 )
        {	
		perror("socket") ;
                return -1;
        }
 

	/* Bind del nostro indirizzo locale   */

	bzero( (char * ) &serv_addr, sizeof(serv_addr) ) ;
	
	serv_addr.sin_family = AF_INET ;
	serv_addr.sin_addr.s_addr = htonl( INADDR_ANY ) ;
	serv_addr.sin_port = htons( port ) ;
        
	if (bind ( sockfd, (struct sockaddr *) &serv_addr, 
                	sizeof(serv_addr)) < 0)
        {
		perror("bind") ;
                return -1;
        }        
        /* Ascolta sulla porta specificata */

   	listen(sockfd, backlog) ;
        
        return( sockfd ) ;
        
   
}//fine socket
//*****************************************************************************/
// INIZIALIZZAZIONE DEL VETTORE
void init(struct element vector[])
{
   int i;
   for (i=0; i<FOPEN_MAX ; i++)
   {
      vector[i].pos_guest=NULL;
      vector[i].pos_speaker=NULL;
   }
}
/******************************************************************************/
// AGGIUNTA DI UN NUOVO PARTECIPANTE ALLA LISTA
int add_guest(int *numcli, int fd, int port, struct element vector[], 
   struct guest **joiners)
{
   struct sockaddr_in name;
   struct guest *temp;
   int namelen;

   namelen=sizeof(name);
   getpeername(fd, (struct sockaddr*) &name, &namelen);
   temp = (struct guest *)malloc(sizeof(struct guest));
   temp->fd=fd;
   temp->port=port;
   temp->address=name.sin_addr.s_addr;
   temp->prec=NULL;
   temp->next=*joiners;
   if((*joiners)!=NULL)
      (*joiners) -> prec = temp;
   *joiners=temp;
   vector[fd].pos_guest=temp;
   vector[fd].pos_speaker=NULL;
   (*numcli) = (*numcli) +1;
   return 0;
}
/******************************************************************************/
// CANCELLAZIONE DI UN PARTECIPANTE DALLA LISTA
int rem_guest(int *numcli, int fd, struct element vector[], 
struct fifo *FIFO_list, struct guest **joiners)
{
   struct guest *temp;
   
   temp=vector[fd].pos_guest;
   if (*joiners == temp)
   {
      *joiners = temp -> next;
   }
   if (temp -> prec != NULL)
      (temp -> prec) -> next = temp -> next;
   if (temp -> next != NULL)
      (temp -> next) -> prec = temp -> prec;
   free(temp);
   temp=NULL;
   vector[fd].pos_guest=NULL;
   if(vector[fd].pos_speaker!=NULL)
   {
      rem_fifo( fd, vector, FIFO_list);
   }
   (*numcli) = (*numcli) -1;
   return fd;
}
/******************************************************************************/
//NOTIFICA DELLA AGGIUNTA DI UN NUOVO PARTECIPANTE
int notify_add(struct guest *joiners,struct element vector[],int fd)
{
   struct guest *temp;
   int ADD_GUEST = _ADD_GUEST;

   temp=joiners;

   while(temp!=NULL)
   {
      if(temp->fd!=fd)
      {
         write(temp->fd, &ADD_GUEST, sizeof(ADD_GUEST));
         
         write(temp->fd, &vector[fd].pos_guest->address, 
            	sizeof(vector[fd].pos_guest->address));
                
         write(temp->fd, &vector[fd].pos_guest->port, 
            	sizeof(vector[fd].pos_guest->port));
      }   
      temp=temp->next;
   }
   return 0;
}
/******************************************************************************/
//NOTIFICA DELL''USCITA DI UN PARTECIPANTE
int notify_rem(struct guest *joiners, struct element vector[], int fd)
{
   struct guest *temp;
   int REM_GUEST = _REM_GUEST;
   
   temp=joiners;
   while(temp!=NULL)
   {
      if(temp->fd!=fd)
      {
         write(temp->fd, &REM_GUEST, sizeof(REM_GUEST));
         
         write(temp->fd, &vector[fd].pos_guest->address, 
            	sizeof(vector[fd].pos_guest->address));
                
         write(temp->fd, &vector[fd].pos_guest->port, 
            	sizeof(vector[fd].pos_guest->port));
      }   
      temp=temp->next;
   }
   return 0;
}
/******************************************************************************/
//AGGIUNTA DI UN PARTECIPANTE NELLA LISTA PER PARLARE
int add_fifo(int fd, struct fifo *FIFO_list, struct element vector[])
{
   
   struct speaker *temp;
   temp = (struct speaker *)malloc(sizeof(struct speaker));
   temp->sockfd=fd;
   temp->next=NULL;
   if(FIFO_list->first==NULL)
   {
      FIFO_list->first=temp;
      FIFO_list->last=temp;
      temp->prec=NULL;
   }
   else
   if(FIFO_list->first==FIFO_list->last)
   {
      FIFO_list -> last = temp;
      FIFO_list -> first -> next = temp;
      FIFO_list -> last -> prec= FIFO_list -> first;
   }
   else
   {
      FIFO_list->last->next=temp;
      temp->prec=FIFO_list->last;
      FIFO_list->last=temp;
   }
   vector[fd].pos_speaker=temp;
   return 0;
}
/******************************************************************************/
//CANCELLAZIONE DI UN PARTECIPANTE NELLA LISTA PER PARLARE 
int rem_fifo(int fd, struct element vector[], struct fifo *FIFO_list)
{
   struct speaker *temp;
   temp=vector[fd].pos_speaker;
   if(FIFO_list->first==NULL)
      return -1;
   if(temp->prec!=NULL)
      temp->prec->next=temp->next;
   else
      FIFO_list->first=temp->next;
   if(temp->next!=NULL)
      temp->next->prec=temp->prec;
   else
      FIFO_list->last=temp->prec;
   free(temp);
   vector[fd].pos_speaker=NULL;
   return 0;
}