{"_id":"mdht","_rev":"51-519267d43eebc2a118c6c913a66563b4","name":"mdht","description":"Mainline DHT","dist-tags":{"latest":"3.1.3"},"versions":{"2.3.3":{"name":"mdht","version":"2.3.3","main":"mdht.js","description":"Mainline DHT","license":"MIT","repository":{"type":"git","url":"git+https://github.com/metamystical/mdht.git"},"dependencies":{"bencode":"^1.0.0","ed25519-supercop":"^1.0.2"},"scripts":{"start":"node server.js"},"bugs":{"url":"https://github.com/metamystical/mdht/issues"},"homepage":"https://github.com/metamystical/mdht#readme","_id":"mdht@2.3.3","_npmVersion":"5.6.0","_nodeVersion":"9.3.0","_npmUser":{"name":"metamystical","email":"metamystical@protonmail.com"},"dist":{"integrity":"sha512-aGDhgL2UhKGywHU0kOTfu6Y63dkEvpRI/5SH7pGRmMIeNAPSDpd+QrxBORobqn+7V1O5a8zHZKMDzZtKvCil+w==","shasum":"0033c193960b80a3f45e37c1185f3f4b3e8f68e9","tarball":"https://registry.npmjs.org/mdht/-/mdht-2.3.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCuJMb2rIeBFBKLTZQqHl1M4LnYv5MmLdogwQf//+KXBAIhAO8rxyBtO5L6GivIVNk4jYBXSWMdwswfukUhKLxy4tpJ"}]},"maintainers":[{"name":"metamystical","email":"metamystical@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/mdht-2.3.3.tgz_1513428388592_0.716783155919984"},"directories":{}},"3.1.2":{"name":"mdht","version":"3.1.2","main":"mdht.js","description":"Mainline DHT","license":"MIT","repository":{"type":"git","url":"git+https://github.com/metamystical/mdht.git"},"dependencies":{"ed25519-supercop":"2.0.1","polycrc":"1.0.1"},"keywords":["dht","distributed-hash-table","mainline","bittorrent","p2p","BEP5","BEP42","BEP44"],"scripts":{"start":"node server.js"},"gitHead":"fc970ff60948ed2e55a19858eae82528a56ae4c4","bugs":{"url":"https://github.com/metamystical/mdht/issues"},"homepage":"https://github.com/metamystical/mdht#readme","_id":"mdht@3.1.2","_nodeVersion":"15.2.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-uuy6jn0J9XlrpurGajYNqtBa9bWgRzk6T4Z4GY6O4rkUF0tjQn1Qsh3rNED4Lwm68mcoG9UpkABvZHPH6GL80w==","shasum":"161b909d8f96d99e65272e4038e03a015469eca5","tarball":"https://registry.npmjs.org/mdht/-/mdht-3.1.2.tgz","fileCount":14,"unpackedSize":65979,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfvQziCRA9TVsSAnZWagAA9QIP/Rqdn+FPcHubslUi+INl\n7p8/6LeuWmzGvtdAhXSMb0EosYsJJHHI89bizt34rJ7rxyfW/WXkj4B4uq0J\nW6DZjoWtq24c/2Hp1AlIx0G70ifYq8rr3eEe+1vqJ775+kpl0ty/QRFD7dfN\ngW/Y2W6jdpMvuvVLBoqcBRDH3N+++oWe76PHUhN5TXzSnDbHUr7UPNA437Cn\nPr7QEhuZDFXnxjK/pvwR+YAo8PLV05oERTzdinnEKYTPEVYm801vIIDVINaw\nItQKenqZFypPbp726EUGe+5AusTWGva/CAB06mD+YD7i0rkYIo54hUwIXhCG\nwqDyTN7ObSbYCU3a6CdF1afNiiAKRVVebR4yzlpimnR5Rr5iUxH34Rs4P9G9\nwzkY0n58K0Oj9Y0IE4q6K4tk/2waJVW2Dmwrq7b0B5cTbnueAIhsr10wrm+k\noFPWAsjUdUnO633q1wxwOSg8P0y+sxLiVCA2QTZlfRDAXeJIZuMJLVX8livh\nSRCZ3hI3dO4/ZVzZ02wG53s4mklbjreQxFIo9QzP3f5hcuoMyVnqBRA6O3/U\ne88sJbdYhknUNVHrQ3736mtC7ouT4Acda8RHuTACJG5SiH0frbmrvxlQHXRl\ntpj0Zk9EhOOPHSKN3aSPuHTmCdrYvXvnx4JRndbGWILyuDZg0kUJb4fAEpp1\nkv1K\r\n=YypM\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFCyQeCdKO6wOQD85J0AWNBRGnh19hcH1pR2DTCwMi5HAiEA9Pb9WIqyXmdwHkD/yyLu1IRZgyibgyPSKG1BMd+DGnM="}]},"_npmUser":{"name":"metamystical","email":"metamystical@protonmail.com"},"directories":{},"maintainers":[{"name":"metamystical","email":"metamystical@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/mdht_3.1.2_1606225121612_0.8748828607617143"},"_hasShrinkwrap":false},"3.1.3":{"name":"mdht","version":"3.1.3","main":"mdht.js","description":"Mainline DHT","license":"MIT","repository":{"type":"git","url":"git+https://github.com/metamystical/mdht.git"},"dependencies":{"ed25519-supercop":"2.0.1","polycrc":"1.0.1"},"keywords":["dht","distributed-hash-table","mainline","bittorrent","p2p","BEP5","BEP42","BEP44"],"scripts":{"start":"node server.js"},"gitHead":"c5317f15c73edd039478ad7100fc9658f3098bdb","bugs":{"url":"https://github.com/metamystical/mdht/issues"},"homepage":"https://github.com/metamystical/mdht#readme","_id":"mdht@3.1.3","_nodeVersion":"15.3.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-unIqtAn5fPmH0n7TdWzj4d8zSPoTGBnJq4PK4Yl38JP3nRWJ2A/Xe3Tyc0nQEBqC4JDCMFUVVQinYIvHn2r/sg==","shasum":"7cf48739dea3f4035a8aac3c40be048a2ece945e","tarball":"https://registry.npmjs.org/mdht/-/mdht-3.1.3.tgz","fileCount":14,"unpackedSize":66048,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfzU/TCRA9TVsSAnZWagAA5RsP/iCB9Dwuz5AbMjd3XgZt\n1tU4ZHht2ZnqzuaYwFdj5aDIFhmYFFloB6JJeX28o6qu/qBehX259etL23Wc\nBl33SB4KU9NyHdjD4XlaHTBz2MHqbtSJAEkI5RcoIE77eTmnHCYwZGDSLDIt\n7nj6CVARkrOGCId6OzwVebFtVEvFqO44zDyFBWHiplrdOkGwKpXv167bhpfO\n57YHC/zN3FGHf7cspRqWBMxH3VRvoKYD3ZnOswJjM1kpqHjXKw31x25DUM8N\n6I1HjZreBsWCnXvCEQJIxuPG7fkzHDVr61d5Nfei9Dz+0+J8pZl1sfywIu/h\nxpa/a9tiYeUWyXGlaxqedzTUfURxH+O6kKyTykhj81PMb7e9zMk+vLtXNZJ8\nI6hIIR+UlFbfnlvXa96YaBLKrsau5xSg8MSA9NpQ3fJ26RDfpRPgTUGCPxoY\n3J1KOYdqlzyR3dCTx8ZXJjK/MZyBpB4pVRZqVcTTRMBRDjI90un76BWFWQjM\nNg7EjUIyqX5Gn7J1Q54FJeoyRTaveeff/fmBBTO0szXC0JTx59kdM+35Q1nq\nUSJ1jkFSx1W9592DC8xH+5zbPErGC2AmW5PoHwCId0iFUMPgeqC8vGq1ZGTJ\n3+bPg96ez1PG+kYDHiVWbbYKG9vqVRYeFflmTMOoqrxZhBLXyoO2JsTwF0C3\n453g\r\n=7MW4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFDNXevE09VlucWW/6KlrzGKxVrZQ77kEVyGIST1/avLAiEAtyYGuLSCSBphM0s7dbTkwv1l0GS9rjSHG7MkGya8hLk="}]},"_npmUser":{"name":"metamystical","email":"metamystical@protonmail.com"},"directories":{},"maintainers":[{"name":"metamystical","email":"metamystical@protonmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/mdht_3.1.3_1607290834458_0.049025250430372536"},"_hasShrinkwrap":false}},"readme":"## mdht -- Mainline DHT implemented in node.js\n\nDynamic Hash Table customized for the Mainline DHT used by bittorrent to locate torrent peers without using a tracker.\nIncludes BEP44 data storage. IPv4 only. References: [BEP5](http://www.bittorrent.org/beps/bep_0005.html), [BEP44](http://www.bittorrent.org/beps/bep_0044.html).\nComputes local [BEP42](http://www.bittorrent.org/beps/bep_0042.html) DHT node id from external IP address if provided.\n\n### Quick start\n\n```\n$ npm i mdht\n$ echo \"require('mdht/server')\" > server.js\n$ node server.js\n```\nserver.js will connect to the global mainline DHT via default UDP port 6881 (which should be forwarded),\nby bootstraping from router.bittorrent.com:6881, and then will begin to respond to requests from\nother nodes. Configuration information and incoming requests are\ndisplayed on the console. The routing table and cryptographic seed are\nsaved to disk for future restarts.\n\nserver.js interfaces between mdht.js (which in turn interfaces with the DHT network), the user\n(via the command line) and the disk (to preserve its state between sessions). It also accepts\ncommands from clients to issue outgoing requests to other DHT nodes via HTTP PUTs on the same port.\n\nNavigating to http://localhost:6881 (default port) in a browser loads a web page from server.js via HTTP GET,\ncontaining a simple UI for getting and putting BEP44 data and for announcing and getting peers.\nAlternatively, client/clientLib.js is available to include in custom clients running in a browser\nor running under Node.js. See client/clientTest.js for examples.\n\n### Terminology\n\nTerm | Description\n-----|------------\n*location* | network *location* (6-byte buffer: 4-byte IPv4 address + 2-byte port); example: Buffer.from('ff0000011ae1', 'hex') represents 127.0.0.1:6881\n*id* | DHT node *id*, infohash of a torrent, or target of BEP44 data (20-byte buffer)\nnode | a member of the Mainline DHT network which uses UDP\npeer | a bittorrent client associated with a DHT node which uses TCP, usually on the same port\n\n### Usage (API)\n```\nconst dhtInit = require('mdht')\nconst dht = dhtInit(options, update) // options is an object, update is a callback function\n```\n#### dhtInit options\n\nOption | Description\n-------|------------\noptions.port | local UDP server port (int, default 6881)\noptions.ip | external ip address used to compute DHT node *id* as per BEP42 (string, default: random *id* is used)\noptions.seed | seed for generating ed25519 key pair for signing mutable data (32-byte buffer, default random)\noptions.bootLocs | remote node *locations* to contact at startup (buffer of concatenated *locations*, default empty)\n\n#### dhtInit returns an object with the following methods:\n```\ndht.announcePeer(ih, impliedPort, ({ numVisited: ..., numStored: ... }) => {}, onV)\ndht.getPeers(ih, ({ numVisited: ..., numFound: ..., peers: ... }) => {}, onV)\ndht.putData(v, mutableSalt, resetTarget, ({ numVisited: ..., numStored: ..., target: ..., v: ..., salt: ..., seq: ..., k: ..., sig: ... }) => {}, onV)\ndht.getData(target, mutableSalt, ({ numVisited: ..., numFound: ..., v: ..., seq: ... }) => {}, onV)\ndht.makeMutableTarget(k, mutableSalt)\ndht.makeImmutableTarget(v)\ndht.stop()\n```\n##### where:\n\n*announcePeer*, *getPeers*, *putData* and *getData* initiate outgoing DHT queries to remote nodes and return\ninformation and/or results in their first callback function after all nodes have responded.\n\nTheir first callback function returns a single object with multiple properties pertinent to the method.\nObject properties that do not apply or were not found are omitted. For example, there will be no\n.peers or .v property if no peers or values are found; and .salt, .seq, .k and .sig are only returned for\nmutable data.\n\nTheir second callback function, onV, if not null or undefined, is called immediately whenever peer\nlocations or BEP44 data are received from a remote node, with a single argument: an object with\n.target and .values for *getPeers* and *announcePeer*, or .ih and .v for *getData* and *putData*,\nplus .socket in both cases, which is just an object version of a node *location*\n{ address: (string), port: (int) }.\n\n*makeMutableTarget* and *makeImmutableTarget* are utilities for computing targets (node *ids*) for use\nwith *getData* or *putData*, which can be called with the arguments target or resetTarget, respectively,\nalong with mutableSalt, as provided by whomever stored the data. If the target is unknown, it can be\ncomputed with *makeMutableTarget* (if k and mutableSalt are known) or *makeImmutableTarget*\n(if v is known).\n\n*stop* stops timers and closes the udp connection, thus stopping the DHT.\n\nArgument | Description\n---------|------------\nih | infohash, *id* of a torrent (buffer)\nimpliedPort | if 1, ignore local port and use externally visible port (undefined, 0 or 1)\ntarget | *id* of BEP44 data (buffer)\nv | BEP44 data to be stored in the DHT (object, buffer, string or number)\nmutableSalt | if immutable BEP44 data then *false* or *''*; if mutable data then *true* if no salt, or *salt* (non-empty string or buffer -- string will be converted to buffer, buffer will be truncated to 64 bytes)\nresetTarget | if not null, a target used to reset the timeout of previously stored mutable data (v is ignored in this case) (buffer)\nk | public key used to make a mutable target (buffer); if null, local public key is used\n\nProperty | Description\n---------|------------\nvalues | array of peer *locations* which have the torrent with infohash ih\ntarget | computed *id* of BEP44 data\nv | for putData, BEP44 data actually stored (may be a retrieved value if resetTarget is used); for getData, retrieved BEP44 data\nsalt | salt actually used (<= 64-byte buffer)\nseq | sequence number (int) of mutable data; outgoing/incoming for putData/getData\nk | public key used to sign and verify mutable data (32-byte buffer)\nsig | ed25519 signature of salt, v and seq (64-byte buffer)\n\n#### update is a function which signals the calling program and is called with two arguments (key, value)\n\nKey | Signal | Value\n----|--------|------\n'udpFail' | initialization failed | local port (int) that failed to open; calling program should restart using a different port\n'id' | initialized | *id* actually used to create routing table\n'publicKey' | initialized | public key (k) actually used for ed25519 signatures\n'listening' | local udp socket is listening | local socket\n'ready' | bootstrap is complete | number of remote nodes visited during bootstrap\n'incoming' | incoming query object | { q: query type (string), socket: remote socket }\n'error' | incoming error object | { e: [error code (int), error message (string)], socket: remote socket }\n'nodes' | periodic report | buffer packed with node *locations* from the routing table; may used for disk storage\n'closest' | periodic report | array of node *ids* from the routing table, the closest nodes to the table *id*\n'peers' | periodic report | { numPeers: number of stored peer locations, numInfohashes: number of stored infohashes }\n'data' | periodic report | number of BEP44 stored data items\n'spam' | detected spammer node, temporarily blocked| 'address:port'\n'dropNode' | node dropped from routing table | 'address:port'\n'dropPeer' | peer location dropped from storage | 'address:port'\n'dropData' | data dropped from BEP44 storage | 'target' (hex string)\n\n### BEP42 DHT Security extension\n\nAs of v3.1.0, mdht.js contains BEP42 code, partially implemented.\nThe code is used to generate a BEP42 compliant local DHT node *id*\ngiven the externally visible IP address. However, BEP42 is not\nenforced on remote DHT nodes. On the server.js log output,\nremote IP addresses are prefixed with an asterix when the corresponding\n*id* is not compliant. At this time, only a small percentage of\nDHT nodes are compliant.\n","maintainers":[{"name":"metamystical","email":"metamystical@protonmail.com"}],"time":{"modified":"2022-05-09T01:29:14.378Z","created":"2017-11-30T06:33:49.474Z","1.0.0":"2017-11-30T06:33:49.474Z","1.0.1":"2017-11-30T07:00:14.077Z","2.0.0":"2017-12-05T11:02:46.696Z","2.1.0":"2017-12-06T23:57:44.931Z","2.2.0":"2017-12-09T18:02:22.781Z","2.2.1":"2017-12-10T01:20:47.514Z","2.2.2":"2017-12-11T14:18:48.282Z","2.3.0":"2017-12-14T15:58:08.740Z","2.3.1":"2017-12-15T08:27:35.301Z","2.3.2":"2017-12-15T09:36:35.678Z","2.3.3":"2017-12-16T12:46:29.610Z","2.3.4":"2018-10-14T07:51:06.257Z","2.3.5":"2018-10-18T07:44:24.163Z","2.4.0":"2018-10-18T16:11:22.694Z","2.4.1":"2019-08-10T06:34:46.119Z","2.5.0":"2019-08-11T12:00:07.294Z","2.5.1":"2019-08-13T18:16:07.595Z","2.6.0":"2019-08-14T19:08:22.411Z","2.7.0":"2020-10-06T16:54:17.846Z","2.7.1":"2020-10-06T23:24:22.485Z","2.7.2":"2020-10-06T23:38:29.278Z","3.0.0":"2020-11-19T16:22:10.666Z","3.0.1":"2020-11-19T23:32:23.557Z","3.1.0":"2020-11-23T04:05:34.367Z","3.1.1":"2020-11-23T05:36:29.697Z","3.1.2":"2020-11-24T13:38:41.817Z","3.1.3":"2020-12-06T21:40:34.613Z"},"homepage":"https://github.com/metamystical/mdht#readme","repository":{"type":"git","url":"git+https://github.com/metamystical/mdht.git"},"bugs":{"url":"https://github.com/metamystical/mdht/issues"},"license":"MIT","readmeFilename":"README.md","keywords":["dht","distributed-hash-table","mainline","bittorrent","p2p","BEP5","BEP42","BEP44"]}