diff --git a/AUTHORS b/AUTHORS index d30782a..8ec125e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,3 @@ Pål-Erik Martinsen Joe Hildeabrand +Peng Fan \ No newline at end of file diff --git a/include/tube.h b/include/tube.h index 562b184..be87fa3 100644 --- a/include/tube.h +++ b/include/tube.h @@ -36,6 +36,13 @@ typedef struct _tube_manager tube_manager; typedef struct _tube tube; +//id and remote peer addr used to distinguish tubes +typedef struct _tuple +{ + uint64_t id; + struct sockaddr peer; +} tuple; + typedef ssize_t (*tube_sendmsg_func)(int socket, const struct msghdr *message, int flags); @@ -102,3 +109,6 @@ LS_API void tube_get_id(tube *t, spud_tube_id *id); LS_API void tube_set_socket_functions(tube_sendmsg_func send, tube_recvmsg_func recv); + +unsigned int tube_hash_tuple(const void *t); +int tube_compare_tuple(const void *key1, const void *key2); diff --git a/src/tube.c b/src/tube.c index ffaeacf..3100736 100644 --- a/src/tube.c +++ b/src/tube.c @@ -281,7 +281,7 @@ LS_API void tube_get_id(tube *t, spud_tube_id *id) { spud_copy_id(&t->id, id); } - +/* static unsigned int hash_id(const void *id) { // treat the 8 bytes of tube ID like a long long. uint64_t key = *(uint64_t *)id; @@ -295,8 +295,25 @@ static unsigned int hash_id(const void *id) { key = key + (key << 6); key = key ^ (key >> 22); return (unsigned int) key; -} +}*/ +unsigned int tube_hash_tuple(const void *t) { + // currently only id and remote sockaddr are taken into consideration + const tuple *tup = t; + const struct sockaddr_in6 * p_in6 = (const struct sockaddr_in6 *) &tup->peer; + uint64_t key = (uint64_t)tup->id + (uint64_t)(*(uint64_t *)p_in6); + + // from + // https://gist.github.com/badboy/6267743#64-bit-to-32-bit-hash-functions + key = (~key) + (key << 18); + key = key ^ (key >> 31); + key = key * 21; + key = key ^ (key >> 11); + key = key + (key << 6); + key = key ^ (key >> 22); + return (unsigned int) key; +} +/* static int compare_id(const void *key1, const void *key2) { int ret = 0; uint64_t k1 = *(uint64_t *)key1; @@ -307,6 +324,20 @@ static int compare_id(const void *key1, const void *key2) { ret = (k1==k2) ? 0 : 1; } return ret; +}*/ + +int tube_compare_tuple(const void *key1, const void *key2) { + //compares two tuple key1 and key2, returns 0 if they are the same and 1 if not. + tuple k1 = *(tuple *)key1; + tuple k2 = *(tuple *)key2; + + if (k1.id == k2.id) { + if (k1.peer.sa_family == k2.peer.sa_family && strcmp(k1.peer.sa_data, k2.peer.sa_data) == 0) { + return 0; + } + } + + return 1; } LS_API bool tube_manager_create(int buckets, @@ -327,7 +358,7 @@ LS_API bool tube_manager_create(int buckets, if (buckets <= 0) { buckets = DEFAULT_HASH_SIZE; } - if (!ls_htable_create(buckets, hash_id, compare_id, &ret->tubes, err)) { + if (!ls_htable_create(buckets, tube_hash_tuple, tube_compare_tuple, &ret->tubes, err)) { goto cleanup; } diff --git a/test/tube_test.c b/test/tube_test.c index 7094482..511b156 100644 --- a/test/tube_test.c +++ b/test/tube_test.c @@ -19,6 +19,22 @@ uint8_t spud[] = { 0xd8, 0x00, 0x00, 0xd8, 0x41, 0x61 }; bool first = true; +//manmade different ID/peer tuples used to test tubemanager hash function +tuple t1 = { + 0x01020304FAFBFCFD, + { + AF_INET, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D} + } + }; +tuple t2 = { + 0x01020304FAFBFCFD, + { + AF_INET, + {0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D} + } + }; + static ssize_t _mock_sendmsg(int socket, const struct msghdr *hdr, int flags) @@ -276,6 +292,16 @@ START_TEST (tube_manager_loop_test) } END_TEST + +START_TEST (tube_manager_hash_test) +{ + unsigned int key1 = tube_hash_tuple(&t1); + unsigned int key2 = tube_hash_tuple(&t2); + ck_assert_int_ne(key1-key2, 0); + ck_assert_int_ne(tube_compare_tuple(&t1, &t2), 0); +} +END_TEST + Suite * tube_suite (void) { Suite *s = suite_create ("tube"); @@ -291,6 +317,8 @@ Suite * tube_suite (void) tcase_add_test (tc_tube, tube_data_test); tcase_add_test (tc_tube, tube_close_test); tcase_add_test (tc_tube, tube_manager_loop_test); + tcase_add_test (tc_tube, tube_manager_hash_test); + suite_add_tcase (s, tc_tube); }