void TestHashmaplinked_IterateHandlesCollisions( CuTest * tc ) { hashmap_t *hm, *hm2; hashmap_iterator_t iter; void *key; hm = hashmap_new(__uint_hash, __uint_compare, 4); hm2 = hashmap_new(__uint_hash, __uint_compare, 4); hashmap_put(hm, (void *) 1, (void *) 92); hashmap_put(hm, (void *) 5, (void *) 91); hashmap_put(hm, (void *) 9, (void *) 90); hashmap_put(hm2, (void *) 1, (void *) 92); hashmap_put(hm2, (void *) 5, (void *) 91); hashmap_put(hm2, (void *) 9, (void *) 90); hashmap_iterator(hm, &iter); /* remove every key we iterate on */ while ((key = hashmap_iterator_next(hm, &iter))) { CuAssertTrue(tc, NULL != hashmap_remove(hm2, key)); } /* check if the hashmap is empty */ CuAssertTrue(tc, 0 == hashmap_count(hm2)); hashmap_freeall(hm); }
void __print_client_contents() { hashmap_iterator_t iter; for ( hashmap_iterator(__clients, &iter); hashmap_iterator_has_next(__clients, &iter); ) { void* bt, *cfg; client_t* cli; hashmap_iterator_t iter_connects; cli = hashmap_iterator_next_value(__clients, &iter); /* loop throught each connection for this peer */ for ( hashmap_iterator(cli->connections, &iter_connects); hashmap_iterator_has_next(cli->connections, &iter_connects); ) { client_connection_t* cn; int jj; cn = hashmap_iterator_next_value(cli->connections, &iter_connects); #if 0 /* debugging */ { void* data; printf("cli: %d nethandle: %d inbox: %dB ", cli->nethandle, cn->nethandle, bipbuf_get_spaceused(cn->inbox)); data = bipbuf_peek(cn->inbox); for (jj=0; jj<bipbuf_get_spaceused(cn->inbox); jj++) { printf("%c", ((char*)data)[jj]); } } printf("\n"); #endif } } }
static void __peer_release(peer_t* p) { hashmap_iterator_t iter; piece_t* pce; for (hashmap_iterator(p->have_pieces, &iter); (pce = hashmap_iterator_next(p->have_pieces, &iter));) { hashmap_remove(p->have_pieces, p); } }
void TestHashmaplinked_DoesNotHaveNextForEmptyIterator( CuTest * tc ) { hashmap_t *hm; hashmap_iterator_t iter; hm = hashmap_new(__uint_hash, __uint_compare, 11); hashmap_iterator(hm, &iter); CuAssertTrue(tc, 0 == hashmap_iterator_has_next(hm, &iter)); hashmap_freeall(hm); }
int bt_rarestfirst_selector_poll_best_piece( void *r, const void *peer ) { rarestfirst_t *rf = r; heap_t *hp; peer_t *pr; void *p; int piece_idx; hashmap_iterator_t iter; piece_t *pce; if (!(pr = hashmap_get(rf->peers, peer))) { return -1; } /* if we have no pieces, fail */ if (0 == hashmap_count(pr->have_pieces)) { return -1; } hp = heap_new(__cmp_piece, rf); /* add to priority queue */ for (hashmap_iterator(rf->pieces, &iter); (p = hashmap_iterator_next(rf->pieces, &iter));) { /* only add if peer has it */ if (hashmap_get(pr->have_pieces, p)) { pce = hashmap_get(rf->pieces, p); heap_offer(hp, pce); } } /* queue best from priority queue */ if ((pce = heap_poll(hp))) { piece_idx = pce->idx; hashmap_remove(rf->pieces, (void *) (long) pce->idx); hashmap_put(rf->pieces_polled, (void *) (long) pce->idx, pce); } else { piece_idx = -1; } heap_free(hp); return piece_idx; }
/** * poll info peer has information * */ int network_poll(void* caller, void **udata, const int msec_timeout, int (*func_process) (void *caller, void* nethandle, const char* buf, unsigned int len), void (*func_process_connection) (void *, void* nethandle, char *ip, int port) ) { client_t* me = *udata; hashmap_iterator_t iter; /* loop throught each connection for this peer */ for ( hashmap_iterator(me->connections, &iter); hashmap_iterator_has_next(me->connections, &iter); ) { client_connection_t* cn; cn = hashmap_iterator_next_value(me->connections, &iter); /* we need to process a connection request created by the peer */ if (0 == cn->connect_status) { char ip[32]; sprintf(ip, "%p", cn->nethandle); #if 0 /* debugging */ printf("processing connection me:%d them:%d\n", me->nethandle, cn->nethandle); #endif func_process_connection(me->bt, cn->nethandle, ip, 4000); cn->connect_status = CS_CONNECTED; } else if (!bipbuf_is_empty(cn->inbox)) { int len = bipbuf_get_spaceused(cn->inbox); if (0 < len) func_process(me->bt, (char*)cn->nethandle, (char*)bipbuf_poll(cn->inbox, len), len); } } return 1; }
void TestHashmaplinked_IterateAndRemoveDoesntBreakIteration( CuTest * tc ) { hashmap_t *hm; hashmap_t *hm2; hashmap_iterator_t iter; void *key; hm = hashmap_new(__uint_hash, __uint_compare, 11); hm2 = hashmap_new(__uint_hash, __uint_compare, 11); hashmap_put(hm, (void *) 50, (void *) 92); hashmap_put(hm, (void *) 49, (void *) 91); hashmap_put(hm, (void *) 48, (void *) 90); hashmap_put(hm, (void *) 47, (void *) 89); hashmap_put(hm, (void *) 46, (void *) 88); hashmap_put(hm, (void *) 45, (void *) 87); /* the following 3 collide: */ hashmap_put(hm, (void *) 1, (void *) 92); hashmap_put(hm, (void *) 5, (void *) 91); hashmap_put(hm, (void *) 9, (void *) 90); hashmap_put(hm2, (void *) 50, (void *) 92); hashmap_put(hm2, (void *) 49, (void *) 91); hashmap_put(hm2, (void *) 48, (void *) 90); hashmap_put(hm2, (void *) 47, (void *) 89); hashmap_put(hm2, (void *) 46, (void *) 88); hashmap_put(hm2, (void *) 45, (void *) 87); /* the following 3 collide: */ hashmap_put(hm2, (void *) 1, (void *) 92); hashmap_put(hm2, (void *) 5, (void *) 91); hashmap_put(hm2, (void *) 9, (void *) 90); hashmap_iterator(hm, &iter); /* remove every key we iterate on */ while ((key = hashmap_iterator_next(hm, &iter))) { CuAssertTrue(tc, NULL != hashmap_remove(hm2, key)); hashmap_remove(hm,key); } /* check if the hashmap is empty */ CuAssertTrue(tc, 0 == hashmap_count(hm2)); hashmap_freeall(hm); hashmap_freeall(hm2); }
/** * @return peer that corresponds to conn_ctx, otherwise NULL */ void *bt_peermanager_conn_ctx_to_peer(void * pm, void* conn_ctx) { bt_peermanager_t *me = pm; hashmap_iterator_t iter; /* find peerconn that has this conn_ctx */ for (hashmap_iterator(me->peers,&iter); hashmap_iterator_has_next(me->peers,&iter);) { bt_peer_t* peer; peer = hashmap_iterator_next(me->peers,&iter); if (peer->conn_ctx == conn_ctx) return peer; } return NULL; }
void* bt_peermanager_get_peer_from_pc(void* pm, const void* pc) { bt_peermanager_t *me = pm; hashmap_iterator_t iter; /* find peerconn that has this ip and port */ for (hashmap_iterator(me->peers,&iter); hashmap_iterator_has_next(me->peers,&iter);) { bt_peer_t* p = hashmap_iterator_next(me->peers,&iter); if (p->pc == pc) { return p; } } return NULL; }
void bt_peermanager_forall( void* pm, void* caller, void* udata, void (*run)(void* caller, void* peer, void* udata)) { bt_peermanager_t *me = pm; hashmap_iterator_t iter; for (hashmap_iterator(me->peers,&iter); hashmap_iterator_has_next(me->peers,&iter);) { bt_peer_t* peer; peer = hashmap_iterator_next(me->peers,&iter); run(caller,peer,udata); } }
/** * @return 1 if the peer is within the manager */ int bt_peermanager_contains(void *pm, const char *ip, const int port) { bt_peermanager_t *me = pm; hashmap_iterator_t iter; /* find peerconn that has this ip and port */ for (hashmap_iterator(me->peers,&iter); hashmap_iterator_has_next(me->peers,&iter);) { bt_peer_t* peer; peer = hashmap_iterator_next(me->peers,&iter); if (!strcmp(peer->ip, ip) && peer->port == port) { return 1; } } return 0; }
void bt_rarestfirst_selector_free( void *r ) { rarestfirst_t *rf = r; hashmap_iterator_t iter; peer_t* p; for (hashmap_iterator(rf->pieces, &iter); (p = hashmap_iterator_next(rf->pieces, &iter));) { hashmap_remove(rf->pieces, p); free(p); } hashmap_free(rf->peers); hashmap_free(rf->pieces); hashmap_free(rf->pieces_polled); free(rf); }
void TestBT_Peer_share_20_pieces(CuTest * tc) { int num_pieces; int ii; client_t* a, *b; hashmap_iterator_t iter; void* mt; char *addr; num_pieces = 50; clients_setup(); mt = mocktorrent_new(num_pieces, 5); a = mock_client_setup(5); b = mock_client_setup(5); for ( hashmap_iterator(clients_get(), &iter); hashmap_iterator_has_next(clients_get(), &iter); ) { void* bt, *cfg; client_t* cli; cli = hashmap_iterator_next_value(clients_get(), &iter); bt = cli->bt; /* default configuration for clients */ cfg = bt_dm_get_config(bt); config_set_va(cfg, "npieces", "%d", num_pieces); config_set(cfg, "piece_length", "5"); config_set(cfg, "infohash", "00000000000000000000"); /* add files/pieces */ bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt), num_pieces * 5); for (ii = 0; ii < num_pieces; ii++) { char hash[21]; void* pd; pd = bt_dm_get_piecedb(bt); mocktorrent_get_piece_sha1(mt, hash, ii); bt_piecedb_add_with_hash_and_size(pd, hash, 5); } } /* B will initiate the connection */ asprintf(&addr, "%p", b); client_add_peer(a, NULL, 0, addr, strlen(addr), 0); __add_random_piece_subset_of_mocktorrent( bt_dm_get_piecedb(a->bt), mt, num_pieces); __add_piece_intersection_of_mocktorrent( bt_dm_get_piecedb(b->bt), bt_dm_get_piecedb(a->bt), mt, num_pieces); bt_dm_check_pieces(a->bt); bt_dm_check_pieces(b->bt); for (ii = 0; ii < 2000; ii++) { #if 0 /* debugging */ printf("\nStep %d:\n", ii + 1); #endif bt_dm_periodic(a->bt, NULL); bt_dm_periodic(b->bt, NULL); network_poll(a->bt, (void*)&a, 0, bt_dm_dispatch_from_buffer, mock_on_connect); network_poll(b->bt, (void*)&b, 0, bt_dm_dispatch_from_buffer, mock_on_connect); } bt_dm_periodic(a->bt, NULL); bt_dm_periodic(b->bt, NULL); // bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(a->bt)); // bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(b->bt)); CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(a->bt))); CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(b->bt))); }
void TestBT_Peer_shares_one_piece( CuTest * tc ) { int ii; client_t* a, *b; hashmap_iterator_t iter; void* mt; char *addr; clients_setup(); mt = mocktorrent_new(1, 5); a = mock_client_setup(5); b = mock_client_setup(5); for ( hashmap_iterator(clients_get(), &iter); hashmap_iterator_has_next(clients_get(), &iter); ) { char hash[21]; client_t* cli = hashmap_iterator_next_value(clients_get(), &iter); void* bt = cli->bt; void *cfg = bt_dm_get_config(bt); /* default configuration for clients */ config_set(cfg, "npieces", "1"); config_set_va(cfg, "piece_length", "%d", 5); config_set(cfg, "infohash", "00000000000000000000"); /* add files/pieces */ //bt_piecedb_add_file(bt_dm_get_piecedb(bt),"test.txt",8,5); bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt), 5); bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt), mocktorrent_get_piece_sha1(mt, hash, 0), 5); } /* write blocks to client A */ { void* data; bt_block_t blk; data = mocktorrent_get_data(mt, 0); blk.piece_idx = 0; blk.offset = 0; blk.len = 5; bt_diskmem_write_block( bt_piecedb_get_diskstorage(bt_dm_get_piecedb(a->bt)), NULL, &blk, data); } bt_dm_check_pieces(a->bt); bt_dm_check_pieces(b->bt); /* let validation jobs run */ bt_dm_periodic(a->bt, NULL); CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(a->bt))); /* connect clients */ asprintf(&addr, "%p", a); client_add_peer(b, NULL, 0, addr, strlen(addr), 0); for (ii = 0; ii < 10; ii++) { #if 0 /* debugging */ printf("\nStep %d:\n", ii + 1); #endif bt_dm_periodic(a->bt, NULL); bt_dm_periodic(b->bt, NULL); network_poll(a->bt, (void*)&a, 0, bt_dm_dispatch_from_buffer, mock_on_connect); network_poll(b->bt, (void*)&b, 0, bt_dm_dispatch_from_buffer, mock_on_connect); // __print_client_contents(); } /* let validation jobs run */ bt_dm_periodic(a->bt, NULL); bt_dm_periodic(b->bt, NULL); CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(b->bt))); }
/** a have message has to be sent by client B, for client A and C to finish */ void TestBT_Peer_three_share_all_pieces_between_each_other(CuTest * tc) { int ii; client_t* a, *b, *c; hashmap_iterator_t iter; void* mt; char *addr; clients_setup(); mt = mocktorrent_new(3,5); a = mock_client_setup(5); b = mock_client_setup(5); c = mock_client_setup(5); for ( hashmap_iterator(clients_get(), &iter); hashmap_iterator_has_next(clients_get(), &iter); ) { char hash[21]; void* bt, *cfg; client_t* cli; cli = hashmap_iterator_next_value(clients_get(), &iter); bt = cli->bt; cfg = bt_dm_get_config(bt); /* default configuration for clients */ config_set(cfg, "npieces", "3"); config_set(cfg, "piece_length", "5"); config_set(cfg, "infohash", "00000000000000000000"); /* add files/pieces */ bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt),20); bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt), mocktorrent_get_piece_sha1(mt,hash,0), 5); bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt), mocktorrent_get_piece_sha1(mt,hash,1), 5); bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt), mocktorrent_get_piece_sha1(mt,hash,2), 5); } /* write blocks to client A & B */ { void* data; bt_block_t blk; blk.piece_idx = 0; blk.offset = 0; blk.len = 5; data = mocktorrent_get_data(mt,0); bt_diskmem_write_block( bt_piecedb_get_diskstorage(bt_dm_get_piecedb(a->bt)), NULL, &blk, data); blk.piece_idx = 1; data = mocktorrent_get_data(mt,1); bt_diskmem_write_block( bt_piecedb_get_diskstorage(bt_dm_get_piecedb(b->bt)), NULL, &blk, data); blk.piece_idx = 2; data = mocktorrent_get_data(mt,2); bt_diskmem_write_block( bt_piecedb_get_diskstorage(bt_dm_get_piecedb(c->bt)), NULL, &blk, data); } bt_dm_check_pieces(a->bt); bt_dm_check_pieces(b->bt); bt_dm_check_pieces(c->bt); /* A connects to B */ asprintf(&addr,"%p", b); client_add_peer(a,NULL,0,addr,strlen(addr),0); /* B connects to C */ asprintf(&addr,"%p", c); client_add_peer(b,NULL,0,addr,strlen(addr),0); for (ii=0; ii<10; ii++) { #if 0 /* debugging */ printf("\nStep %d:\n", ii+1); #endif bt_dm_periodic(a->bt, NULL); bt_dm_periodic(b->bt, NULL); bt_dm_periodic(c->bt, NULL); network_poll(a->bt, (void*)&a, 0, bt_dm_dispatch_from_buffer, mock_on_connect); network_poll(b->bt, (void*)&b, 0, bt_dm_dispatch_from_buffer, mock_on_connect); network_poll(c->bt, (void*)&c, 0, bt_dm_dispatch_from_buffer, mock_on_connect); // __print_client_contents(); } // bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(a->bt)); // bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(b->bt)); // bt_piecedb_print_pieces_downloaded(bt_dm_get_piecedb(c->bt)); /* empty jobs */ bt_dm_periodic(a->bt, NULL); bt_dm_periodic(b->bt, NULL); bt_dm_periodic(c->bt, NULL); CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(a->bt))); CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(b->bt))); CuAssertTrue(tc, 1 == bt_piecedb_all_pieces_are_complete(bt_dm_get_piecedb(c->bt))); }
/** * Does the bt_dm_check_pieces() confirm if a piece is complete? */ void TestBT_Peer_shares_all_pieces_between_each_other( CuTest * tc ) { client_t* a, *b; hashmap_iterator_t iter; void* mt; clients_setup(); mt = mocktorrent_new(2, 5); a = mock_client_setup(5); b = mock_client_setup(5); for ( hashmap_iterator(clients_get(), &iter); hashmap_iterator_has_next(clients_get(), &iter); ) { char hash[21]; void* bt, *cfg; client_t* cli; cli = hashmap_iterator_next_value(clients_get(), &iter); bt = cli->bt; cfg = bt_dm_get_config(bt); /* default configuration for clients */ config_set(cfg, "npieces", "2"); config_set(cfg, "piece_length", "5"); config_set(cfg, "infohash", "00000000000000000000"); /* add files/pieces */ bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt), 5); bt_piecedb_increase_piece_space(bt_dm_get_piecedb(bt), 12); bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt), mocktorrent_get_piece_sha1(mt, hash, 0), 5); bt_piecedb_add_with_hash_and_size(bt_dm_get_piecedb(bt), mocktorrent_get_piece_sha1(mt, hash, 1), 5); } /* write blocks to client A & B */ { void* data; bt_block_t blk; blk.piece_idx = 0; blk.offset = 0; blk.len = 5; data = mocktorrent_get_data(mt, 0); bt_diskmem_write_block( bt_piecedb_get_diskstorage(bt_dm_get_piecedb(b->bt)), NULL, &blk, data); blk.piece_idx = 1; data = mocktorrent_get_data(mt, 1); bt_diskmem_write_block( bt_piecedb_get_diskstorage(bt_dm_get_piecedb(a->bt)), NULL, &blk, data); } bt_dm_check_pieces(a->bt); bt_dm_check_pieces(b->bt); bt_dm_periodic(a->bt, NULL); bt_dm_periodic(b->bt, NULL); CuAssertTrue(tc, bt_dm_piece_is_complete(a->bt, 1)); CuAssertTrue(tc, bt_dm_piece_is_complete(b->bt, 0)); }