###############################################################################
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;
}