summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dht.c40
1 files changed, 23 insertions, 17 deletions
diff --git a/src/dht.c b/src/dht.c
index b1b1fa4..b4b3cbf 100644
--- a/src/dht.c
+++ b/src/dht.c
@@ -754,6 +754,8 @@ int bucket_good (const struct dht * d, const struct bucket * b) {
/**
* when we are sure that a node exists on a specific ip:port and we know it's port, but we are unsure if the node is already in the routing table, we call this function, which makes a query to this node if it's a candidate for filling the routing table. this doesn't yet add it to the routing table, because we are unsure if it's a good node / can respond to queries. replied() is called if a node replied to our query.
*
+ * see NOTE02
+ *
* @param d [in] library handle
* @param a [in] pointer to sockaddr of the node
* @param id [in] id of the node, 20 bytes is read from this address
@@ -1110,31 +1112,35 @@ void handle (struct dht * d, char * pkt, int len, struct sockaddr_in6 addr) {
break;
}
break;
- case 'R':
+ case 'R': // we only ever query and expect responses to get_peers and find_node, so it's egal
case 'r':
struct bencoding * rid = bpath(b, "r/id");
if (rid && rid->type & string && rid->valuelen == 20)
replied(d, rid->value, &addr); // since here I'm only really interested about nodes and values
struct bencoding * t = bpath(b, "t");
- if (!(t && t->type & string && t->valuelen == 20))
- break;
- if (!(torrent = find_torrent(d, t->value)))
- break;
- if (!torrent->type) // yeet, l33t haxx0r tried to announce a torrent by sending a crafted response to a ficticios get_peers query
- break; // this could enable the DHT node to be used as a DDoS spreader. uninterested torrents can't be updated this way
- bforeach (bpath(b, "r/values"), p) {
- if (!(p->type & string) || (p->valuelen != 6 && p->valuelen != 18))
- break;
- struct peer * peer = calloc(1, sizeof *peer);
- memcpy(peer->addr.sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\xFF\xFF\xFF\xFF", 12);
- peer->addr.sin6_port = *((uint16_t *) (peer->value + peer->valuelen-2));
- memcpy(peer->addr.sin6_addr+(p->valuelen == 6 ? 8 : 0), p->valuelen == 6 ? 4 : 16);
- add_peer(d, torrent, peer);
- }
+ struct torrent * torrent = NULL;
+ if ((t && t->type & string && t->valuelen == 20) && (torrent = find_torrent(d, t->value)) && torrent->type)
+ bforeach (bpath(b, "r/values"), p) {
+ if (!(p->type & string) || (p->valuelen != 6 && p->valuelen != 18))
+ break;
+ struct peer * peer = calloc(1, sizeof *peer);
+ memcpy(peer->addr.sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\xFF\xFF\xFF\xFF", 12);
+ peer->addr.sin6_port = *((uint16_t *) (p->value + p->valuelen-2));
+ memcpy(peer->addr.sin6_addr+(p->valuelen == 6 ? 8 : 0), p->value, p->valuelen == 6 ? 4 : 16);
+ add_peer(d, torrent, peer);
+ }
bforeach (bpath(b, "r/nodes" /* haha subreddit */), n) {
if (!(n->type & string) || (n->valuelen != 4+2+20 && n->valuelen != 16+2+20))
break;
- // TODO nodes and nodes6
+ struct node * node = node_init();
+ memcpy(node->addr.sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\xFF\xFF\xFF\xFF", 12);
+ node->addr.sin6_port = *((uint16_t *) (n->value + n->valuelen-2));
+ memcpy(node->addr.sin6_addr+(n->valuelen == 4+2+20 ? 8 : 0), n->value + 20, n->valuelen == 4+2+20 ? 4 : 16);
+ memcpy(node->id, n->value, 20);
+ potential_node(d, &node->addr, id); // NOTE02 this is quite important and means that at the beginning, a lot of packets will be sent, since every reply of potential_node will generate K replies. naively this would generate an exponentially increasing number of packets, in increasing powers of 8 (8**n). to prevent an absolute resource hog, this is only done when node would be useful and would contribute to the routing table
+ if (torrent)
+ else
+ node_free(node);
}
case 'E':
case 'e':