/** * @brief Calcola il ritardo dei pacchetti PING ricevuti dal Load Balancer Fixed. * @param *buf : puntatore al pacchetto PING * @return Restituisce il ritardo del pacchetto espresso in millisecondi. */ long int compute_delay_ping(uint32_t *buf) { struct timeval sent, now, tempoimpiegato; long int msec; memcpy( (char*)&sent, (char*)&(buf[0]), sizeof(struct timeval) ); gettimeofday(&now,NULL); tempoimpiegato=differenza(now,sent); msec=(tempoimpiegato.tv_sec*1000)+(tempoimpiegato.tv_usec/1000); return(msec); }
void save_delay(FILE *f, uint32_t *buf) { struct timeval sent, now, tempoimpiegato; uint32_t idmsg; long int msec; if(f==NULL) return; idmsg=buf[0]; memcpy( (char*)&sent, (char*)&(buf[1]), sizeof(struct timeval) ); gettimeofday(&now,NULL); /* fprintf( f, "\nsent: %lu : %ld sec %ld usec\n", idmsg, sent.tv_sec, sent.tv_usec ); fprintf( f, "now: %lu : %ld sec %ld usec\n", idmsg, now.tv_sec, now.tv_usec ); */ tempoimpiegato=differenza(now,sent); msec=(tempoimpiegato.tv_sec*1000)+(tempoimpiegato.tv_usec/1000); /* fprintf( f, "tempoimpiegato: %lu : %ld sec %ld usec\n\n", idmsg, tempoimpiegato.tv_sec, tempoimpiegato.tv_usec ); */ if(msec>150) { numritardi++; printf("%u : delay msec %ld TEMPO SUPERATO\n", idmsg, msec); } else printf("%u : delay msec %ld\n", idmsg, msec); fprintf(f,"%u %ld\n", idmsg, msec); fflush(f); /* if(msec>150) { fprintf( f, "\nsent: %lu : %ld sec %ld usec\n", idmsg, sent.tv_sec, sent.tv_usec ); fprintf( f, "now: %lu : %ld sec %ld usec\n", idmsg, now.tv_sec, now.tv_usec ); fprintf( f, "tempoimpiegato: %lu : %ld sec %ld usec\n\n", idmsg, tempoimpiegato.tv_sec, tempoimpiegato.tv_usec ); fprintf(f, "TEMPO SUPERATO - TERMINO\n"); fflush(f); exit(888); } */ }
long int compute_delay(uint32_t *buf) { struct timeval sent, now, tempoimpiegato; uint32_t id; long int msec; id=buf[0]; memcpy( (char*)&sent, (char*)&(buf[1]), sizeof(struct timeval) ); gettimeofday(&now,NULL); /* fprintf( f, "\nsent: %lu : %ld sec %ld usec\n", id, sent.tv_sec, sent.tv_usec ); fprintf( f, "now: %lu : %ld sec %ld usec\n", id, now.tv_sec, now.tv_usec ); */ tempoimpiegato=differenza(now,sent); msec=(tempoimpiegato.tv_sec*1000)+(tempoimpiegato.tv_usec/1000); /* fprintf( f, "tempoimpiegato: %lu : %ld sec %ld usec\n\n", id, tempoimpiegato.tv_sec, tempoimpiegato.tv_usec ); */ return(msec); }
int menu (void) { int choose, a, b, ris; //DICHIARAZIONE VARIABILI //INSERIMENTO DATI printf ("\nInserisci primo numero: "); scanf ("%d", &a); printf ("\nInserisci secondo numero: "); scanf ("%d", &b); //SCELTA DELL'OPERAZIONE printf ("\n\nCosa vuoi fare ora?\n1. Somma\n2. Differenza\n3. Prodotto\n4. Divisione\n9. Ricomincia\n0. Esci\nScelta: "); scanf ("%d", &choose); switch (choose) { //CHIAMATE A FUNZIONE case 1: ris = somma (a,b); break; case 2: ris = differenza(a,b); break; case 3: ris = prodotto (a,b); break; case 4: ris = divisione (a,b); break; case 9: return 0; break; //SE NESSUNO DEI PRECEDENTI, ESCI default: printf ("\nAddio!\n"); return 1; break; } printf ("\nIl risultato e': %d\n", ris); //STAMPA RISULTATO printf ("\nVuoi effettuare un'altra operazione?\n0. Si\n1. No\nScelta: "); scanf ("%d", &choose); if (choose==1) { printf ("\nAddio!\n"); return 1; } else return 0; }
/** * @brief Main * @return Ritorna un intero. */ int main(int argc, char *argv[]) { /* Inizializzazione delle variabili */ index = 0; lPkt = NULL; contACK = 0; tipoCnt = 0; printf ("uso i parametri di default \n%s\n", PARAMETRIDEFAULT ); localportfrommobile = 6001; localportdatamonitor = 7001; portmonitor = 8000; /* Inizializzazione dei vettori */ initV(cfgPKT); initV(tipoConn); initV(pktTipoConn); init_random(); /* Si connette al monitor */ ris=TCP_setup_connection(&monitorfd, "127.0.0.1", portmonitor, 300000, 300000, 1); if(!ris) { printf ("TCP_setup_connection() failed\n"); exit(1); } else printf("monitorfd %d\n", monitorfd); FD_ZERO(&all); FD_SET(monitorfd,&all); maxfd=monitorfd; ris=RecvCfg(monitorfd,&numporte,porte); if(!ris) { printf ("RecvCfg() failed\n"); exit(1); } for(i=0;i<numporte;i++) { cfgPorte[i]=porte[i]; } /* Creazione del pacchetto della configurazione delle porte */ config_pkt_porte(cfgPKT, numporte); ris=UDP_setup_socket_bound( &monitordatafd, localportdatamonitor, 65535, 65535 ); if (!ris) { printf ("UDP_setup_socket_bound() failed\n"); exit(1); } FD_SET(monitordatafd,&all); if(monitordatafd>maxfd) maxfd=monitordatafd; appmobilefd=0; /* Attende la connessione dall'applicazione lato mobile */ ris=TCP_setup_socket_listening( &listening_mobilefd, localportfrommobile, 300000, 300000, 1); if (!ris) { printf ("TCP_setup_socket_listening() failed\n"); exit(1); } do { memset (&Cli, 0, sizeof (Cli)); len = sizeof (Cli); appmobilefd = accept ( listening_mobilefd, (struct sockaddr *) &Cli, &len); } while ( (appmobilefd<0) && (errno==EINTR) ); if (appmobilefd < 0 ) { perror("accept() failed: \n"); exit (1); } /* NO NAGLE per i tcp */ ris=SetsockoptTCPNODELAY(appmobilefd,1); if (!ris) { fprintf(stderr,"unable to setup TCPNODELAY option\n"); exit(5); } /* chiusura del socket TCP listening e setup dei socket UDP */ close(listening_mobilefd); FD_SET(appmobilefd,&all); if(appmobilefd>maxfd) maxfd=appmobilefd; /* Imprime il timestamp sul primo pacchetto, ossia fa partire il cronometro */ gettimeofday(&timePktFirst,NULL); memcpy( (char*)&(tipoConn[0]), (char*)&timePktFirst, sizeof(struct timeval) ); /* Controllo del tipo di connessione */ for(;;) { do { rdset=all; #ifdef VICDEBUG stampa_fd_set("rdset prima",&rdset); #endif ris=select(maxfd+1,&rdset,NULL,NULL,NULL); } while( (ris<0) && (errno==EINTR) ); if(ris<0) { perror("select failed: "); exit(1); } /* Controlla se sono arrivati pacchetti dall'applicazione */ if( FD_ISSET(appmobilefd,&rdset) ) { uint32_t buf[PKTSIZE]; uint32_t idmsg; struct timeval sent, now, tempoimpiegato; long int msec; /* riceve un pkt */ /*ris=Readn(appmobilefd,(char*)buf,PKTSIZE); if(ris!=PKTSIZE) { fprintf(stderr,"recv from appmobile failed, received %d: ", ris); exit(9); }*/ ris=Readn(appmobilefd,(char*)buf,sizeof(buf)); if(ris!=sizeof(buf)) { fprintf(stderr,"recv from appmobile failed, received %d: ", ris); exit(9); } /* Appena arriva un pacchetto dall'AppMobile, calcola quanto tempo è passato */ memcpy( (char*)&sent, (char*)&(tipoConn[0]), sizeof(struct timeval) ); gettimeofday(&now,NULL); tempoimpiegato=differenza(now,sent); msec=(tempoimpiegato.tv_sec*1000)+(tempoimpiegato.tv_usec/1000); idmsg = buf[0]; /* ID del pkt di connessione è 42, tanto per cambiare */ pktTipoConn[0] = 42; /* Può capitare che arrivi il primo pacchetto con 40msec di delay su connessione LENTA */ /* Se è il primo pacchetto */ if(idmsg < 1) { /* E se il primo pacchetto arriva con abbastanza ritardo, vuol dire che la connessione è LENTA */ if((msec > DELAY_VELOCE) && (msec < DELAY_MUTA)) { tipoCnt = pktTipoConn[1] = CONN_LENTA; break; } /* Altrimenti sarà MUTA */ else if(msec >= DELAY_MUTA) { tipoCnt = pktTipoConn[1] = CONN_MUTA; break; } } /* Se invece il secondo pacchetto è veloce, vuol dire che siamo nella VELOCE */ else if(msec <= DELAY_LENTA) { tipoCnt = pktTipoConn[1] = CONN_VELOCE; break; } /* Altrimenti è LENTA */ else { tipoCnt = pktTipoConn[1] = CONN_LENTA; break; } } } /* Invio il tipo di connessione al Fixed su tutte le porte attive per avvertirlo */ /* Invio il tipo di connessione su ogni porta attiva per ben due volte (per evitare di gestire i suoi NACK) */ for(k=0; k<2; k++) { for(i=0; i<numporte; i++) { ris = send_udp(monitordatafd, (char*)pktTipoConn, sizeof(pktTipoConn) , 1000, "127.0.0.1", cfgPorte[i]); if(!(ris)) { fprintf(stderr,"Errore durante l'invio del tipo di connessione!\n"); } } } send_config(cfgPKT, monitordatafd, cfgPorte, numporte); /* Configurazione del LBMobile sul tipo di connessione */ switch(tipoCnt) { case CONN_MUTA: #ifdef TIPO_CONN fprintf(stdout,ROSSO "\n*** Attivazione della connessione MUTA ***\n" DEFAULTCOLOR "\n"); #endif /* *********************************************** MUTA ************************************************** */ for(;;) { do { rdset=all; #ifdef VICDEBUG stampa_fd_set("rdset prima",&rdset); #endif ris=select(maxfd+1,&rdset,NULL,NULL,NULL); } while( (ris<0) && (errno==EINTR) ); if(ris<0) { perror("select failed: "); exit(1); } #ifdef VICDEBUG stampa_fd_set("rdset dopo",&rdset); #endif /* Lettura dei pacchetti UDP provenienti dal Monitor */ if(FD_ISSET(monitordatafd,&rdset)) { lettura_pkt_monitor(); } /* Lettura dei pacchetti TCP (CONF, ACK, NACK) provenienti dal Monitor */ if( FD_ISSET(monitorfd,&rdset) ) { char ch; int ris; uint32_t tmpnumporte; uint16_t tmpporte[MAXNUMCONNECTIONS]; uint32_t idmsg; /* ris=recv(monitorfd,buf,65536,MSG_DONTWAIT); */ ris=recv(monitorfd,&ch,1,0); if(ris!=1) { fprintf(stderr,"recv from monitor failed: "); exit(9); } if(ch=='C') { /* Ricezione del nuovo numero di porte attive */ ris=recv(monitorfd,(char*)&tmpnumporte,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(C)recv_configurazione failed: "); exit(9); } /* Ricezione del nuovo vettore di porte attive */ for(i=0;i<tmpnumporte;i++) { ris=recv(monitorfd,&(tmpporte[i]),sizeof(uint16_t),0); if(ris!=sizeof(uint16_t)) { fprintf(stderr,"(C%d)recv_configurazione failed: ",i); exit(9); } } /* Aggiorna l'indice della porta a cui stava inviando i pacchetti col nuovo */ config_new_porte(cfgPorte, tmpporte); setup_new_configurazione(&numporte,porte,&tmpnumporte,tmpporte); /* Creazione del pacchetto della configurazione delle porte */ config_pkt_porte(cfgPKT, numporte); /* Invio della configurazione al Fixed */ send_config(cfgPKT, monitordatafd, cfgPorte, numporte); } else if( ch=='A' ) { ris=recv(monitorfd,(char*)&idmsg,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(A)recv ack failed: "); exit(9); } /* Se arriva un ACK presente nella lista di pacchetti, lo rimuove */ if(find_id_pkt(idmsg, lPkt) != NULL) { lPkt = rim_pkt(idmsg, lPkt); } } else if( ch=='N' ) { struct listaPKT *list_aux; list_aux = NULL; ris=recv(monitorfd,(char*)&idmsg,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(N)recv nack failed: "); exit(9); } /* Restituisce il puntatore lista all'elemento interessato */ list_aux = find_id_pkt(idmsg, lPkt); /* Se il pacchetto NACKato è presente nella lista */ if(list_aux != NULL) { /* E se la porta da cui è stato inviato il pacchetto è uguale all'attuale da cui s'invia */ if(list_aux->portaPKT == cfgPorte[index]) { /* Viene cambiata */ index=(index+1)%numporte; } /* Aggiorna anche la porta d'invio del pacchetto */ list_aux->portaPKT = cfgPorte[index]; /* Rispedisce l'esatto pacchetto che è stato NACKato */ ris=send_udp(monitordatafd, (char*)list_aux->pkt, sizeof(list_aux->pkt) , 1000, "127.0.0.1", cfgPorte[index] ); if(!(ris)) { fprintf(stderr,"pkt id %u NOT sent\n", list_aux->pkt[0] ); } } } } /* Controlla se sono arrivati pacchetti dall'applicazione */ if( FD_ISSET(appmobilefd,&rdset) ) { lettura_pkt_app(); } } /* fine for ;; */ /***********************************************************************************************************/ break; case CONN_VELOCE: #ifdef TIPO_CONN fprintf(stderr,GREEN "\n*** Attivazione della connessione VELOCE ***\n" DEFAULTCOLOR "\n"); #endif /* *********************************************** VELOCE ************************************************** */ for(;;) { do { rdset=all; #ifdef VICDEBUG stampa_fd_set("rdset prima",&rdset); #endif ris=select(maxfd+1,&rdset,NULL,NULL,NULL); } while( (ris<0) && (errno==EINTR) ); if(ris<0) { perror("select failed: "); exit(1); } #ifdef VICDEBUG stampa_fd_set("rdset dopo",&rdset); #endif /* Lettura dei pacchetti UDP provenienti dal Monitor */ if(FD_ISSET(monitordatafd,&rdset)) { lettura_pkt_monitor(); } /* Lettura dei pacchetti TCP (CONF, ACK, NACK) provenienti dal Monitor */ if( FD_ISSET(monitorfd,&rdset) ) { char ch; int ris; uint32_t tmpnumporte; uint16_t tmpporte[MAXNUMCONNECTIONS]; uint32_t idmsg; /* ris=recv(monitorfd,buf,65536,MSG_DONTWAIT); */ ris=recv(monitorfd,&ch,1,0); if(ris!=1) { fprintf(stderr,"recv from monitor failed: "); exit(9); } if(ch=='C') { ris=recv(monitorfd,(char*)&tmpnumporte,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(C)recv_configurazione failed: "); exit(9); } for(i=0;i<tmpnumporte;i++) { ris=recv(monitorfd,&(tmpporte[i]),sizeof(uint16_t),0); if(ris!=sizeof(uint16_t)) { fprintf(stderr,"(C%d)recv_configurazione failed: ",i); exit(9); } } config_new_porte(cfgPorte, tmpporte); setup_new_configurazione(&numporte,porte,&tmpnumporte,tmpporte); /* Creazione del pacchetto della configurazione delle porte */ config_pkt_porte(cfgPKT, numporte); send_config(cfgPKT, monitordatafd, cfgPorte, numporte); } else if( ch=='A' ) { ris=recv(monitorfd,(char*)&idmsg,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(A)recv ack failed: "); exit(9); } /* Se arriva un ACK presente nella lista di pacchetti, lo rimuove */ if(find_id_pkt(idmsg, lPkt) != NULL) { lPkt = rim_pkt(idmsg, lPkt); } /* Incrementa il contatore degli ACK */ contACK++; } else if( ch=='N' ) { struct listaPKT *list_aux; list_aux = NULL; ris=recv(monitorfd,(char*)&idmsg,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(N)recv nack failed: "); exit(9); } /* Restituisce il puntatore lista all'elemento interessato */ list_aux = find_id_pkt(idmsg, lPkt); /* Se il pacchetto NACKato è presente nella lista */ if(list_aux != NULL) { /* Se precedentemente sono arrivati almeno due ACK dietro fila, vuol dire che attualmente il Mobile è connesso sulla porta 'OK', quindi viene data una seconda chance al pacchetto rinviandolo sulla medesima porta, altrimenti si scorre il vettore di porte dato che due NACK sulla stessa porta indicano il cambiamento in 'LOSS' */ if(contACK < NUM_CONTACK) { if(list_aux->portaPKT == cfgPorte[index]) { index=(index+1)%numporte; } } else { contACK = 0; } /* Aggiorna anche la porta d'invio del pacchetto */ list_aux->portaPKT = cfgPorte[index]; /* Rispedisce l'esatto pacchetto che è stato NACKato */ ris=send_udp(monitordatafd, (char*)list_aux->pkt, sizeof(list_aux->pkt) , 1000, "127.0.0.1", cfgPorte[index] ); if(!(ris)) { fprintf(stderr,"pkt id %u NOT sent\n", list_aux->pkt[0] ); } } } } /* Controlla se sono arrivati pacchetti dall'applicazione */ if( FD_ISSET(appmobilefd,&rdset) ) { lettura_pkt_app(); } } /* fine for ;; */ /***********************************************************************************************************/ break; case CONN_LENTA: #ifdef TIPO_CONN fprintf(stdout,ORANGE "\n*** Attivazione della connessione LENTA ***\n" DEFAULTCOLOR "\n"); #endif /* *********************************************** LENTA ************************************************** */ for(;;) { do { rdset=all; #ifdef VICDEBUG stampa_fd_set("rdset prima",&rdset); #endif ris=select(maxfd+1,&rdset,NULL,NULL,NULL); } while( (ris<0) && (errno==EINTR) ); if(ris<0) { perror("select failed: "); exit(1); } #ifdef VICDEBUG stampa_fd_set("rdset dopo",&rdset); #endif /* Lettura dei pacchetti UDP provenienti dal Monitor */ if(FD_ISSET(monitordatafd,&rdset)) { lettura_pkt_monitor(); } /* Lettura dei pacchetti TCP (CONF, ACK, NACK) provenienti dal Monitor */ if( FD_ISSET(monitorfd,&rdset) ) { char ch; int ris; uint32_t tmpnumporte; uint16_t tmpporte[MAXNUMCONNECTIONS]; uint32_t idmsg; /* ris=recv(monitorfd,buf,65536,MSG_DONTWAIT); */ ris=recv(monitorfd,&ch,1,0); if(ris!=1) { fprintf(stderr,"recv from monitor failed: "); exit(9); } if(ch=='C') { ris=recv(monitorfd,(char*)&tmpnumporte,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(C)recv_configurazione failed: "); exit(9); } for(i=0;i<tmpnumporte;i++) { ris=recv(monitorfd,&(tmpporte[i]),sizeof(uint16_t),0); if(ris!=sizeof(uint16_t)) { fprintf(stderr,"(C%d)recv_configurazione failed: ",i); exit(9); } } config_new_porte(cfgPorte, tmpporte); setup_new_configurazione(&numporte,porte,&tmpnumporte,tmpporte); /* Creazione del pacchetto della configurazione delle porte */ config_pkt_porte(cfgPKT, numporte); send_config(cfgPKT, monitordatafd, cfgPorte, numporte); } else if( ch=='A' ) { ris=recv(monitorfd,(char*)&idmsg,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(A)recv ack failed: "); exit(9); } /* Se arriva un ACK presente nella lista di pacchetti, lo rimuove */ if(find_id_pkt(idmsg, lPkt) != NULL) { lPkt = rim_pkt(idmsg, lPkt); } } else if( ch=='N' ) { struct listaPKT *list_aux; list_aux = NULL; ris=recv(monitorfd,(char*)&idmsg,sizeof(uint32_t),0); if(ris!=sizeof(uint32_t)) { fprintf(stderr,"(N)recv nack failed: "); exit(9); } /* Restituisce il puntatore lista all'elemento interessato */ list_aux = find_id_pkt(idmsg, lPkt); /* Se il pacchetto NACKato è presente nella lista */ if(list_aux != NULL) { /* Se non sono arrivati dei NACK precedentemente, viene data la seconda chance all'attuale pacchetto NACKato, altrimenti si scorre il vettore di porte */ if(contACK > 0) { if(list_aux->portaPKT == cfgPorte[index]) { index=(index+1)%numporte; } contACK = 0; } /* Aggiorna anche la porta d'invio del pacchetto */ list_aux->portaPKT = cfgPorte[index]; /* Rispedisce l'esatto pacchetto che è stato NACKato */ ris=send_udp(monitordatafd, (char*)list_aux->pkt, sizeof(list_aux->pkt) , 1000, "127.0.0.1", cfgPorte[index] ); if(!(ris)) { fprintf(stderr,"pkt id %u NOT sent\n", list_aux->pkt[0] ); } contACK++; } } } /* Controlla se sono arrivati pacchetti dall'applicazione */ if( FD_ISSET(appmobilefd,&rdset) ) { lettura_pkt_app(); } } /* fine for ;; */ /***********************************************************************************************************/ break; default: fprintf(stderr,"Errore durante la configurazione del tipo di connessione.\n"); exit(1); break; } close(monitorfd); return(0); }
double sec_differenza(struct timeval dopo,struct timeval prima) { struct timeval diff=differenza(dopo,prima); return( ((double)diff.tv_sec)+(((double)diff.tv_usec)/1000000.0) ); }