rendered paste body/** Homework 1 - Server* by Labianca Fabio Nino */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>#include <signal.h>#include <sys/wait.h>#include <fcntl.h>#include <ctype.h>#include "errlib.h"#include "sockwrap.h"#include "mywrappers.h"#include "wrappers.h"#define DEFAULT_PORT 12345#define DEFAULT_CHILDREN 2#define MAXBUFL 255#define LISTENQ 15/* * Struttura per memorizzare PID dei figli */typedef struct client{ pid_t pid;}child;/* * Dichiarazione variabili globali */child *queue=NULL; /* coda figli */char *prog;int port=DEFAULT_PORT, children=DEFAULT_CHILDREN, connection=0;/* * Controllo che la stringa contenga solo numeri */int check_num (char *s){char temp_var[MAXBUFL];int j=0; memset (temp_var, '\0', MAXBUFL); strncpy (temp_var, s, MAXBUFL-1);#ifdef TRACE err_msg ("(%s) info - Stringa %s | Lunghezza %d\r\n", prog, s, strlen(temp_var));#endif for (j=0; j<strlen(temp_var); j++) { if ( !isdigit(temp_var[j]) ) {#ifdef TRACE err_msg ("(%s) error - '%c' is not a digit\r\n", prog, temp_var[j]);#endif err_quit ("Usage: %s [-nMAXCHILDRENNUMBER] [-pPORTNUMBER]", prog); } } return 0;}/* * Controllo correttezza parametri */void check_args (int argc, char *argv[]){ int i=0, status=0;#ifdef TRACE err_msg ("(%s) info - argc %d\r\n", prog, argc);#endif if (argc>1) { for (i=1; i<argc; i++ ){ if ( (sscanf(argv[i],"-p%d",&port)==1) && ( status!=1 ) ) { check_num(argv[i]+2); if (port<1024 || port>=65536) {#ifdef TRACE err_msg ("(%s) error - Port %d is not between 1024 - 65535\r\n", prog, port);#endif err_quit ("Usage: %s [-nMAXCHILDRENNUMBER] [-pPORTNUMBER]", prog); } status=1; } else { if ( (sscanf(argv[i],"-n%d",&children)==1) && ( status!=2 ) ) { check_num(argv[i]+2); if (children<=0 || children>=65536) {#ifdef TRACE err_msg ("(%s) error - Child %d is not between 1 - 65535\r\n", prog, children);#endif err_quit ("Usage: %s [-nMAXCHILDRENNUMBER] [-pPORTNUMBER]", prog); } status=2; } else err_quit ("Usage: %s [-nMAXCHILDRENNUMBER] [-pPORTNUMBER]", prog); } } }#ifdef TRACE err_msg ("(%s) info - TCP Port: %d\r\n", prog, port); err_msg ("(%s) info - Max Children number: %d\r\n", prog, children);#endif}/* * Inserimento PID dei figli nell'array*/void pid_queue(pid_t p){int i=0; for (i=0; i<children; i++) { if (queue[i].pid == 0) { queue[i].pid = p; connection++; break; } }}/* * Estrazione PID dei figli dall'array*/void pid_unqueue(pid_t p){int i; for (i=0; i<children; i++) { if (queue[i].pid == p) { queue[i].pid = 0; #ifdef TRACE err_msg ("(%s) info - Child number %d (pid: %d) deleted\r\n", prog, connection, p);#endif --connection; } }}/* * Gestione segnali*/void sigchld_h (int signum){pid_t pid;int status; //signal(SIGCHLD, sigchld_h); while ((pid = waitpid(-1,&status,WNOHANG)) > 0) {#ifdef TRACE err_msg ("(%s) info - Child number %d (pid: %d) terminated with status %d\r\n", prog, connection, pid, status);#endif pid_unqueue(pid); }#ifdef TRACE err_msg ("(%s) info - Number of children currently connected: %d\r\n", prog, connection);#endif}void sigint_h (int signum){#ifdef TRACE err_msg ("(%s) info - Server shut down\r\n", prog);#endif exit(0);}void sigterm_h (int signum){int i; for (i=0; i<children; i++) { if (queue[i].pid == 0) continue;#ifdef TRACE err_msg("(%s) info - chiusura in corso di %d", prog, queue[i].pid);#endif kill(queue[i].pid, SIGKILL); }}/* * Invia la E di errore sul socket*/void send_err(int connfd){ Writen (connfd, "E", 1); return;}/* * Funzione che esegue i calcoli */void calc (int connfd, uint8_t nbyte){char buf[MAXBUFL], ch;size_t n;int8_t num1_8=0, num2_8=0, ris8=0;uint16_t num1_16=0, num2_16=0, ris16=0;#ifdef TRACE err_msg ("(%s) info - Waiting for operation from child number %d ...\r\n", prog, connection+1);#endif while ((n = myReadn (connfd, buf, 1)) > 0) { ch = buf[0]; if (nbyte==1) { myReadn (connfd, buf, 2*sizeof(int8_t)); memcpy ((void *) &num1_8, buf, sizeof(int8_t)); memcpy ((void *) &num2_8, buf+sizeof(int8_t), sizeof(int8_t));#ifdef TRACE err_msg("(%s) info - op: %c num1: %u num2: %u\r\n", prog, ch, (int8_t)num1_8, (int8_t)num2_8);#endif if(ch=='+') { //if ( (int)(num1_8+num2_8) != (int) ( (int8_t)(num1_8+num2_8) ) ) // { // memcpy (buf, "V", sizeof(char)); // Writen (connfd, buf, sizeof(char)); //} //else //{ //memcpy (buf, "=", sizeof(char)); ris8=(num1_8+num2_8); //memcpy (buf+sizeof(char), (void*)&ris8, sizeof(int8_t)); memcpy (buf, (void*)&ris8, sizeof(int8_t));#ifdef TRACE err_msg("(%s) info - ris8: %u\r\n", prog, (int8_t)ris8);#endif //Writen (connfd, buf, sizeof(char)+sizeof(int8_t)); Writen (connfd, buf, sizeof(int8_t)); //} //break;/* switch(ch) { case '+': if ( (int)(num1_8+num2_8) != (int) ( (int8_t)(num1_8+num2_8) ) ) { memcpy (buf, "V", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else { memcpy (buf, "=", sizeof(char)); ris8=(num1_8+num2_8); memcpy (buf+sizeof(char), (void*)&ris8, sizeof(int8_t)); Writen (connfd, buf, sizeof(char)+sizeof(int8_t)); } break; case '-': if ( (int)(num1_8-num2_8) != (int) ( (int8_t)(num1_8-num2_8) ) ) { memcpy (buf, "V", sizeof(char)); Writen (connfd, buf, sizeof(char));} else { memcpy (buf, "=", sizeof(char)); ris8=(num1_8-num2_8); memcpy (buf+sizeof(char), (void*)&ris8, sizeof(int8_t)); Writen (connfd, buf, sizeof(char)+sizeof(int8_t)); } break; case '*': if ( (int)(num1_8*num2_8) != (int) ( (int8_t)(num1_8*num2_8) ) ) { memcpy (buf, "V", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else { memcpy (buf, "=", sizeof(char)); ris8=(num1_8*num2_8); memcpy (buf+sizeof(char), (void*)&ris8, sizeof(int8_t)); Writen (connfd, buf, sizeof(char)+sizeof(int8_t));} break; case '/': if ( (int8_t)num2_8==0 ) send_err(connfd); else if ( (int)(num1_8/num2_8) != (int) ( (int8_t)(num1_8/num2_8) ) ) { memcpy (buf, "V", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else if ( ( (int8_t)num1_8==0) || ( ( (int8_t)(num1_8/num2_8) )==0 ) ) { memcpy (buf, "U", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else { memcpy (buf, "=", sizeof(char)); ris8=(num1_8/num2_8); memcpy (buf+sizeof(char), (void*)&ris8, sizeof(int8_t)); Writen (connfd, buf, sizeof(char)+sizeof(int8_t)); } break;*/ //default: send_err(connfd); //break; } } if (nbyte==2) { myReadn (connfd, buf, 4); memcpy ((void *) &num1_16, buf, sizeof(uint16_t)); num1_16=ntohs(num1_16); memcpy ((void *) &num2_16, buf+sizeof(uint16_t), sizeof(uint16_t)); num2_16=ntohs(num2_16);#ifdef TRACE err_msg("(%s) info - op: %c num1: %u num2: %u\r\n", prog, ch, num1_16, num2_16);#endif switch(ch) { case '+': if ( (int)(num1_16+num2_16) != (int) ( (uint16_t)(num1_16+num2_16) ) ) memcpy (buf, "V", sizeof(char)); else { memcpy (buf, "=", sizeof(char)); ris16=htons(num1_16+num2_16); memcpy (buf+sizeof(char), (void*)&ris16, sizeof(uint16_t)); Writen (connfd, buf, sizeof(char)+sizeof(uint16_t)); } break; case '-': if ( (int)(num1_16-num2_16) != (int) ( (uint16_t)(num1_16-num2_16) ) ) { memcpy (buf, "V", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else { memcpy (buf, "=", sizeof(char)); ris16=htons(num1_16-num2_16); memcpy (buf+sizeof(char), (void*)&ris16, sizeof(uint16_t)); Writen (connfd, buf, sizeof(char)+sizeof(uint16_t)); } break; case '*': if ( (int)(num1_16*num2_16) != (int) ( (uint16_t)(num1_16*num2_16) ) ) { memcpy (buf, "V", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else { memcpy (buf, "=", sizeof(char)); ris16=htons(num1_16*num2_16); memcpy (buf+sizeof(char), (void*)&ris16, sizeof(uint16_t)); Writen (connfd, buf, sizeof(char)+sizeof(uint16_t)); } break; case '/': if ( (uint16_t)num2_16==0 ) send_err(connfd); else if ( (int)(num1_16/num2_16) != (int) ( (uint16_t)(num1_16/num2_16) ) ) { memcpy (buf, "V", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else if ( ( (uint16_t)num1_16==0) || ( ( (uint16_t)(num1_16/num2_16) )==0 ) ) { memcpy (buf, "U", sizeof(char)); Writen (connfd, buf, sizeof(char)); } else { memcpy (buf, "=", sizeof(char)); ris16=htons(num1_16/num2_16); memcpy (buf+sizeof(char), (void*)&ris16, sizeof(uint16_t)); Writen (connfd, buf, sizeof(char)+sizeof(uint16_t)); } break; default: send_err(connfd); break; } } memset(buf, '\0', sizeof(buf)); } return;}/* * Funzione che invia msg di hello */void hello (int connfd){char buf[MAXBUFL],ch;size_t n;uint8_t byte=0; memset(buf, '\0', sizeof(buf)); while ((n = myReadn (connfd, buf, 1) > 0)) { ch=buf[0]; if (ch!=' ') { if (ch=='Q') return; if (ch=='H') { myReadn (connfd, buf, sizeof (uint8_t)); memcpy ((void *) &byte, buf, sizeof (uint8_t)); if (byte==1 || byte==2) { memset(buf, '\0', sizeof(buf)); snprintf (buf, sizeof(buf), "?\r\n"); Writen (connfd, buf, strlen(buf));#ifdef TRACE err_msg("(%s) info - Numero catturato: %d - lancio Calcolo(); \r\n", prog, (uint8_t)byte);#endif calc(connfd, byte); } else send_err(connfd); }else send_err(connfd); }else send_err(connfd); } return;}/* * main function */int main (int argc, char *argv[]){/* identificatori dei socket */int listenfd, connfd;/* dati connessioni */struct sockaddr_in servaddr, cliaddr;char buffer[MAXBUFL];socklen_t cliaddrlen;pid_t pid;uint8_t out=255, in=0;/* dati per la SETSOCKOPT */int on=1;struct linger ling; prog = argv[0]; check_args(argc, argv); queue = (child *)Malloc(children*sizeof(child)); memset ((void *) queue, 0, children*sizeof(child)); memset(buffer, '\0', sizeof(buffer)); listenfd = Socket (AF_INET, SOCK_STREAM, 0); /* permette il riuso immediato di un indirizzo ip */ Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); ling.l_onoff=0; ling.l_linger=0; /* se rimangono dei dati sul canale in chiusura tenta di inviarli lo stesso */ Setsockopt(listenfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); memset (&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(port); Bind (listenfd, (SA*) &servaddr, sizeof(servaddr)); Listen (listenfd, LISTENQ);#ifdef TRACE err_msg ("(%s) info - Socket created, waiting for connections ...\r\n", prog);#endif signal (SIGCHLD, sigchld_h); signal (SIGTERM, sigterm_h); signal (SIGINT, sigint_h); while (1) { cliaddrlen = sizeof(cliaddr); connfd = Accept (listenfd, (SA*) &cliaddr, &cliaddrlen);#ifdef TRACE err_msg ("(%s) info - New connection from client %s:%u\r\n", prog, inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));#endif if(connection>=children) { Writen (connfd, &out, sizeof(uint8_t));//IMP Close (connfd); } else { Writen (connfd, &in, sizeof(uint8_t)); if ((pid = myFork()) == 0) /* this is the child */ { Close (listenfd); signal(SIGCHLD, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); hello (connfd); Close (connfd); exit (0); } else /* this is the parent */ { Close (connfd); pid_queue(pid);#ifdef TRACE err_msg ("(%s) info - Child number %d (pid:%d) spawned\r\n", prog, connection, pid); err_msg ("(%s) info - Waiting for HELLO from child number %d ...\r\n", prog, connection);#endif } } } exit (0);}