void sendPacket() { char* buffer; int length; if(currentAlarm == NULL) { length = 9; buffer = malloc(sizeof(char)*length); memset(buffer, 0, length); strcpy(buffer, "Exit\r\n\r\n"); } else { length = (strlen(currentAlarm->reminder)+10+3); buffer = malloc(sizeof(char)*length); if(!buffer) { printf("Failed to malloc for writing alarm to packet!\r\n"); exit(-1); } memset(buffer, 0, length); strcpy(buffer, timeToString(currentAlarm->reminderNumber)); strcat(buffer, " "); writeTimeOfDay(buffer); strcat(buffer, currentAlarm->reminder); strcat(buffer, "\r\n"); #ifdef Debug printf("Packet: %s\r\n", buffer); #endif } mySendTo(udpSocket, buffer, length, 0, registeredaddr, addrlen); }
int main(int argc, char * argv[]){ //first, check the number of argument if (argc != 2){ printf("Usage: serveur.exe <port number>\n"); exit(1); } //trap SIGINT signal(SIGINT,SIGINT_handler); //variable definition int sock_Data, addr_len,pid, seq, cwnd,normal_wnd, advanced_wnd; int test =-1; int SEG_SIZE,size,inc,descriptorToCheck[2]; int reuse = 1; int ctrlBuff_SIZE = 12; int isSYN=0; int seq_advanced, seq_expected,checkBreak=0; char SYN_ACK[12]; char FIN[4]="FIN"; char ctrlBuffer[ctrlBuff_SIZE]; char * dataBuffer; FILE * file; DATA DATA = NULL; struct timeval ZERO = {0, 0}; // struct sockaddr_in SOCKADDR_IN * my_addr_UDP;//Adress for listening UDP SOCKADDR_IN * my_client_addr;//Adress client, for control SOCKADDR_IN * data_addr;//Adress client for Data int port_nb = atoi(argv[1]); int sock_Control= mySocket(AF_INET,SOCK_DGRAM,0); //socketUDP //display the descriptor value and pid of server printf("Id Socket: %i\n",sock_Control); printf("PID father: %i\n",getpid()); //allow to reuse immediately the socket setsockopt( sock_Control, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); // structure sockaddr_in initialization my_addr_UDP = conf_sock_addr(AF_INET, port_nb, "0.0.0.0"); my_client_addr = init_sock_addr(); size = sizeof(*my_client_addr); //link the socket to the structure myBind(sock_Control,my_addr_UDP,sizeof(*my_addr_UDP)); descriptorToCheck[0] = sock_Control; //init fd set fd_set * my_read_set = init_fd_set(); //loop to be a daemon while (isSIGINT==0){ //set the fd_set set_fd_set(my_read_set,descriptorToCheck[0]); select(sock_Control+1,my_read_set,NULL,NULL,&ZERO); if ( FD_ISSET(sock_Control, my_read_set) ){ // message reception myReceiveFrom(sock_Control, ctrlBuffer, ctrlBuff_SIZE,my_client_addr,&size); printf("Reception UDP by %d: %s\n",getpid(),ctrlBuffer); // if message of type SYN if ( check_SYN(ctrlBuffer) == 1){ port_nb= (port_nb+1)%8975+1025 ; sprintf(SYN_ACK,"SYN-ACK%04d",port_nb); //new socket for receiving data sock_Data = mySocket(AF_INET,SOCK_DGRAM,0); data_addr = conf_sock_addr(AF_INET, port_nb, "0.0.0.0"); addr_len = sizeof(* data_addr); descriptorToCheck[1]=sock_Data; //binding sock on addr client myBind(sock_Data,data_addr,addr_len); printf("Connexion Asked by client, dialoguing on port %d \n", ntohs(data_addr->sin_port)); printf("Adresse client %s\n",inet_ntoa(my_client_addr->sin_addr)); data_addr = conf_sock_addr(AF_INET, port_nb, inet_ntoa(my_client_addr->sin_addr)); // variable for receiving SEG_SIZE= getMTU(data_addr)-28; // (MTU - header UDP + header IP) SEG_SIZE=(SEG_SIZE> 5000)?5000:SEG_SIZE; dataBuffer = (char *)malloc(SEG_SIZE*sizeof(char)); isSYN=1; mySendTo(sock_Control, SYN_ACK,12,my_client_addr); } if ( check_ACK(ctrlBuffer) == 1 && isSYN ==1){ printf("Connexion Accept\n"); isSYN = 0; //a little fork pid = fork(); //if error if (pid == -1){ perror("Fork Error\n"); exit(-1); } /*======================================================================================*/ /*===================================== child code =====================================*/ /*======================================================================================*/ else if (pid == 0){ myClose(sock_Control); // reception of file name myReceiveFrom(sock_Data,dataBuffer, SEG_SIZE,data_addr,&addr_len); printf("Client Asking for file %s\n",dataBuffer); //retrieve file name file=myOpen(dataBuffer,"r"); seq=1, seq_advanced=1, cwnd =400,normal_wnd=320, advanced_wnd=cwnd-normal_wnd; //while something to send, send and wait for ack do { checkBreak=0; seq_expected=(seq == seq_advanced)?seq+cwnd:seq_advanced+advanced_wnd; printf("seq :%d, seq_expected %d, seq_advanced %d\n",seq, seq_expected, seq_advanced); //construct DATA to send from file if (test == -1) test= readFileToBUFFER(file,&DATA,seq,(seq+cwnd==seq_expected)?cwnd:seq_advanced-seq+advanced_wnd,SEG_SIZE); else readFileToBUFFER(file,&DATA,seq,test-seq,SEG_SIZE); //send dataBuffer to client if(seq+normal_wnd==seq_expected || seq == 1) { sendData(sock_Data, cwnd, DATA, data_addr); }else{ printf("fast retransmit, resend sequence presumed lost\n"); sendData(sock_Data, normal_wnd, DATA, data_addr); printf("fast retransmit, send selected data\n"); sendSelectedData(sock_Data,seq_advanced,advanced_wnd,DATA,data_addr); } //while there is something to read set_fd_set(my_read_set, descriptorToCheck[1]); select(sock_Data + 1, my_read_set, NULL, NULL, &ZERO); while (FD_ISSET(sock_Data,my_read_set) ) { //reception myReceiveFrom(sock_Data, ctrlBuffer, ctrlBuff_SIZE, data_addr, &addr_len); //number of sequences acknowledged, (-1 si duplicate ACK) inc = check_ACK_Seq(seq,cwnd,ctrlBuffer); if (inc == -1) // if duplicate ACK { printf("ACK Duplicate "); sendSelectedData(sock_Data,seq,1,DATA,data_addr); if (checkBreak==0){ usleep(100000); checkBreak=1; } } else if (inc > 0){// if good ACK checkBreak=0; seq += inc; if (seq==seq_expected)break; } //set the descriptor to check set_fd_set(my_read_set, descriptorToCheck[1]); select(sock_Data + 1, my_read_set, NULL, NULL, &ZERO); } if ( test == -1) seq_advanced=(seq_advanced+advanced_wnd > seq+2000 || seq_advanced < seq+normal_wnd)?seq+normal_wnd:seq_advanced+advanced_wnd; else seq_advanced=(seq_advanced+advanced_wnd > seq + 2000 || seq_advanced+advanced_wnd> test+1)?seq+normal_wnd:seq_advanced+advanced_wnd; } while(seq != test+1 ); printf("client dialoguing on port %d\n",ntohs(data_addr->sin_port)); for(reuse=0;reuse<1000000;reuse++) mySendTo(sock_Data, FIN, 4, data_addr); //Send FIN to client //to do a clean exit myClose(sock_Data); free(my_addr_UDP); free(my_client_addr); free(dataBuffer); free_Data(DATA); fclose(file); printf("\e[1;3%dmEnd of connexion. Son with pid:%d is closing, communicate on %d\e[0m\n", sock_Data % 8, getpid(),port_nb); exit(1); } /*======================================================================================*/ /*==================================== end of child ====================================*/ /*======================================================================================*/ } }
int main(int argc, char**argv) { if (argc < 4) { write(2, "You must supply an IP address, a port, and a secret key!\r\n", 25); return -1; } #ifdef Debug printf("Argv[1]: %s\r\nArgv[2]: %s\r\nArgv[3]: %s\r\n", argv[1], argv[2], argv[3]); #endif int port = numberFromString(argv[2]); if (port < 49152 || port > 65535) { write(2, "The port must be between 49152 and 65535!\r\n", 43); return -1; } #ifdef Debug printf("Port: %d\r\n", port); #endif // Malloc space for our secret key secret = mallocAndCheck(sizeof(char)*strlen(argv[3])); strcpy(secret, argv[3]); #ifdef Debug printf("Secret: %s\r\n", secret); #endif char *buffer = mallocAndCheck(sizeof(char)*1024); int x; for(x = 0; x < 1024; x++) { buffer[x] = '\0'; } int msglen = 1024; addrlen = (socklen_t)sizeof(struct sockaddr_storage); udpSocket = socket(AF_INET, SOCK_DGRAM, 0); if(udpSocket <= 0) { write(2, "Unable to bind socket!\r\n", 24); return -1; } registeredaddr = mallocAndCheck(addrlen); ((struct sockaddr_in *)registeredaddr)->sin_family = AF_INET; ((struct sockaddr_in *)registeredaddr)->sin_port = htons(port); // Parse the arg given to us for the IP if(inet_pton(AF_INET, argv[1], &((struct sockaddr_in *)registeredaddr)->sin_addr) <= 0) { write(2, "Failed to parse IP Address!\r\n", 29); return -1; } int reminders = 1; int registered = 0; int lastReminder = 0; setClientAlarmHandler(); // While we have reminders to receive while(reminders) { for(x = 0; x < 1024; x++) { buffer[x] = '\0'; } // If we've not registered, send a registration packet if(!registered) { registration(0); } // Busy wait for a packet while(recvfrom(udpSocket, buffer, msglen, 0, registeredaddr, &addrlen) <= 0) { // If we've not received a registration ACK // and we don't have an alarm set to send it // again, we'll set a timer if(!alarmSet) setClientAlarm(); } #ifdef Debug printf("\r\nReceived: %s\r\n", buffer); #endif // Exit packet will tell us when we're done if(strcmp(buffer, "Exit\r\n\r\n") == 0) { write(2, "All Reminders Received!\r\n", 25); reminders = 0; } // Our registration was dropped! else if (strcmp(buffer, "DropRegistration\r\n\r\n") == 0) { write(2, "Registration Dropped!\r\n", 23); registered = 0; } // Our registration was accepted! else if (strcmp(buffer, "Registered\r\n\r\n") == 0) { write(2, "Registered!\r\n", 13); registered = 1; alarm(0); } // Default case else { int number = numberFromString(buffer); #ifdef Debug printf("Received: %d, Last: %d\r\n", number, lastReminder); #endif // If we've received a reminder that is more than just the increment // of the last one, send the resend packet if(number - lastReminder > 1) { // WE LOST A PACKET! char* resend = mallocAndCheck(sizeof(char)*8 + sizeof(int)); memset(resend, 0, sizeof(char)*8 + sizeof(int)); strcpy(resend, "Resend\t"); strcat(resend, timeToString(lastReminder+1)); mySendTo(udpSocket, resend, strlen(resend), 0, registeredaddr, addrlen); } // Otherwise, cancel our registration alarm if we've had one // and update our last received reminder. // Display the reminder packet; else { alarm(0); alarmSet = 0; lastReminder = number; write(2, buffer, strlen(buffer)); write(2, "\r\n", 2); } } } return 0; }