Beispiel #1
0
bool Downloader::request_one() {
	log_->trace() << log_tag() << BOOST_CURRENT_FUNCTION;
	// Try to choose block to request
	for(auto& needed_chunk : needed_chunks_) {
		auto& ct_hash = needed_chunk.first;

		// Try to choose a remote to request this block from
		auto remote = find_node_for_request(ct_hash);
		if(remote == nullptr) continue;

		// Rebuild request map to determine, which block to download now.
		AvailabilityMap<uint32_t> request_map = needed_chunk.second->file_map();
		for(auto& request : needed_chunk.second->requests)
			request_map.insert({request.second.offset, request.second.size});

		// Request, actually
		if(!request_map.full()) {
			NeededChunk::BlockRequest request;
			request.offset = request_map.begin()->first;
			request.size = std::min(request_map.begin()->second, uint32_t(Config::get()->globals()["p2p_block_size"].asUInt()));
			request.started = std::chrono::steady_clock::now();

			remote->request_block(ct_hash, request.offset, request.size);
			needed_chunk.second->requests.insert({remote, request});
			return true;
		}
	}
	return false;
}
void call()
{
  int i=0;
	for(i;i<3;i++)
	{
		request_block();
	}
}
Beispiel #3
0
void listen_from_peers() 
{
    struct peer_state* peer = peers;
    unsigned int msglen = 0;
    while(missing_blocks() > 0)
    {
        fd_set fdrset_clone;
        fd_set fdwset_clone;
        FD_COPY(&fdrset,&fdrset_clone);
        FD_COPY(&fdwset,&fdwset_clone);
        int rdy = select(FD_SETSIZE,&fdrset_clone,&fdwset_clone,0, 0);
        if(rdy <= 0) {
            continue;
        }
        peer = peers;
        if(active_peers() == 0){
            break;
        }
        while(peer){
        
            if(FD_ISSET(peer->socket,&fdwset_clone)){
                if(peer->connected == 0){
                    //to send the handshake if it is not connected
                    send_handshake(peer);
                }
                else if(peer->send_count > 0) {
                    //to send the have/interested/piece messages to peers
                    send_buffed_msg(peer);
                }
            }

            if(FD_ISSET(peer->socket,&fdrset_clone)) 
            {
                int newbytes = recv(peer->socket,peer->incoming+peer->count,BUFSIZE-peer->count,0);
                if(newbytes <= 0){ 
                    peer->trying_to_connect = 0;
                    if(newbytes == 0){
                        piece_status[peer->requested_piece] = PIECE_EMPTY;
                    }
                    disconnet_peer(peer);
                    reconnect_peer(peer);
                    peer = peer->next;
                    continue; 
                } 
                peer->count += newbytes;
                if(!peer->handshaked){                    
                    peer->count -= peer->incoming[0]+49;
                    if(peer->count) {
                        memmove(peer->incoming,peer->incoming + peer->incoming[0]+49,peer->count);
                    }
                    peer->handshaked = 1;
                }

               if(memcmp(peer->incoming+peer->incoming[0]+8+20,"-UICCS450-",strlen("-UICCS450-"))==0) {
                    fprintf(stderr,"Caught a CS450 peer, exiting.\n");
                    disconnet_peer(peer);
                    continue;
                }   

                while(peer->count >= (ntohl(((int*)peer->incoming)[0])) + 4){ 
                msglen = ntohl(((int*)peer->incoming)[0]);

                   switch(peer->incoming[4]) {
                        // CHOKE
                        case 0: {
                                    if(debug)
                                        fprintf(stderr,"Choke\n");
                                    peer->choked = 1;
                                    piece_status[peer->requested_piece]=PIECE_EMPTY;
                                    peer->requested_piece = -1;
                                    break;
                                }
                                // UNCHOKE
                        case 1: {
                                    if(debug)
                                        fprintf(stderr,"Unchoke\n");
                                    peer->choked = 0;
                                    peer->requested_piece = next_piece(-1,peer);    
                                    request_block(peer,peer->requested_piece,0);
                                    break;
                                }
                                //Interested
                        case 2: {
                                    //dev_notifier();
                                    send_choke_unchoke_msg(peer,0); //ischoked = 0
                                    peer->not_interested = 0;
                                    break;
                                }
                                //Not interested
                        case 3: {
                                    //dev_notifier();
                                    peer->not_interested = 1;
                                    break;
                                }
                                // HAVE -- update the bitfield for this peer
                        case 4: {
                                    int piece = ntohl(*((int*)&peer->incoming[5]));
                                    int bitfield_byte = piece/8;
                                    int bitfield_bit = piece%8;
                                    if(debug)
                                        fprintf(stderr,"Have %d\n",piece);

                                    peer->bitfield[bitfield_byte] |= 1 << (7 - bitfield_bit);
                                    piece_occurence_value[piece]++;
                                    send_interested(peer);
                                    break;
                                }
                                // BITFIELD -- set the bitfield for this peer
                        case 5:
                                //peer->choked = 0; //commenting it according to prof's note in class
                                if(debug) 
                                    printf("Bitfield of length %d\n",msglen-1);
                                int fieldlen = msglen - 1;
                                if(fieldlen != (file_length/piece_length/8+1)) {
                                    disconnet_peer(peer);
                                    if(active_peers() == 0){
                                        break;
                                    }
                                    peer = peer->next;
                                    continue;
                                }               
                                memcpy(peer->bitfield,peer->incoming+5,fieldlen);
                                read_bit_maps(peer->bitfield,fieldlen);
                                send_interested(peer);
                                break;
                                //Request piece
                        case 6: { 
                                if(peer->i_choked_it == 1) 
                                    break;
                                decode_request_send_piece_to_peer(peer);
                                }       
                                break;                         
                                // PIECE
                        case 7: {
                                    //make the tit for tatter
                                    peer->send_recv_balancer++;
                                    if(peer->i_choked_it && peer->send_recv_balancer == 0){
                                        peer->i_choked_it = 0;
                                        send_choke_unchoke_msg(peer,0); //unchoke peer
                                    }
                                    int piece = ntohl(*((int*)&peer->incoming[5]));
                                    int offset = ntohl(*((int*)&peer->incoming[9]));
                                    int datalen = msglen - 9;

                                    fprintf(stderr,"Writing piece %d, offset %d, ending at %d\n",piece,offset,piece*piece_length+offset+datalen);
                                    write_block(peer->incoming+13,piece,offset,datalen,1);
                                    draw_state();
                                    offset+=datalen;
                                    if(offset==piece_length || (piece*piece_length+offset == file_length) ) {
                                        broadcast_have_msg(piece);
                                        draw_state();
                                        if(debug) 
                                            fprintf(stderr,"Reached end of piece %d at offset %d\n",piece,offset);

                                        peer->requested_piece=next_piece(piece,peer);
                                        offset = 0;
                                    }
                                    request_block(peer,peer->requested_piece,offset);
                                    break;                                  
                                }
                    }
                    drop_message(peer);      
                }
            }
            peer = peer->next;
        }
    }
    return;
}
Beispiel #4
0
// handles the message. no, we *don't* need to pass in msglen
int handle_message(struct peer_state* peer) {
	int msglen = ntohl(((int*)peer->incoming)[0]);	// because not returned from receive message
	int newbytes = 0;
	fflush(stdout);
	if(msglen == 0) {
		piece_status[peer->requested_piece] = PIECE_EMPTY;
		draw_state();
		shutdown_peer(peer);
		return 0;
	}
	// not picking any of the cases in switch; calling handle_message prematurely?
	switch(peer->incoming[4]) {

		// CHOKE
		case 0: {
			if(debug)
				fprintf(stderr,"Choke\n");
			peer->choked = 1;
			piece_status[peer->requested_piece] = PIECE_EMPTY;
			peer->requested_piece = -1;
			break;
		}
		// UNCHOKE
		case 1: {
			if(debug)
				fprintf(stderr,"Unchoke\n");
			peer->choked = 0;
			// grab a new piece - WARNING: this assumes that you don't get choked mid-piece!
			peer->requested_piece = next_piece(-1);
			// keep track of how many bytes downloaded of the piece
			// add to piece_status
			request_block(peer,peer->requested_piece,0);
			break;
		}
		// INTERESTED
		case 2: {
			// TODO: Send unchoke message to peer (?)
			peer->choked = 0; // unchoke peer
			break;
		}
		// HAVE -- update the bitfield for this peer
		case 4: {
			int piece_index = ntohl(*((int*)&peer->incoming[5]));
			int bitfield_byte = piece_index/8;
			int bitfield_bit = 7-(piece_index%8);
			if(debug)
				fprintf(stderr,"Have %d\n", piece_index);
			peer->bitfield[bitfield_byte] |= 1 << bitfield_bit;
			send_interested(peer);
			break;
		}
		// BITFIELD - set the bitfield for this peer
		case 5: {
			peer->choked = 0;
			if(debug)
				printf("Bitfield of length %d\n", msglen-1);
			int fieldlen = msglen - 1;
			if(fieldlen != (file_length/piece_length/8+1)) {
				fprintf(stderr,"Incorrect bitfield size, expected %d\n", file_length/piece_length/8+1);
				shutdown_peer(peer);
				return 0;
			}
			memcpy(peer->bitfield,peer->incoming+5,fieldlen);
			send_interested(peer);
			break;
		}
		// REQUEST
		case 6: {
			// peer is requesting piece
			// copy from file 
			// send to them
			// update ratio information
			break;
		}
		// PIECE
		case 7: {
			int piece = ntohl(*((int*)&peer->incoming[5]));
			int offset = ntohl(*((int*)&peer->incoming[9]));
			int datalen = msglen - 9;

			fprintf(stderr,"Writing piece %d, offset %d, ending at %d\n", piece, offset, piece*piece_length+offset+datalen);
			write_block(peer->incoming+13,piece,offset,datalen,1);		// save this block to comp

			draw_state(); // segfault source?
			offset += datalen;
			if(offset==piece_length || (piece*piece_length+offset == file_length) ) {
				if(debug)
					fprintf(stderr, "Reached end of piece %d at offset %d\n", piece, offset);

				peer->requested_piece = next_piece(piece);
				offset = 0;

				if(peer->requested_piece == -1) {
					fprintf(stderr,"No more pieces to download!\n");

					// but don't exit if sth. is still being downloaded
					for(int i = 0; i < file_length/piece_length+1; i++) 
						if(piece_status[i] != 2) {
							shutdown_peer(peer);
							return 0;
						}
						shutdown_peer(peer);
						return 0;
				}
			}
			request_block(peer,peer->requested_piece,offset);
			break;
		}
		case 20: {
			printf("Extended type is %d\n", peer->incoming[5]);
			struct bencode *extended = ben_decode(peer->incoming,msglen);
			print_bencode(extended);
			break;
		}
    }
	drop_message(peer);
	return 1;
}