예제 #1
0
파일: hw4.c 프로젝트: raghavan/networking
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;
}
예제 #2
0
int Peer::clock()
{
    if (m_state == PEER_STATE_SEND_HANDSHAKE)
    {
        if (m_sock == NULL)
        {
            try
            {
                m_nm->Socket_add(m_addr, shared_from_this(), m_sock);
            }
            catch (...)
            {
                goto_sleep();
                return ERR_INTERNAL;
            }
        }
        if (send_handshake() != ERR_NO_ERROR)
            goto_sleep();
        if (send_bitfield() != ERR_NO_ERROR)
            goto_sleep();
        m_state = PEER_STATE_WAIT_HANDSHAKE;
    }
    if (!m_peer_choking)
    {
        if (m_state == PEER_STATE_GENERAL_READY )
            m_state = PEER_STATE_REQUEST_READY;
    }
    else if (m_state == PEER_STATE_GENERAL_READY || m_state == PEER_STATE_REQUEST_READY)
    {
        send_interested();
        m_state = PEER_STATE_WAIT_UNCHOKE;
    }
    //если находимся в нужном состоянии и очередь не пуста
    if ((m_state == PEER_STATE_GENERAL_READY || m_state == PEER_STATE_REQUEST_READY || m_state == PEER_STATE_WAIT_UNCHOKE) && !m_requests_queue.empty())
    {
        char block[BLOCK_LENGTH];
        uint32_t block_length;
        PIECE_INDEX piece_index;
        BLOCK_INDEX block_index;
        std::set<BLOCK_ID>::iterator iter = m_requests_queue.begin();
        get_piece_block_from_block_id(*iter, piece_index, block_index);
        //если удалось прочитать блок и отправить, удаляем индекс блока из очереди
        if (m_torrent->read_block(piece_index, block_index, block, block_length) == ERR_NO_ERROR &&
                send_piece(piece_index, BLOCK_LENGTH * block_index, block_length, block) == ERR_NO_ERROR)
        {
            m_requests_queue.erase(iter);
            m_torrent->inc_uploaded(block_length);
            m_uploaded += block_length;
            //logger::LOGGER() << "rx=%f tx=%f\n", get_rx_speed(), get_tx_speed());
        }
    }
    if (m_state == PEER_STATE_REQUEST_READY && m_requested_blocks.size() <= PEER_MAX_REQUEST_NUMBER && !m_blocks2request.empty())
    {
        std::set<BLOCK_ID>::iterator iter = m_blocks2request.begin();
        PIECE_INDEX piece;
        BLOCK_INDEX block;
        uint32_t length;
        get_piece_block_from_block_id(*iter, piece, block);
        m_torrent->get_block_length_by_index(piece, block, length);
        if (send_request(piece, block, length) == ERR_NO_ERROR)
        {
            m_requested_blocks.insert(*iter);
            m_blocks2request.erase(iter);
        }
    }
    return ERR_NO_ERROR;
}
예제 #3
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;
}