static void recalc_tmo(unsigned long tmo, struct timeval *t0, struct timeval *t)
{
        unsigned long dt;

        dt = elapsed_msec(t0);
        dt = (dt < tmo) ? tmo - dt : 0;
        (void)msec_to_timeval(dt, t);
}
Esempio n. 2
0
/* updates rtt and deviation estimates based on new sample */
void update_rtt(unsigned this_rtt) {
	// if this is the first packet, make an 'educated guess' as to the rtt and deviation
	if(sequence_number==0) {
		rtt = this_rtt;
		deviation = this_rtt/2;
	}
	else {
	  deviation = 0.7*deviation + 0.3*(abs(this_rtt - rtt));
	  rtt = 0.8*rtt + 0.2*this_rtt;
	}
	msec_to_timeval(rtt+4*deviation,&timeout);
}
Esempio n. 3
0
File: hw6.c Progetto: lfcmpi/UIC
void wait_for_ack(int sock) {

	// repeatedly send it until we get an ack
	while(1) {
		fd_set readset;
		FD_ZERO(&readset);
		FD_SET(sock,&readset); 

		struct timeval t;
		if(window[0].sent_at + timeout > current_msec()) {			
			unsigned msec_until_expiry = window[0].sent_at + timeout - current_msec(); 
			msec_to_timeval(msec_until_expiry,&t);
		}
		else {
			msec_to_timeval(10,&t);
		}

		/*		// always allow a 1 msec wait
		if(msec_until_expiry<0) {
			t.tv_sec = 0;
			t.tv_usec = 100;
			//			memset(&t,0,sizeof(t));
			}*/

		int rdy = select(FD_SETSIZE,&readset,0,0,&t);

		char incoming[1400];
		struct hw6_hdr *hdr = (struct hw6_hdr*)incoming;
		if(rdy>0) {
			struct sockaddr_in from_addr;
			unsigned int addrsize = sizeof(from_addr);
			int recv_count=recvfrom(sock,incoming,1400,0,(struct sockaddr*)&from_addr,&addrsize);
			if(recv_count<0) {
				perror("When receiving packet.");
				return;
			}
		}

		// if we timed out, or got a double acknowledgment, double the timeout value and send again
		if(rdy==0 || 
			 // double acknowledgment only triggers retransmission once per round-trip time
			 (ntohl(hdr->ack_number)==ntohl(window[0].data->sequence_number)-1 && 
				((current_msec() - window[0].sent_at) > rtt))) { //last_ack_number) {
			if(rdy==0)
				fprintf(stderr,"\nTimed out on packet %d, msec %u\n",ntohl(window[0].data->sequence_number),timeval_to_msec(&t));//,msec_until_expiry);
			else
				fprintf(stderr,"\nDouble ack indicating loss of packet %d, msec %u\n",ntohl(window[0].data->sequence_number),timeval_to_msec(&t));//,msec_until_expiry);

			fprintf(stderr,"Window packets: ");
			for(int p=0;p<packets_outstanding;p++) {
				fprintf(stderr,"%d, ",ntohl(window[p].data->sequence_number));				
			}
			fprintf(stderr,"\n");

			timeout *= 2;
			if(timeout > MAX_TIMEOUT) 
				timeout = MAX_TIMEOUT;

			window_size /=2;
			if(window_size < 1) 
				window_size=1;
			
			ssthresh = window_size;
			congestion_avoidance = 1;
			ca_last_increase = current_msec();

			for(int i=0;i<packets_outstanding && i<window_size;i++)  {
				fprintf(stderr,"Resending Packet %d with rtt %f dev %f timeout %d ms window %d  to %s         \n",ntohl(window[i].data->sequence_number),rtt, deviation,timeout,window_size,inet_ntoa(peeraddr.sin_addr));
				if(sendto(sock, window[i].data, window[i].len, 0,(struct sockaddr*)&peeraddr,sizeof(peeraddr)) <=0)
						perror("Couldn't send!");
				window[i].retx = 1;
				window[i].sent_at = current_msec(); // update the timestamp
			}
			fprintf(stderr,"Done resending, for now\n");

		}
		else if(rdy==-1) {
			perror("select error");
		}
		else {
			
			/* blow away all the packets acked here */
			// fprintf(stderr,"Got ack for %d, time left %d, rtt %d, retx %d\n",ntohl(hdr->ack_number), timeval_to_msec(&t), current_msec() - window[0].sent_at, window[0].retx);
			int got_ack=0;
			last_ack_number = ntohl(hdr->ack_number);
			while(packets_outstanding > 0 && ntohl(hdr->ack_number) >= ntohl(window[0].data->sequence_number)) {
				if(!window[0].retx)
					update_rtt(current_msec() - window[0].sent_at);
				pop_packet(sock);

				got_ack=1;
			}

			if(got_ack) break;
			
			if(! (hdr->flags & ACK)) {
				// ack whatever we have so far
				struct hw6_hdr ack;
				ack.flags = ACK;
				if(ntohl(hdr->sequence_number) == expected_sequence_number) {
					expected_sequence_number++;
				}
				else {
					fprintf(stderr,"Unexpected non-ACK in rel_send(). Acking what we have so far. \n");
				}
				ack.ack_number = htonl(expected_sequence_number-1);
				sendto(sock, &ack, sizeof(ack), 0,(struct sockaddr*)&peeraddr,sizeof(peeraddr));
			}		 
		}
	}

}
Esempio n. 4
0
void rel_send(int sock, void *buf, int len)
{
    if(user == UNKNOWN){
        user = SENDER;
    }
    int flag_ack_checked;
    int flag_packet_dropped;
 	// make the packet = header + buf
	char packet[1400];
	struct hw7_hdr *hdr = (struct hw7_hdr*)packet;
	flag_ack_checked = 0;
	flag_packet_dropped = 0;
	memset(hdr,0,sizeof(struct hw7_hdr));
	hdr->sequence_number = htonl(sequence_number);
	memcpy(hdr+1,buf,len);

	fprintf(stderr,"\r<SHUBHAM>Sent Packet - %d with rtt %d dev %d timeout - %d ms           \n",sequence_number,rtt, deviation,timeval_to_msec(&timeout));
	sendto(sock, packet, sizeof(struct hw7_hdr)+len, 0,(struct sockaddr*)&peeraddr,sizeof(peeraddr));

	// put packet in queue, flag = ack not rxed, seq_no
    struct senderQelements *s;
    s = calloc(sizeof(struct senderQelements),1);
    s->magic = 'S';
    s->ack_rxed = 0;
    s->retx = 0;
    s->packet_len = sizeof(struct hw7_hdr) + len;
    s->sent_time = current_msec();
    memcpy(s->packet, packet, s->packet_len);
    doQInsert((char *)s);

	// 1. If queue has no. of elements  == window size or if this is the close packet
    if(getCurrentQSize() == window_size || len == 0){
        int ack_count;
        ack_count = 0;
	//      wait for acks from all
        while(ack_count < window_size) {
            if(getCurrentQSize() == 0){ //double check...otherwise we might go in infinite loop //remove
                break;
            }

            fd_set readset;
            FD_ZERO(&readset);
            FD_SET(sock,&readset); 

            struct timeval t = timeout; // select changes the timeout parameter on some platforms, so make a copy

            int rdy = select(FD_SETSIZE,&readset,0,0,&t);

            if(rdy==0) {
                //send all unacked packets again
                send_all_unacked_packets_again(sock);
                flag_packet_dropped = 1;
                // if we timed out, send again double the timeout value
                msec_to_timeval(min(1000,2*timeval_to_msec(&timeout)), &timeout);
                /*
                fprintf(stderr,"\rSent Packet %d with rtt %d dev %d timeout %d ms           ",sequence_number,rtt, deviation,timeval_to_msec(&timeout));
                sendto(sock, packet, sizeof(struct hw7_hdr)+len, 0,(struct sockaddr*)&peeraddr,sizeof(peeraddr));
                //s->retx=1;
                fprintf(stderr,"\r<SHUBHAM>Retransmitting - Packet %d with rtt %d dev %d timeout %d ms           \n",sequence_number,rtt, deviation,timeval_to_msec(&timeout));
                */
            }
            else if(rdy==-1) {
                perror("select error");
            }
            else {
                char incoming[1400];
                struct sockaddr_in from_addr;
                unsigned int addrsize = sizeof(from_addr);
                int recv_count=recvfrom(sock,incoming,1400,0,(struct sockaddr*)&from_addr,&addrsize);
                if(recv_count<0) {
                    perror("When receiving packet.");
                    return;
                }

                struct hw7_hdr *hdr = (struct hw7_hdr*)incoming;
                if(ntohl(hdr->ack_number) >= start_seq_no && ntohl(hdr->ack_number) <= (start_seq_no + window_size - 1)) {
                    fprintf(stderr,"\r<SHUBHAM>Got ack for %d       \n",ntohl(hdr->ack_number));
                    fprintf(stderr,"<SHUBHAM> Ack rxed - %d , start_seq_no , redundant log\n", (ntohl(hdr->ack_number)) - start_seq_no, start_seq_no);
                    struct senderQelements *s;
                    s = getNthElement((ntohl(hdr->ack_number)) - start_seq_no);
                    fprintf(stderr,"<SHUBHAM> nth element in Q packet->seq_no = %d\n", ntohl(((struct hw7_hdr *)s->packet)->sequence_number));
                    if(s->ack_rxed){
                        fprintf(stderr,"<SHUBHAM> RE-Ack rxed - %d , doing nothing\n", (ntohl(hdr->ack_number)) - start_seq_no);
                    }
                    else{
                        ack_count++;
                        if(!s->retx){
                            // if this is an ack for our present packet, update the rtt and exit
                            update_rtt(current_msec() - s->sent_time);
                        }
                    }
                    s->ack_rxed = 1;
                    //break;
                }

                // if it's not an ack, it's the end of the stream. ACK it. 
                // Scenario: 1. Sender sends close, 2. rxer sends ack(it is lost), 3. rxer sends close, 4. sender recives close in rel_send()
                /*SHUBHAM: todo?? Handle the close part here?? */
                if(! (hdr->flags & ACK)) {
                    // ack whatever we have so far
                    struct hw7_hdr ack;
                    ack.flags = ACK;
                    if(ntohl(hdr->sequence_number) == expected_sequence_number) {
                        expected_sequence_number++;
                    }
                    else {
                        fprintf(stderr,"Unexpected non-ACK in rel_send(), size %d. Acking what we have so far. \n",recv_count);
                    }
                    ack.ack_number = htonl(expected_sequence_number-1);
                    fprintf(stderr,"\r<SHUBHAM>Exception: Sending ACK - %d  for a non-ack packet receivd        \n",ntohl(ack.ack_number));
                    sendto(sock, &ack, sizeof(ack), 0,(struct sockaddr*)&peeraddr,sizeof(peeraddr));
                }		 
            }
            flag_ack_checked = 1;
        }
    }
    /*
    else{
        //      return, so that user can send next packet.
        return;
    }
    */
    if(len == 0 && !flag_ack_checked){
        perror("Some problem");
        exit(2);
    }
    if(flag_ack_checked){
        while(getCurrentQSize() > 0){ //make_raghvan_change
            struct senderQelements *s;
            s = doQDelete();
            free(s);
        }
        start_seq_no = start_seq_no + window_size; //make_raghvan_change
	    if(start_seq_no != sequence_number+1){
	        exit(20); //assert_remove
        }
        if(flag_packet_dropped == 1){
            decrease_window_size();
        }
        else{
            increase_window_size();
        }
    }
	sequence_number++;
}
/*
 * We end up here due to a osegw_receive, osegw_receive_w_tmo or
 * osegw_init_async_receive. While we are waiting for a signal,
 * we must be able to handle "pings" and osegw_cancel_async_receive
 * from the client.
 */
int OseGW_PLT_ReceiveRequest_cbk(int skt, int len, char *payload,
                                 struct ClientInfo *cinfo)
{
	struct OseGW_ReceiveRequest *req;
        struct OseGW_TransportHdr thdr;
        union LINX_SIGNAL *sig;
        LINX_SIGSELECT *sigsel;
        int nfds, status, size, linx_skt, sigsel_len;
        fd_set rfds;
        struct timeval tv0, tv, *tvp;
        unsigned int tmo;
        void *buf;

        linx_skt = linx_get_descriptor(cinfo->linx);
	req = (struct OseGW_ReceiveRequest *)payload;
        sigsel_len = ntohl(req->sigsel_len);
        buf = NULL;

        /* 0. This may be a osegw_cancel_async_receive... */
        if (sigsel_len == 0) {
                sig = NULL;
                size = 0;
                goto out;
        }

        /* 1. Setup signal filter that should be used while polling... */
        sigsel = copy_sigselect(req);
        if (sigsel == NULL)
                goto e_exit;
        if (set_sigselect(linx_skt, sigsel) == -1)
                goto e_exit;

        /* 2. Setup time-out... */
	tmo = ntohl(req->timeout);
        if (tmo != (unsigned int)~0) {
                tvp = msec_to_timeval(tmo, &tv);
                if (gettimeofday(&tv0, NULL) == -1)
                        goto e_exit;
        } else
                tvp = NULL; /* Infinite */

  again:

        /* 3. Setup descriptors... */
        FD_ZERO(&rfds);
        FD_SET(linx_skt, &rfds); /* LINX socket */
        FD_SET(skt, &rfds);      /* TCP socket */
        nfds = linx_skt > skt ? linx_skt : skt;

        /* 4. Wait for a signal, ping or osegw_cancel_async_receive */
        status = select(nfds + 1, &rfds, NULL, NULL, tvp);
        if (status == -1)
                goto e_exit;

        if (status == 0) {
                /* osegw_receive_w_tmo has timed out */
                sig = NULL;
                size = 0;
                goto out;
        }

        if (FD_ISSET(linx_skt, &rfds)) {
                /* A signal that matches the signal filter is available */
                status = linx_receive(cinfo->linx, &sig, sigsel);
                if (status == -1)
                        goto e_exit;
                size = linx_sigsize(cinfo->linx, &sig) - sizeof(SIGSELECT);
                goto out;
        }

        if (FD_ISSET(cinfo->sd, &rfds)) {
                /* Get command */
                buf = get_command(skt, &thdr);
                if (buf == NULL)
                        goto e_exit;

                switch (thdr.payload_type) {
                case OseGW_PLT_InterfaceRequest:
                        status = OseGW_PLT_InterfaceRequest_cbk(skt, thdr.payload_len, buf, cinfo);
                        if (status == -1)
                                goto e_exit;
                        /* Compensate for the time spent in select */
                        if (tvp != NULL)
                                recalc_tmo(tmo, &tv0, &tv);
                        goto again;
                        break;
                case OseGW_PLT_ReceiveRequest:
                        req = (struct OseGW_ReceiveRequest *)buf;
                        sigsel_len = ntohl(req->sigsel_len);
                        if (sigsel_len != 0)
                                goto e_exit; /* Only cancel async receive is allowed */
                        sig = NULL;
                        size = 0;
                        goto out;
                        break;
                default:
                        syslog(LOG_INFO, "Gateway protocol violation detected, "
                               "got type %d while in a receive", thdr.payload_type);
                        goto e_exit;
                        break;
                }
        }
  out:
        free(buf);
        free(sigsel);
        return OseGW_PLT_ReceiveReply_cbk(skt, size, (char *)sig, cinfo);

  e_exit:
        free(buf);
        free(sigsel);
        return -1;
}