/** * receive the packet, save it into buffer * send corresponding ack back * @param dl, the handler * @param pkt, the received packet * @return 0 on success, -1 if fails */ int dl_recv(download_t *dl, packet_t *pkt) { uint32_t seq; size_t offset; if (dl->finished) { return 0; } /* do not update rtt until start */ if (dl->started && !dl->block_update) { update_rtt(&dl->rtt, &dl->dev, dl->ts); } else { /* record data_len for the first time */ dl->data_length = GET_DATA_LEN(pkt); dl->started = 1; dl->block_update = 0; } seq = GET_SEQ(pkt); offset = (seq - 1) * dl->data_length ; // discard data packet with seq number not sitting in current receive window // or size exceeds the buffer length. if( ! seq_fit_in(&dl->rwin, seq) || offset + GET_DATA_LEN(pkt) > BT_CHUNK_SIZE){ return -1; } if(! seq_exist_in(&dl->rwin, seq)){ memcpy(dl->buffer + offset, GET_DATA(pkt), GET_DATA_LEN(pkt)); recvwin_mark(&dl->rwin, seq); } send_ack(dl->p_index, get_ack(dl)); dl->ts = get_timestamp_now(); dl->timeout_cnt = 0; if ( (dl->next_pkt_expected -1)* dl->data_length >= BT_CHUNK_SIZE) { dl->finished = 1; } return 0; }
int process_pong(Header *header, ChordPacketArgs *args, Pong *msg, Node *from) { ChordServer *srv = args->srv; Finger *f, *pred, *newpred; ulong new_rtt; int fnew; if (IN6_IS_ADDR_UNSPECIFIED(&srv->node.addr)) return CHORD_ADDR_UNDISCOVERED; if (!verify_ticket(srv->ticket_salt, srv->ticket_salt_len, srv->ticket_hash_len, msg->ticket.data, msg->ticket.len, "c6sl", CHORD_PING, &from->addr, from->port, msg->time)) return CHORD_INVALID_TICKET; f = insert_finger(srv, &from->id, &from->addr, from->port, &fnew); if (!f) return CHORD_FINGER_ERROR; LOG_PROCESS(&from->id, &from->addr, from->port); f->npings = 0; new_rtt = get_current_time() - msg->time; /* takes care of overlow */ update_rtt(&f->rtt_avg, &f->rtt_dev, (long)new_rtt); pred = pred_finger(srv); activate_finger(srv, f); /* there is a two-way connectivity to this node */ newpred = pred_finger(srv); /* check whether pred has changed, i.e., * f has became the new pred */ assert(newpred || (pred == newpred)); if (pred != newpred) chord_update_range(srv, &newpred->node.id, &srv->node.id); return CHORD_NO_ERROR; }
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)); } } } }
static void cpg_bm_deliver_fn ( cpg_handle_t handle_in, const struct cpg_name *group_name, uint32_t nodeid, uint32_t pid, void *msg, size_t msg_len) { uLong crc=0; struct cpghum_header *header = (struct cpghum_header *)msg; uLong recv_crc = header->crc & 0xFFFFFFFF; unsigned int *dataint = (unsigned int *)((char*)msg + sizeof(struct cpghum_header)); unsigned int datalen; if (nodeid > MAX_NODEID) { cpgh_log_printf(CPGH_LOG_ERR, "Got message from invalid nodeid %d (too high for us). Quitting\n", nodeid); exit(1); } packets_recvd++; packets_recvd1++; g_recv_length = msg_len; datalen = header->size - sizeof(struct cpghum_header); // Report RTT first in case abort_on_error is set if (nodeid == g_our_nodeid) { unsigned long rtt_usecs; // For flood update_rtt(&header->timestamp, packets_recvd1, &interim_min_rtt, &interim_avg_rtt, &interim_max_rtt); rtt_usecs = update_rtt(&header->timestamp, g_recv_counter[nodeid], &min_rtt, &avg_rtt, &max_rtt); if (report_rtt) { if (machine_readable) { cpgh_log_printf(CPGH_LOG_RTT, "%ld%c%ld%c%ld%c%ld\n", rtt_usecs, delimiter, min_rtt, delimiter, avg_rtt, delimiter, max_rtt); } else { cpgh_log_printf(CPGH_LOG_RTT, "%s: RTT %ld uS (min/avg/max): %ld/%ld/%ld\n", group_name->value, rtt_usecs, min_rtt, avg_rtt, max_rtt); } } } // Basic check, packets should all be the right size if (msg_len != header->size) { length_errors++; cpgh_log_printf(CPGH_LOG_ERR, "%s: message sizes don't match. got %zu, expected %u from node %d\n", group_name->value, msg_len, header->size, nodeid); if (abort_on_error) { exit(2); } } g_recv_size[nodeid] = msg_len; // Sequence counters are incrementing in step? if (header->counter != g_recv_counter[nodeid]) { /* Don't report the first mismatch or a newly restarted sender, we're just catching up */ if (g_recv_counter[nodeid] && header->counter) { sequence_errors++; cpgh_log_printf(CPGH_LOG_ERR, "%s: counters don't match. got %d, expected %d from node %d\n", group_name->value, header->counter, g_recv_counter[nodeid], nodeid); if (abort_on_error) { exit(2); } } else { g_recv_start[nodeid] = header->counter; } /* Catch up or we'll be printing errors for ever */ g_recv_counter[nodeid] = header->counter+1; } else { g_recv_counter[nodeid]++; } /* Check crc */ crc = crc32(0, NULL, 0); crc = crc32(crc, (Bytef *)dataint, datalen) & 0xFFFFFFFF; if (crc != recv_crc) { crc_errors++; cpgh_log_printf(CPGH_LOG_ERR, "%s: CRCs don't match. got %lx, expected %lx from nodeid %d\n", group_name->value, recv_crc, crc, nodeid); if (abort_on_error) { exit(2); } } g_recv_count++; }
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++; }