{"id":18578664,"url":"https://github.com/jech/dht","last_synced_at":"2025-04-12T23:32:56.154Z","repository":{"id":46173241,"uuid":"2173593","full_name":"jech/dht","owner":"jech","description":"BitTorrent DHT library","archived":false,"fork":false,"pushed_at":"2023-03-18T13:46:04.000Z","size":232,"stargazers_count":699,"open_issues_count":5,"forks_count":169,"subscribers_count":63,"default_branch":"master","last_synced_at":"2025-04-04T02:51:10.955Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.irif.fr/~jch/software/bittorrent/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jech.png","metadata":{"files":{"readme":"README","changelog":"CHANGES","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2011-08-08T14:03:55.000Z","updated_at":"2025-03-29T22:03:47.000Z","dependencies_parsed_at":"2024-01-31T09:02:08.497Z","dependency_job_id":"fabb6e36-98bd-4637-be53-3d04498f0bd6","html_url":"https://github.com/jech/dht","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jech%2Fdht","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jech%2Fdht/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jech%2Fdht/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jech%2Fdht/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jech","download_url":"https://codeload.github.com/jech/dht/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248647257,"owners_count":21139081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T23:36:43.626Z","updated_at":"2025-04-12T23:32:56.115Z","avatar_url":"https://github.com/jech.png","language":"C","readme":"The files dht.c and dht.h implement the variant of the Kademlia Distributed\nHash Table (DHT) used in the Bittorrent network (``mainline'' variant).\n\nThe file dht-example.c is a stand-alone program that participates in the\nDHT.  Another example is a patch against Transmission, which you might or\nmight not be able to find somewhere.\n\nThe code is designed to work well in both event-driven and threaded code.\nThe caller, which is either an event-loop or a dedicated thread, must\nperiodically call the function dht_periodic.  In addition, it must call\ndht_periodic whenever any data has arrived from the network.\n\nAll functions return -1 in case of failure, in which case errno is set, or\na positive value in case of success.\n\nInitialisation\n**************\n\n* dht_init\n\nThis must be called before using the library.  You pass it an integer\nidentifying a bound IPv4 datagram socket in non-blocking mode, an integer\nidentifying a bound IPv6 datagram socket in non-blocking mode, and your\nnode id, a 20-octet array that should be globally unique.\n\nThe integers that identify the two sockets should usually be file\ndescriptors; however, as the library does not directly perform any socket-\nor file-related operations on them, they can be arbitrary integers, for\nexample indices in a table of structures that represent sockets in your\ncode.\n\nIf you're on a multi-homed host, you should bind your sockets to one of\nyour addresses.  This is especially relevant for IPv6.\n\nNode ids must be well distributed, so you cannot just use your Bittorrent\nid; you should either generate a truly random value (using plenty of\nentropy), or at least take the SHA-1 of something.  However, it is a good\nidea to keep the id stable, so you may want to store it in stable storage\nat client shutdown.\n\n \n* dht_uninit\n\nThis may be called at the end of the session.\n\nBootstrapping\n*************\n\nThe DHT needs to be taught a small number of contacts to begin functioning.\nYou can hard-wire a small number of stable nodes in your application, but\nthis obviously fails to scale.  You may save the list of known good nodes\nat shutdown, and restore it at restart.  You may also grab nodes from\ntorrent files (the nodes field), and you may exchange contacts with other\nBittorrent peers using the PORT extension.\n\n* dht_ping_node\n\nThis is the main bootstrapping primitive.  You pass it an address at which\nyou believe that a DHT node may be living, and a query will be sent.  If\na node replies, and if there is space in the routing table, it will be\ninserted.\n\n* dht_insert_node\n\nThis is a softer bootstrapping method, which doesn't actually send\na query -- it only stores the node in the routing table for later use.\n\nNote that dht_insert_node requires that you supply a node id.  If the id\nturns out to be wrong, the DHT will eventually recover; still, inserting\nmassive amounts of incorrect information into your routing table is not\na good idea.\n\nAn additionaly difficulty with dht_insert_node is that a Kademlia routing\ntable cannot absorb nodes faster than a certain rate.  A freshly initialised\nrouting table is able to absorb 128 nodes of each address family without\ndropping any.  The tolerable rate after that is difficult to estimate: it is\nprobably on the order of one node every few seconds per node already in\nthe table divided by 8, for some suitable value of 8.\n\nDoing some work\n***************\n\n* dht_periodic\n\nThis function should be called by your main loop periodically, and also\nwhenever data is available on the socket.  The time after which\ndht_periodic should be called if no data is available is returned in the\nparameter tosleep.  (You do not need to be particularly accurate; actually,\nit is a good idea to be late by a random value.)\n\nThe parameters buf, buflen, from and fromlen optionally carry a received\nmessage.  If buflen is 0, then no message was received.\n\nDht_periodic also takes a callback, which will be called whenever something\ninteresting happens (see below).\n\n* dht_search\n\nThis schedules a search for information about the info-hash specified in\nid; it returns 1 if this is a new search, and 0 if it merely reset the\ntimeouts for a search in progress.  If port is not 0, it specifies the TCP\nport on which the current peer is listening; in that case, when the search\nis complete it will be announced to the network.  The port is in host\norder, beware if you got it from a struct sockaddr_in.\n\nIn either case, data is passed to the callback function as soon as it is\navailable, possibly in multiple pieces.  The callback function will also\nbe called when the search is complete.\n\nUp to DHT_MAX_SEARCHES (1024) searches can be in progress at a given time;\nany more, and dht_search will return -1.  If you specify a new search for\nthe same info hash as a search still in progress, the previous search is\ncombined with the new one -- you will only receive a completion indication\nonce.\n\nInformation queries\n*******************\n\n* dht_nodes\n\nThis returns the number of known good, dubious and cached nodes in our\nrouting table.  This can be used to decide whether it's reasonable to start\na search; a search is likely to be successful as long as we have a few good\nnodes; however, in order to avoid overloading your bootstrap nodes, you may\nwant to wait until good is at least 4 and good + doubtful is at least 30 or\nso.\n\nIt also includes the number of nodes that recently sent us an unsolicited\nrequest; this can be used to determine if the UDP port used for the DHT is\nfirewalled.\n\nIf you want to display a single figure to the user, you should display\ngood + doubtful, which is the total number of nodes in your routing table.\nSome clients try to estimate the total number of nodes, but this doesn't\nmake much sense -- since the result is exponential in the number of nodes\nin the routing table, small variations in the latter cause huge jumps in\nthe former.\n\n* dht_get_nodes\n\nThis retrieves the list of known good nodes, starting with the nodes in our\nown bucket.  It is a good idea to save the list of known good nodes at\nshutdown, and ping them at startup.\n\n* dht_dump_tables\n* dht_debug\n\nThese are debugging aids.\n\nFunctions provided by you\n*************************\n\n* The callback function\n\nThe callback function is called with 5 arguments.  Closure is simply the\nvalue that you passed to dht_periodic.  Event is one of DHT_EVENT_VALUES or\nDHT_EVENT_VALUES6, which indicates that we have new values, or\nDHT_EVENT_SEARCH_DONE or DHT_EVENT_SEARCH_DONE6, which indicates that\na search has completed.  In either case, info_hash is set to the info-hash\nof the search.\n\nIn the case of DHT_EVENT_VALUES, data is a list of nodes in ``compact''\nformat -- 6 or 18 bytes per node.  Its length in bytes is in data_len.\n\n* dht_sendto\n\nThis will be called whenever the library needs to send a datagram.  If the\nintegers passed to dht_init are file descriptors, this can simply be an\nalias for the sendto system call.\n\n* dht_blacklisted\n\nThis is a function that takes an IP address and returns true if this\naddress should be silently ignored.  Do not use this feature unless you\nreally must -- Kademlia supposes transitive reachability.\n\n* dht_hash\n\nThis should compute a reasonably strong cryptographic hash of the passed\nvalues.  SHA-1 should be good enough.\n\n* dht_random_bytes\n\nThis should fill the supplied buffer with cryptographically strong random\nbytes.  It's called every 30 minutes on average, so it doesn't need to be\nfast.\n\nFinal notes\n***********\n\n* NAT\n\nNothing works well across NATs, but Kademlia is somewhat less impacted than\nmany other protocols.  The implementation takes care to distinguish between\nunidirectional and bidirectional reachability, and NATed nodes will\neventually fall out from other nodes' routing tables.\n\nWhile there is no periodic pinging in this implementation, maintaining\na full routing table requires slightly more than one packet exchange per\nminute, even in a completely idle network; this should be sufficient to\nmake most full cone NATs happy.\n\n\n                                        Juliusz Chroboczek\n                                        \u003cjch@pps.jussieu.fr\u003e\n","funding_links":[],"categories":["BitTorrent","Uncategorized"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjech%2Fdht","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjech%2Fdht","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjech%2Fdht/lists"}