#include <sys/types.h>		//librerie da includere
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "mio.h"	// cerco nel percorso del file client

// definizioni di funzioni

void gestoreFineConn (int);   	// gestisce segnale PIPE
void gestoreUscita (int); 	//gestisco il segnale di uscita

int isPrimo(long);		// funzioni computazionali
int analizza(long,long);
void invia(long);

int ds_sock;			// tutte le funzioni sono a conoscenza di questo parametro


int main (int argc, char *argv[])
{
	struct sockaddr_in client;
	char buffer [BUF_DIM];	// buffer per trasmettere messaggi stringa al server
	char *ip_Server;	// ip del server con cui ci si vuole connettere
	int porta_Server;	// stessa porta del server
	long inf, sup;  	// estremi dell'intervallo da analizzare
	char risposta;		// memorizza la risposta se continuare o meno l'analisi

	if (argc<3)	// controllo che il numero dei parametri sia corretto
		{
		printf("Introdurre %s <IP_Server> <porta_TCP_Server>\n",argv[0]);
		exit(-1);
		}

	ip_Server = argv[1];	// memorizzo nelle variabili i parametri introdotti
	porta_Server = atoi(argv[2]);

	while (3) //il ciclo finisce con la chiusura del server
	{

	if  ((ds_sock = socket(AF_UNIX,SOCK_STREAM,0))<0)	// creo la socket
		{	
		printf ("Errore di socket");
		printf ("Impossibile connetersi al Server \n ");
		exit (-1);
		}

	printf("***************************************\n");
	printf("Premere Control + C per uscire\n");
	printf("\n");
	printf ("ds server %d\n",ds_sock);

	client.sin_family = AF_UNIX;			// imposta la struttura del server a cui connettermi
	client.sin_port = porta_Server;
	client.sin_addr.s_addr = inet_addr(ip_Server);	// converto IP stringa in long uns.



	if ((connect(ds_sock,&client, sizeof(client))) <0 ) 	// provo a connettermi con il server
		{	
		printf("Impossibile effettuare connessione\n");
		exit (-1);
		}

	signal (SIGINT,gestoreUscita);		// armo il segnale di uscita
	signal (SIGPIPE,gestoreFineConn);	// armo il segnale di chiusura PIPE

	write (ds_sock,"Pronto",BUF_DIM);	// invio il mio stato di pronto al server
	read (ds_sock,buffer,BUF_DIM);
	printf ("Stato connessione : %s\n",buffer);// legge lo stato del server o fine o OK
	if (strcmp(buffer,"fine")==0) 		// il server ha finito i pacchetti
		{	
			printf ("Il Server ha concluso la computazione\n");
			if ((close(ds_sock))== -1 )
				printf ("Impossibile chiudere la socket server\n");
			exit(-1);
		}
	read (ds_sock,&inf,sizeof(inf));    // leggo l'intervaalo da anlizzare inviato dal server
	read (ds_sock,&sup,sizeof(sup));

	printf ("Intervallo da analizzare [%d,%d] \n",inf,sup);

	analizza(inf,sup);	// funzione di analisi del pacchetto
	
	printf("\n");

	printf ("Sto per chiudere la porta\n");

	if ((close(ds_sock))== -1 )
		printf ("Impossibile chiudere la socket server\n");

	printf ("Ho chiuso le porte\n");
	} // ritorno all'inizio del ciclo
}


void gestoreUscita (int sig )	// gestisco una chiusura del client prematura
{
	invia (0);	// in questo modo interrompo il figlio del server
	exit (-1);
}



void gestoreFineConn (int sig)	// gestisco il segnale chiusura PIPE
{	
	printf ("\n");
	printf ("Il server ha chiuso la socket\n");  	// avviso del segnale ricevuto ed esco
	exit(-1);
}


int analizza (long inf, long sup)	// funzione che scandisce i vari numeri dell'intervallo
{	long i;
	for (i = inf; i<=sup; i++)
		if ((isPrimo(i))==1) invia(i);	// se i è primo lo invio al figlio del server

	invia(0);   // termino la comunicazione con il figlio del server a fine ciclo
}


int isPrimo (long numero)		// funzione che controlla se il numero è primo
{	long i;
	long resto;
	for (i=2; i<numero; i++)	// non considero il numero 1 (non inviato dal server)
		{
		resto = numero%i;
		if (resto==0) return (0); // il numero non è primo
		}
	return(1);  			  // se sono arrivato fino a qui il numero è primo
}


void invia (long numero)	// funzione che invia il segnale
{
	write (ds_sock,&numero,sizeof(numero));
}