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);
}
Exemple #2
0
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;
}