Пример #1
0
void handle_message(cjdnsadmin_t *adm, char *buffer, ssize_t len) {
    // TODO: fix memory leak
    struct bencode *b = ben_decode(buffer, len);
    if (!b) {
        fprintf(stderr, "bencode error: %lu\n",len);
        printf("message from cjdns: \"%*s\"\n", (int)len, buffer);
        return;
    }
    // Get IPs
    struct bencode *table = ben_dict_get_by_str(b, "routingTable");
    size_t i, num_items = ben_list_len(table);
    for (i = 0; i < num_items; i++) {
        struct bencode *item = ben_list_get(table, i);
        struct bencode *ip = ben_dict_get_by_str(item, "ip");
        if (ben_is_str(ip)) {
            const char *ip_str = ben_str_val(ip);
            if (adm->on_found_ip) {
                (*adm->on_found_ip)(adm->on_found_ip_obj, ip_str);
            }
        }
    }
    // check if there is more
    struct bencode *more = ben_dict_get_by_str(b, "more");
    int more_int = more && ben_is_int(more) && ben_int_val(more);
    if (more_int == 1) {
        // get the next page of the routing table
        adm->fetch_peers_page++;
        cjdnsadmin_fetch_peers(adm);
    } else {
        // start from the first page next time
        adm->fetch_peers_page = 0;
    }
    ben_free(b);
}
Пример #2
0
/* handle_announcement reads an announcement document to find some peers to download from. 
	Puts em in benPeers, and we then handle the peer scanning or whatever in the main function. */
void handle_announcement(char *ptr, size_t size) {
	struct bencode* anno = ben_decode(ptr,size);

	printf("Torrent has %lld seeds and %lld downloading peers. \n",
				 ((struct bencode_int*)ben_dict_get_by_str(anno,"complete"))->ll,
				 ((struct bencode_int*)ben_dict_get_by_str(anno,"incomplete"))->ll);
		 
	benPeers = (struct bencode_list*)ben_dict_get_by_str(anno,"peers");
}
Пример #3
0
/* handle_announcement reads an announcement document to find some peers to download from.
     start a new tread for each peer.
 */
void handle_announcement(char *ptr, size_t size) {
    struct bencode* anno = ben_decode(ptr,size);

    printf("Torrent has %lld seeds and %lld downloading peers. \n",
                 ((struct bencode_int*)ben_dict_get_by_str(anno,"complete"))->ll,
                 ((struct bencode_int*)ben_dict_get_by_str(anno,"incomplete"))->ll);
         
    struct bencode_list *peers = (struct bencode_list*)ben_dict_get_by_str(anno,"peers");

    // handle the binary case
    if(peers->type == BENCODE_STR) {
        printf("Got binary list of peers\n");
       struct peer_addr *peerlist = (struct peer_addr*)((struct bencode_str*)peers)->s;
        for(int i=0;i<((struct bencode_str*)peers)->len/6;i++) {                
            struct in_addr a;
            a.s_addr = peerlist[i].addr;
            printf("Found peer %s:%d\n",inet_ntoa(a),ntohs(peerlist[i].port));               

            connect_all_peers(&peerlist[i]);
        }            
    }
    // handle the bencoded case
    else {
        for(int i=0;i<peers->n;i++) {
            printf("Got bencoded list of peers\n");
            struct bencode *peer = peers->values[i];
            char *address = ((struct bencode_str*)ben_dict_get_by_str(peer,"ip"))->s;
            unsigned short port = ((struct bencode_int*)ben_dict_get_by_str(peer,"port"))->ll;
            printf("Found peer %s:%d\n",address,port);

            struct peer_addr *peeraddr = malloc(sizeof(struct peer_addr));
            peeraddr->addr=inet_addr(address);
            peeraddr->port=htons(port);
            connect_all_peers(peeraddr);
        }
    }
    
    listen_from_peers();
}
Пример #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;
}