From d034968774ea34bee748b265d363e1145cc2da0b Mon Sep 17 00:00:00 2001 From: Shane Bryldt Date: Tue, 6 Dec 2016 23:37:36 +0000 Subject: [PATCH] FS-9775: Added preliminary support for processing find_nodes query, including calls to compact addresses and node info --- libs/libks/src/dht/ks_dht-int.h | 13 ++++ libs/libks/src/dht/ks_dht.c | 121 +++++++++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 8 deletions(-) diff --git a/libs/libks/src/dht/ks_dht-int.h b/libs/libks/src/dht/ks_dht-int.h index 4f835ed18d..f74d3d9065 100644 --- a/libs/libks/src/dht/ks_dht-int.h +++ b/libs/libks/src/dht/ks_dht-int.h @@ -5,6 +5,19 @@ KS_BEGIN_EXTERN_C +/** + * + */ +KS_DECLARE(ks_status_t) ks_dht2_utility_compact_address(ks_sockaddr_t *address, + uint8_t *buffer, + ks_size_t *buffer_length, + ks_size_t buffer_size); +KS_DECLARE(ks_status_t) ks_dht2_utility_compact_node(ks_dht2_nodeid_raw_t *nodeid, + ks_sockaddr_t *address, + uint8_t *buffer, + ks_size_t *buffer_length, + ks_size_t buffer_size); + /** * */ diff --git a/libs/libks/src/dht/ks_dht.c b/libs/libks/src/dht/ks_dht.c index 746c9e62fa..02327a2421 100644 --- a/libs/libks/src/dht/ks_dht.c +++ b/libs/libks/src/dht/ks_dht.c @@ -180,8 +180,8 @@ KS_DECLARE(ks_status_t) ks_dht2_autoroute(ks_dht2_t *dht, ks_bool_t autoroute, k if (!autoroute) { port = 0; - } else if (port == 0) { - return KS_STATUS_FAIL; + } else if (port <= 0) { + port = KS_DHT_DEFAULT_PORT; } dht->autoroute = autoroute; @@ -331,13 +331,81 @@ KS_DECLARE(void) ks_dht2_pulse(ks_dht2_t *dht, int32_t timeout) /** * */ -KS_DECLARE(ks_status_t) ks_dht2_maketid(ks_dht2_t *dht) +KS_DECLARE(ks_status_t) ks_dht2_utility_compact_address(ks_sockaddr_t *address, + uint8_t *buffer, + ks_size_t *buffer_length, + ks_size_t buffer_size) { - ks_assert(dht); + ks_size_t required = sizeof(uint16_t); + uint16_t port = 0; + + ks_assert(address); + ks_assert(buffer); + ks_assert(buffer_length); + ks_assert(buffer_size); + ks_assert(address->family == AF_INET || address->family == AF_INET6); + if (address->family == AF_INET) { + required += sizeof(uint32_t); + } else { + required += 8 * sizeof(uint16_t); + } + + if (*buffer_length + required > buffer_size) { + ks_log(KS_LOG_DEBUG, "Insufficient space remaining for compacting\n"); + return KS_STATUS_FAIL; + } + + if (address->family == AF_INET) { + uint32_t *paddr = (uint32_t *)&address->v.v4.sin_addr; + uint32_t addr = htonl(*paddr); + port = htons(address->v.v4.sin_port); + + memcpy(buffer + (*buffer_length), (void *)&addr, sizeof(uint32_t)); + *buffer_length += sizeof(uint32_t); + } else { + uint16_t *paddr = (uint16_t *)&address->v.v6.sin6_addr; + port = htons(address->v.v6.sin6_port); + + for (int32_t i = 0; i < 8; ++i) { + uint16_t addr = htons(paddr[i]); + memcpy(buffer + (*buffer_length), (void *)&addr, sizeof(uint16_t)); + *buffer_length += sizeof(uint16_t); + } + } + + memcpy(buffer + (*buffer_length), (void *)&port, sizeof(uint16_t)); + *buffer_length += sizeof(uint16_t); + return KS_STATUS_SUCCESS; } +/** + * + */ +KS_DECLARE(ks_status_t) ks_dht2_utility_compact_node(ks_dht2_nodeid_raw_t *nodeid, + ks_sockaddr_t *address, + uint8_t *buffer, + ks_size_t *buffer_length, + ks_size_t buffer_size) +{ + ks_assert(address); + ks_assert(buffer); + ks_assert(buffer_length); + ks_assert(buffer_size); + ks_assert(address->family == AF_INET || address->family == AF_INET6); + + if (*buffer_length + KS_DHT_NODEID_LENGTH > buffer_size) { + ks_log(KS_LOG_DEBUG, "Insufficient space remaining for compacting\n"); + return KS_STATUS_FAIL; + } + + memcpy(buffer + (*buffer_length), (void *)nodeid, KS_DHT_NODEID_LENGTH); + *buffer_length += KS_DHT_NODEID_LENGTH; + + return ks_dht2_utility_compact_address(address, buffer, buffer_length, buffer_size); +} + /** * */ @@ -904,37 +972,44 @@ KS_DECLARE(ks_status_t) ks_dht2_process_query_findnode(ks_dht2_t *dht, ks_dht2_m { struct bencode *id; struct bencode *target; - //const char *idv; + struct bencode *want; + const char *idv; //const char *targetv; ks_size_t idv_len; ks_size_t targetv_len; + ks_bool_t want4 = KS_FALSE; + ks_bool_t want6 = KS_FALSE; ks_dht2_message_t *response = NULL; struct bencode *r = NULL; + uint8_t buffer[1000]; + ks_size_t buffer_length = 0; ks_status_t ret = KS_STATUS_FAIL; ks_assert(dht); ks_assert(message); ks_assert(message->args); + id = ben_dict_get_by_str(message->args, "id"); if (!id) { ks_log(KS_LOG_DEBUG, "Message args missing required key 'id'\n"); return KS_STATUS_FAIL; } - //idv = ben_str_val(id); + idv = ben_str_val(id); idv_len = ben_str_len(id); if (idv_len != KS_DHT_NODEID_LENGTH) { ks_log(KS_LOG_DEBUG, "Message args 'id' value has an unexpected size of %d\n", idv_len); return KS_STATUS_FAIL; } + target = ben_dict_get_by_str(message->args, "target"); if (!target) { ks_log(KS_LOG_DEBUG, "Message args missing required key 'target'\n"); return KS_STATUS_FAIL; } - + //targetv = ben_str_val(target); targetv_len = ben_str_len(target); if (targetv_len != KS_DHT_NODEID_LENGTH) { @@ -943,9 +1018,37 @@ KS_DECLARE(ks_status_t) ks_dht2_process_query_findnode(ks_dht2_t *dht, ks_dht2_m } + want = ben_dict_get_by_str(message->args, "want"); + if (want) { + size_t want_len = ben_list_len(want); + for (size_t i = 0; i < want_len; ++i) { + struct bencode *iv = ben_list_get(want, i); + if (!ben_cmp_with_str(iv, "n4")) { + want4 = KS_TRUE; + } + if (!ben_cmp_with_str(iv, "n6")) { + want6 = KS_TRUE; + } + } + } + + if (!want4 && !want6) { + want4 = message->raddr.family == AF_INET; + want6 = message->raddr.family == AF_INET6; + } + + // @todo add/touch bucket entry for remote node + ks_log(KS_LOG_DEBUG, "Message query find_node is valid\n"); - + // @todo get closest nodes to target from route table + + // @todo compact into buffer + if (ks_dht2_utility_compact_node((ks_dht2_nodeid_raw_t *)idv, &message->raddr, buffer, &buffer_length, sizeof(buffer)) != KS_STATUS_SUCCESS) { + return KS_STATUS_FAIL; + } + + if (ks_dht2_message_alloc(&response, dht->pool) != KS_STATUS_SUCCESS) { goto done; } @@ -959,6 +1062,8 @@ KS_DECLARE(ks_status_t) ks_dht2_process_query_findnode(ks_dht2_t *dht, ks_dht2_m } ben_dict_set(r, ben_blob("id", 2), ben_blob(dht->nodeid.id, KS_DHT_NODEID_LENGTH)); + // @todo populate nodes/nodes6 + ben_dict_set(r, ben_blob("nodes", 5), ben_blob(buffer, buffer_length)); ks_log(KS_LOG_DEBUG, "Sending message response find_node\n"); ks_q_push(dht->send_q, (void *)response);