nictuku / dht Goto Github PK
View Code? Open in Web Editor NEWKademlia/Mainline DHT node in Go.
License: Other
Kademlia/Mainline DHT node in Go.
License: Other
dht/store.go
still refers to Taipei-Torrent in the filenames, I believe they should be changed to something more dht
-related
It seems that function "lookupFiltered" is only choosing nodes that "wasContactedRecently", without calculating distance, right?
see:
http://engineering.bittorrent.com/2013/12/19/dht-bootstrap-update/
http://libtorrent.org/dht_sec.html
I expect some useful reference code to be available here:
https://github.com/bittorrent/bootstrap-dht
Unless there's something that needs setup, go test doesn't work as I'd expect:
$ go test -v
=== RUN TestDHTLocal
It just hangs, or at least runs for a very long time.
func example(d *dht.DHT) {
for r := range d.PeersRequestResults {
for _, peers := range r {
for _, p := range peers {
dht.DecodePeerAddress(p) // can panic
}
}
}
}
Has resulted in this error once, of many runs. I do not know how to replicate it.
panic: runtime error: index out of range
goroutine 12 [running]:
runtime.panic(0x6e11e0, 0xc8bdb7)
/home/steve/.gvm/gos/go1.2rc3/src/pkg/runtime/panic.c:266 +0xb6
github.com/nictuku/nettools.BinaryToDottedPort(0x0, 0x0, 0x7fe8d2aefe90, 0x7fe8d2aefe80)
/home/steve/.gvm/pkgsets/go1.2rc3/global/src/github.com/nictuku/nettools/addresses.go:10 +0x260
github.com/nictuku/dht.DecodePeerAddress(0x0, 0x0, 0x14, 0xc21063ab80)
/home/steve/.gvm/pkgsets/go1.2rc3/global/src/github.com/nictuku/dht/krpc.go:258 +0x31
I have a very simple code that uses DHT to send out 16 peer requests every few minutes.
To launch the DHT:
numTargetPeers = 64
dht, err := dht.NewDHTNode(port, numTargetPeers, false)
Yet after just 16 calls to dht.PeersRequest and a minute or so of run time I get:
"totalDroppedPackets": 0,
"totalFindNodeDupes": 224,
"totalGetPeersDupes": 734,
"totalKilledNodes": 10
"totalNodes": 3610,
"totalPacketsFromBlockedHosts": 0,
"totalPeers": 15,
"totalReachableNodes": 575,
"totalRecv": 689,
"totalRecvFindNode": 0,
"totalRecvFindNodeReply": 185,
"totalRecvGetPeers": 0,
"totalRecvGetPeersReply": 403,
"totalRecvPingReply": 5,
"totalSelfPromotions": 0,
"totalSent": 3183,
"totalSentFindNode": 254,
"totalSentGetPeers": 2520,
"totalSentPing": 5,
SentGetPeers = 2520 times? Total Nodes = 3610?
My scroll back buffer isn't even long enough for a single second of the logs sent to stdout, I'll include a few here:
[10/30/13 05:10:19] [TRAC] wasContactedRecently for ih=4af397b24852d5b8b3e8ff389aff79288af69172 in node [email protected]:9638 returned true
[10/30/13 05:10:19] [TRAC] wasContactedRecently for ih=4af397b24852d5b8b3e8ff389aff79288af69172 in node [email protected]:51413 returned true
[10/30/13 05:10:19] [TRAC] wasContactedRecently for ih=4af397b24852d5b8b3e8ff389aff79288af69172 in node [email protected]:39776 returned true
[10/30/13 05:10:19] [TRAC] wasContactedRecently for ih=4af397b24852d5b8b3e8ff389aff79288af69172 in node [email protected]:8045 returned trueexit status 2
Am I doing something wrong? Is the default some kind of mapping all the nodes on the DHT or similar? My understanding is that each dht.PeersRequest should do log(N) peer lookups (where N is the number of nodes in the DHT).
I think there's a small issue regarding the dht.Run()
function, it both contains an initialization phase, prone to error (listen fails), and the main loop which I think suggests that it should be run in a go routine, since the only other way out is dht.Stop()
from another routine.
It makes the handling of the first error a bit tricky. It also leads to another trickiness : a call to dht.Port()
method is prone to hanging if listen fails and we did not check Run()
's return value - at least a close(dht.portRequest)
would be necessary I think
I'm not sure about the best way to handle this, or if you wish to change anything at all, ideally I think we should accept the main loop will be running in a routine, and go dht.loop()
ourselves in there as a private function if initialization (listen) was successful - loop not giving any error. It would allow the main entry point to return everytime, so we know the dht is running, or not. A downside to this is that it will induce retro-compatibilities issues, since we cannot expect dht.Run()
to block - maybe something like an alternate dht.Start()
, with depreciation on Run ?
The DHT node needs some space in memory (LRU) where it stores recent downloaders for infohashes.
https://github.com/vitessio/vitess/blob/master/go/cache/lru_cache.go
they have added a cost
type LRUCache struct {
mu sync.Mutex
// list & table contain *entry objects.
list *list.List
table map[string]*list.Element
cost func(interface{}) int64
size int64
capacity int64
evictions int64
}
Hey I am looking to store (publish my ownership of a infohash) is there a way this library can do this?
I run the example code, and then :
Note that there are many bad nodes that reply to anything you ask.
Peers found:
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x40e130, 0xe)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:547 +0x90
runtime.newstack()
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/stack.go:940 +0xb11
runtime.morestack()
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/asm_amd64.s:359 +0x7f
goroutine 24 [stack growth]:
runtime.mallocgc(0x10, 0x36a100, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/malloc.go:499 fp=0xc8402002c8 sp=0xc8402002c0
runtime.newobject(0x36a100, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/malloc.go:781 +0x42 fp=0xc8402002f0 sp=0xc8402002c8
runtime.convT2E(0x36a100, 0xc840200370, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/iface.go:140 +0x97 fp=0xc840200318 sp=0xc8402002f0
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0x9b fp=0xc8402003a0 sp=0xc840200318
github.com/nictuku/dht.(*InfoHash).String(0xc8258c74b0, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402003d8 sp=0xc8402003a0
fmt.(*pp).handleMethods(0xc8258de4e0, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402004b8 sp=0xc8402003d8
fmt.(*pp).printArg(0xc8258de4e0, 0x36a100, 0xc8258c74b0, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840200640 sp=0xc8402004b8
fmt.(*pp).doPrintf(0xc8258de4e0, 0x3fca10, 0x2, 0xc840200a60, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402009c8 sp=0xc840200640
fmt.Sprintf(0x3fca10, 0x2, 0xc840200a60, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840200a18 sp=0xc8402009c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc840200aa0 sp=0xc840200a18
github.com/nictuku/dht.(*InfoHash).String(0xc8258c74a0, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc840200ad8 sp=0xc840200aa0
fmt.(*pp).handleMethods(0xc8258de410, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc840200bb8 sp=0xc840200ad8
fmt.(*pp).printArg(0xc8258de410, 0x36a100, 0xc8258c74a0, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840200d40 sp=0xc840200bb8
fmt.(*pp).doPrintf(0xc8258de410, 0x3fca10, 0x2, 0xc840201160, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402010c8 sp=0xc840200d40
fmt.Sprintf(0x3fca10, 0x2, 0xc840201160, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840201118 sp=0xc8402010c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402011a0 sp=0xc840201118
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7490, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402011d8 sp=0xc8402011a0
fmt.(*pp).handleMethods(0xc8258de340, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402012b8 sp=0xc8402011d8
fmt.(*pp).printArg(0xc8258de340, 0x36a100, 0xc8258c7490, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840201440 sp=0xc8402012b8
fmt.(*pp).doPrintf(0xc8258de340, 0x3fca10, 0x2, 0xc840201860, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402017c8 sp=0xc840201440
fmt.Sprintf(0x3fca10, 0x2, 0xc840201860, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840201818 sp=0xc8402017c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402018a0 sp=0xc840201818
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7480, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402018d8 sp=0xc8402018a0
fmt.(*pp).handleMethods(0xc8258de270, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402019b8 sp=0xc8402018d8
fmt.(*pp).printArg(0xc8258de270, 0x36a100, 0xc8258c7480, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840201b40 sp=0xc8402019b8
fmt.(*pp).doPrintf(0xc8258de270, 0x3fca10, 0x2, 0xc840201f60, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc840201ec8 sp=0xc840201b40
fmt.Sprintf(0x3fca10, 0x2, 0xc840201f60, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840201f18 sp=0xc840201ec8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc840201fa0 sp=0xc840201f18
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7470, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc840201fd8 sp=0xc840201fa0
fmt.(*pp).handleMethods(0xc8258de1a0, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402020b8 sp=0xc840201fd8
fmt.(*pp).printArg(0xc8258de1a0, 0x36a100, 0xc8258c7470, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840202240 sp=0xc8402020b8
fmt.(*pp).doPrintf(0xc8258de1a0, 0x3fca10, 0x2, 0xc840202660, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402025c8 sp=0xc840202240
fmt.Sprintf(0x3fca10, 0x2, 0xc840202660, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840202618 sp=0xc8402025c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402026a0 sp=0xc840202618
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7460, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402026d8 sp=0xc8402026a0
fmt.(*pp).handleMethods(0xc8258de0d0, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402027b8 sp=0xc8402026d8
fmt.(*pp).printArg(0xc8258de0d0, 0x36a100, 0xc8258c7460, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840202940 sp=0xc8402027b8
fmt.(*pp).doPrintf(0xc8258de0d0, 0x3fca10, 0x2, 0xc840202d60, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc840202cc8 sp=0xc840202940
fmt.Sprintf(0x3fca10, 0x2, 0xc840202d60, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840202d18 sp=0xc840202cc8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc840202da0 sp=0xc840202d18
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7450, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc840202dd8 sp=0xc840202da0
fmt.(*pp).handleMethods(0xc8258de000, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc840202eb8 sp=0xc840202dd8
fmt.(*pp).printArg(0xc8258de000, 0x36a100, 0xc8258c7450, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840203040 sp=0xc840202eb8
fmt.(*pp).doPrintf(0xc8258de000, 0x3fca10, 0x2, 0xc840203460, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402033c8 sp=0xc840203040
fmt.Sprintf(0x3fca10, 0x2, 0xc840203460, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840203418 sp=0xc8402033c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402034a0 sp=0xc840203418
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7440, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402034d8 sp=0xc8402034a0
fmt.(*pp).handleMethods(0xc8258dbee0, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402035b8 sp=0xc8402034d8
fmt.(*pp).printArg(0xc8258dbee0, 0x36a100, 0xc8258c7440, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840203740 sp=0xc8402035b8
fmt.(*pp).doPrintf(0xc8258dbee0, 0x3fca10, 0x2, 0xc840203b60, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc840203ac8 sp=0xc840203740
fmt.Sprintf(0x3fca10, 0x2, 0xc840203b60, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840203b18 sp=0xc840203ac8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc840203ba0 sp=0xc840203b18
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7430, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc840203bd8 sp=0xc840203ba0
fmt.(*pp).handleMethods(0xc8258dbe10, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc840203cb8 sp=0xc840203bd8
fmt.(*pp).printArg(0xc8258dbe10, 0x36a100, 0xc8258c7430, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840203e40 sp=0xc840203cb8
fmt.(*pp).doPrintf(0xc8258dbe10, 0x3fca10, 0x2, 0xc840204260, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402041c8 sp=0xc840203e40
fmt.Sprintf(0x3fca10, 0x2, 0xc840204260, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840204218 sp=0xc8402041c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402042a0 sp=0xc840204218
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7420, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402042d8 sp=0xc8402042a0
fmt.(*pp).handleMethods(0xc8258dbd40, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402043b8 sp=0xc8402042d8
fmt.(*pp).printArg(0xc8258dbd40, 0x36a100, 0xc8258c7420, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840204540 sp=0xc8402043b8
fmt.(*pp).doPrintf(0xc8258dbd40, 0x3fca10, 0x2, 0xc840204960, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402048c8 sp=0xc840204540
fmt.Sprintf(0x3fca10, 0x2, 0xc840204960, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840204918 sp=0xc8402048c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402049a0 sp=0xc840204918
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7410, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402049d8 sp=0xc8402049a0
fmt.(*pp).handleMethods(0xc8258dbc70, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc840204ab8 sp=0xc8402049d8
fmt.(*pp).printArg(0xc8258dbc70, 0x36a100, 0xc8258c7410, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840204c40 sp=0xc840204ab8
fmt.(*pp).doPrintf(0xc8258dbc70, 0x3fca10, 0x2, 0xc840205060, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc840204fc8 sp=0xc840204c40
fmt.Sprintf(0x3fca10, 0x2, 0xc840205060, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840205018 sp=0xc840204fc8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402050a0 sp=0xc840205018
github.com/nictuku/dht.(*InfoHash).String(0xc8258c7400, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402050d8 sp=0xc8402050a0
fmt.(*pp).handleMethods(0xc8258dbba0, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402051b8 sp=0xc8402050d8
fmt.(*pp).printArg(0xc8258dbba0, 0x36a100, 0xc8258c7400, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840205340 sp=0xc8402051b8
fmt.(*pp).doPrintf(0xc8258dbba0, 0x3fca10, 0x2, 0xc840205760, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402056c8 sp=0xc840205340
fmt.Sprintf(0x3fca10, 0x2, 0xc840205760, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840205718 sp=0xc8402056c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402057a0 sp=0xc840205718
github.com/nictuku/dht.(*InfoHash).String(0xc8258c73f0, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402057d8 sp=0xc8402057a0
fmt.(*pp).handleMethods(0xc8258dbad0, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402058b8 sp=0xc8402057d8
fmt.(*pp).printArg(0xc8258dbad0, 0x36a100, 0xc8258c73f0, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840205a40 sp=0xc8402058b8
fmt.(*pp).doPrintf(0xc8258dbad0, 0x3fca10, 0x2, 0xc840205e60, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc840205dc8 sp=0xc840205a40
fmt.Sprintf(0x3fca10, 0x2, 0xc840205e60, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840205e18 sp=0xc840205dc8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc840205ea0 sp=0xc840205e18
github.com/nictuku/dht.(*InfoHash).String(0xc8258c73e0, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc840205ed8 sp=0xc840205ea0
fmt.(*pp).handleMethods(0xc8258dba00, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc840205fb8 sp=0xc840205ed8
fmt.(*pp).printArg(0xc8258dba00, 0x36a100, 0xc8258c73e0, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840206140 sp=0xc840205fb8
fmt.(*pp).doPrintf(0xc8258dba00, 0x3fca10, 0x2, 0xc840206560, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402064c8 sp=0xc840206140
fmt.Sprintf(0x3fca10, 0x2, 0xc840206560, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840206518 sp=0xc8402064c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402065a0 sp=0xc840206518
github.com/nictuku/dht.(*InfoHash).String(0xc8258c73d0, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc8402065d8 sp=0xc8402065a0
fmt.(*pp).handleMethods(0xc8258db930, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc8402066b8 sp=0xc8402065d8
fmt.(*pp).printArg(0xc8258db930, 0x36a100, 0xc8258c73d0, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840206840 sp=0xc8402066b8
fmt.(*pp).doPrintf(0xc8258db930, 0x3fca10, 0x2, 0xc840206c60, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc840206bc8 sp=0xc840206840
fmt.Sprintf(0x3fca10, 0x2, 0xc840206c60, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840206c18 sp=0xc840206bc8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc840206ca0 sp=0xc840206c18
github.com/nictuku/dht.(*InfoHash).String(0xc8258c73c0, 0x0, 0x0)
<autogenerated>:3 +0xa4 fp=0xc840206cd8 sp=0xc840206ca0
fmt.(*pp).handleMethods(0xc8258db860, 0xc800000078, 0x0, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:730 +0x62a fp=0xc840206db8 sp=0xc840206cd8
fmt.(*pp).printArg(0xc8258db860, 0x36a100, 0xc8258c73c0, 0x78, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:806 +0x4a9 fp=0xc840206f40 sp=0xc840206db8
fmt.(*pp).doPrintf(0xc8258db860, 0x3fca10, 0x2, 0xc840207360, 0x1, 0x1)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:1238 +0x1dcd fp=0xc8402072c8 sp=0xc840206f40
fmt.Sprintf(0x3fca10, 0x2, 0xc840207360, 0x1, 0x1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/fmt/print.go:203 +0x6f fp=0xc840207318 sp=0xc8402072c8
github.com/nictuku/dht.InfoHash.String(0xc8200daba0, 0x14, 0x0, 0x0)
/workspace/go/src/github.com/nictuku/dht/krpc.go:277 +0xfb fp=0xc8402073a0 sp=0xc840207318
...additional frames elided...
created by github.com/nictuku/dht.(*DHT).Start
/workspace/go/src/github.com/nictuku/dht/dht.go:319 +0x95
goroutine 1 [sleep]:
time.Sleep(0x12a05f200)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/time.go:59 +0xf9
main.main()
/tongshe/tongshe-desktop/ssmm/p2p.go:65 +0x8f2
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/asm_amd64.s:1998 +0x1
goroutine 20 [chan receive]:
github.com/golang/glog.(*loggingT).flushDaemon(0x5e33a0)
/workspace/go/src/github.com/golang/glog/glog.go:882 +0x67
created by github.com/golang/glog.init.1
/workspace/go/src/github.com/golang/glog/glog.go:410 +0x297
goroutine 21 [select]:
github.com/nictuku/nettools.(*ClientThrottle).cleanup(0xc8200da9c0)
/workspace/go/src/github.com/nictuku/nettools/ratelimit.go:78 +0x2ec
created by github.com/nictuku/nettools.NewThrottler
/workspace/go/src/github.com/nictuku/nettools/ratelimit.go:19 +0x31a
goroutine 23 [IO wait]:
net.runtime_pollWait(0x1210fd8, 0x72, 0x1250028)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/netpoll.go:160 +0x60
net.(*pollDesc).Wait(0xc8200f8060, 0x72, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitRead(0xc8200f8060, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/fd_poll_runtime.go:78 +0x36
net.(*netFD).accept(0xc8200f8000, 0x0, 0x12110d0, 0xc82000e1c0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/fd_unix.go:426 +0x27c
net.(*TCPListener).AcceptTCP(0xc82002a010, 0xbf5b1, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/tcpsock_posix.go:254 +0x4d
net/http.tcpKeepAliveListener.Accept(0xc82002a010, 0x0, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/http/server.go:2427 +0x41
net/http.(*Server).Serve(0xc8200f6000, 0x1211098, 0xc82002a010, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/http/server.go:2117 +0x129
net/http.(*Server).ListenAndServe(0xc8200f6000, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/http/server.go:2098 +0x136
net/http.ListenAndServe(0xc820071048, 0x5, 0x0, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/http/server.go:2195 +0x98
created by main.main
/tongshe/tongshe-desktop/ssmm/p2p.go:55 +0x74d
goroutine 25 [chan receive]:
main.drainresults(0xc8200a6280)
/tongshe/tongshe-desktop/ssmm/p2p.go:76 +0x42c
created by main.main
/tongshe/tongshe-desktop/ssmm/p2p.go:61 +0x8b8
goroutine 4 [IO wait]:
net.runtime_pollWait(0x1210f18, 0x72, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/netpoll.go:160 +0x60
net.(*pollDesc).Wait(0xc82006a450, 0x72, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitRead(0xc82006a450, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/fd_poll_runtime.go:78 +0x36
net.(*netFD).readFrom(0xc82006a3f0, 0xc82014e000, 0x1000, 0x1000, 0x0, 0x0, 0x0, 0x1250028, 0xc8200700a0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/fd_unix.go:277 +0x2a5
net.(*UDPConn).ReadFromUDP(0xc820080050, 0xc82014e000, 0x1000, 0x1000, 0x0, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.6.2/libexec/src/net/udpsock_posix.go:61 +0x117
github.com/nictuku/dht.readFromSocket(0xc820080050, 0xc8200e60c0, 0xc8200e6060, 0xc82006e240)
/workspace/go/src/github.com/nictuku/dht/krpc.go:234 +0x100
github.com/nictuku/dht.(*DHT).loop.func1(0xc8200a6280, 0xc8200e60c0, 0xc8200e6060)
/workspace/go/src/github.com/nictuku/dht/dht.go:386 +0x84
created by github.com/nictuku/dht.(*DHT).loop
/workspace/go/src/github.com/nictuku/dht/dht.go:387 +0x135
Hey there,
This is a little off topic, but what is the UI that is in the image in the readme?
Thanks,
-MH
code.google.com/p/bencode-go ==> github.com/jackpal/bencode-go
code.google.com/p/vitess/go/cache ==> github.com/youtube/vitess/go/cache
WARNING: DATA RACE
Write by goroutine 52:
github.com/nictuku/dht.(_remoteNode).newQuery()
/Users/yves/go/src/pkg/github.com/nictuku/dht/krpc.go:88 +0x186
github.com/nictuku/dht.(_DHT).pingNode()
/Users/yves/go/src/pkg/github.com/nictuku/dht/dht.go:414 +0x116
github.com/nictuku/dht.func·002()
/Users/yves/go/src/pkg/github.com/nictuku/dht/dht.go:267 +0x105
Previous read by goroutine 10:
github.com/nictuku/dht.(_nTree).filter()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:224 +0x100
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:151 +0xf6
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:179 +0x480
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:179 +0x480
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:179 +0x480
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).traverse()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:175 +0x334
github.com/nictuku/dht.(_nTree).lookupFiltered()
/Users/yves/go/src/pkg/github.com/nictuku/dht/routing.go:143 +0x105
github.com/nictuku/dht.(_DHT).nodesForInfoHash()
/Users/yves/go/src/pkg/github.com/nictuku/dht/dht.go:526 +0xd7
github.com/nictuku/dht.(_DHT).replyGetPeers()
/Users/yves/go/src/pkg/github.com/nictuku/dht/dht.go:519 +0x5da
github.com/nictuku/dht.(_DHT).processPacket()
/Users/yves/go/src/pkg/github.com/nictuku/dht/dht.go:390 +0x14f1
github.com/nictuku/dht.(*DHT).DoDHT()
/Users/yves/go/src/pkg/github.com/nictuku/dht/dht.go:244 +0x84b
Goroutine 52 (running) created at:
github.com/nictuku/dht.(*DHT).DoDHT()
/Users/yves/go/src/pkg/github.com/nictuku/dht/dht.go:270 +0xa74
Goroutine 10 (running) created at:
main.main()
/Users/yves/go/src/github.com/nictuku/magnets/supernode/main.go:99 +0x3c5
runtime.main()
/Users/yves/go/src/pkg/runtime/proc.c:248 +0x91
This is not reliably reproduceable.
$ go test -v
=== RUN TestDHTLocal
Found peer 0: 127.0.0.1:52407
Found peer 0: 127.0.0.1:42450
--- PASS: TestDHTLocal (1.41 seconds)
=== RUN TestDHTLarge
panic: routingTable.insert() got a node with a nil address
goroutine 41 [running]:
runtime.panic(0x67d840, 0xc20815e100)
/usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
github.com/nictuku/dht.(*routingTable).insert(0xc2080a4ba0, 0xc20815ac00, 0x0, 0x0)
/home/nictuku/src/github.com/nictuku/dht/routing_table.go:122 +0x391
github.com/nictuku/dht.(*routingTable).getOrCreateNode(0xc2080a4ba0, 0xc208152000, 0x14, 0xc208169fe0, 0x10, 0xc20815ac0
0, 0x0, 0x0)
/home/nictuku/src/github.com/nictuku/dht/routing_table.go:162 +0x180
github.com/nictuku/dht.(*DHT).processFindNodeResults(0xc2080b2fc0, 0xc2080a2240, 0xc20816962a, 0x1, 0xc20816970a, 0x1, 0
x0, 0x0, 0x0, 0x0, ...)
/home/nictuku/src/github.com/nictuku/dht/dht.go:908 +0xa86
github.com/nictuku/dht.(*DHT).processPacket(0xc2080b2fc0, 0xc208121000, 0x11c, 0x1000, 0xc208141e88, 0x4, 0x4, 0x1ae1, 0
x0, 0x0)
/home/nictuku/src/github.com/nictuku/dht/dht.go:518 +0xec7
github.com/nictuku/dht.(*DHT).Run(0xc2080b2fc0, 0x0, 0x0)
/home/nictuku/src/github.com/nictuku/dht/dht.go:385 +0xca4
created by github.com/nictuku/dht.TestDHTLarge
/home/nictuku/src/github.com/nictuku/dht/dht_test.go:178 +0x2cf
goroutine 16 [chan receive]:
testing.RunTests(0x7ff570, 0x91ff60, 0xa, 0xa, 0x1)
/usr/local/go/src/pkg/testing/testing.go:505 +0x923
testing.Main(0x7ff570, 0x91ff60, 0xa, 0xa, 0x91e720, 0x3, 0x3, 0x91b0a0, 0x1, 0x1)
/usr/local/go/src/pkg/testing/testing.go:435 +0x84
main.main()
github.com/nictuku/dht/_test/_testmain.go:73 +0x9c
BEP 5 has been updated to document the long standing de-facto standard of including a version string in RPC messages. This is an important feature for identifying implementations which may be lacking features or misbehaving. The relevant section of BEP5:
A key
v
should be included in every message with a client version string. The string should be a two character client identifier registered in BEP 20 followed by a two character version identifier.
The convention is for the client identifier to identify the DHT implementation rather than the client application. Thus the same identifier should be used regardless of which client is using this module.
Hey, this is Bill Broadley. Was using sourcegraph to look at DHT for the pending IPv6 patches. Seems harmless (and free) to enable sourcegraph to rebuild after each commit. Just a though, thanks.
I want to use Sourcegraph code search and code review with dht. A project maintainer needs to enable it to set up a webhook so the code is up-to-date there.
Could you please enable dht on @sourcegraph by going to https://sourcegraph.com/github.com/nictuku/dht and clicking on Settings? (It should only take 15 seconds.)
Thank you!
When I looked at the code of peerContactsSet, this function seems to be wrong.
func (p *peerContactsSet) next() []string {
count := kNodes
if count > len(p.set) {
count = len(p.set)
}
x := make([]string, 0, count)
xx := make(map[string]bool) //maps are easier to dedupe
for range p.set {
nid := p.ring.Move(1).Value.(string) <----this line will always return the first next item since p.ring never change its pos.
if _, ok := xx[nid]; p.set[nid] && !ok {
xx[nid] = true
}
if len(xx) >= count {
break
}
}
...
The move function will return a new pointer rather than change the original pointer as demonstrated in this playground.
func (r *Ring) Move(n int) *Ring {
if r.next == nil {
return r.init()
}
switch {
case n < 0:
for ; n < 0; n++ {
r = r.prev
}
case n > 0:
for ; n > 0; n-- {
r = r.next
}
}
return r
}
Need a PR to fix it?
In your project, you use github.com/youtube/vitess/go/cache
and github.com/golang/groupcache/lru
.
These dependencies are HUGE and you only need a small part.
You should copy them and create a small repository, like https://github.com/pierrre/lrucache .
Of possible interest.
http://people.kth.se/~rauljc/p2p11/jimenez2011subsecond.pdf
Optimization for mainline compatible DHT that significantly improves performance and efficiency.
Inspired by Taipei Torrent's swarm test, I want to make sure the DHT nodes are able to talk to each other properly.
Interoperability should be tested eventually but that would be a separate issue.
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0xb9db6]
goroutine 10 [running]:
github.com/nictuku/dht.(_routingTable).kill(0xc20803cb10, 0xc2080980c0)
/Users/yuansc/go/src/github.com/nictuku/dht/routing_table.go:176 +0x136
github.com/nictuku/dht.(_routingTable).cleanup(0xc20803cb10, 0xd18c2e2800, 0xc20802e3c0, 0x0, 0xa)
/Users/yuansc/go/src/github.com/nictuku/dht/routing_table.go:228 +0x8d3
github.com/nictuku/dht.(*DHT).Run(0xc20804e140, 0x0, 0x0)
/Users/yuansc/go/src/github.com/nictuku/dht/dht.go:412 +0x1045
created by main.main
/Users/yuansc/go/src/dht/examples/find_infohash_and_wait/main.go:57 +0x783
goroutine 1 [sleep]:
main.main()
/Users/yuansc/go/src/dht/examples/find_infohash_and_wait/main.go:65 +0x923
goroutine 5 [chan receive]:
github.com/golang/glog.(*loggingT).flushDaemon(0x4a0b00)
/Users/yuansc/go/src/github.com/golang/glog/glog.go:879 +0x78
created by github.com/golang/glog.init·1
/Users/yuansc/go/src/github.com/golang/glog/glog.go:410 +0x2a7
goroutine 17 [syscall, 45 minutes, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 7 [select]:
github.com/nictuku/nettools.(*ClientThrottle).cleanup(0xc20800ab20)
/Users/yuansc/go/src/github.com/nictuku/nettools/ratelimit.go:78 +0x28b
created by github.com/nictuku/nettools.NewThrottler
/Users/yuansc/go/src/github.com/nictuku/nettools/ratelimit.go:19 +0xe8
goroutine 12 [IO wait, 43 minutes]:
net.(_pollDesc).Wait(0xc208010220, 0x72, 0x0, 0x0)
/usr/local/go/src/net/fd_poll_runtime.go:84 +0x47
net.(_pollDesc).WaitRead(0xc208010220, 0x0, 0x0)
/usr/local/go/src/net/fd_poll_runtime.go:89 +0x43
net.(_netFD).readFrom(0xc2080101c0, 0xc208094000, 0x1000, 0x1000, 0x0, 0x0, 0x0, 0x566b48, 0xc20802aa10)
/usr/local/go/src/net/fd_unix.go:269 +0x4a1
net.(_UDPConn).ReadFromUDP(0xc20802c050, 0xc208094000, 0x1000, 0x1000, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/net/udpsock_posix.go:67 +0x124
github.com/nictuku/dht.readFromSocket(0xc20802c050, 0xc208050540, 0xc2080505a0, 0xc208050180)
/Users/yuansc/go/src/github.com/nictuku/dht/krpc.go:231 +0xff
created by github.com/nictuku/dht.(*DHT).Run
/Users/yuansc/go/src/github.com/nictuku/dht/dht.go:307 +0x1eb
goroutine 9 [IO wait, 43 minutes]:
net.(_pollDesc).Wait(0xc2080101b0, 0x72, 0x0, 0x0)
/usr/local/go/src/net/fd_poll_runtime.go:84 +0x47
net.(_pollDesc).WaitRead(0xc2080101b0, 0x0, 0x0)
/usr/local/go/src/net/fd_poll_runtime.go:89 +0x43
net.(_netFD).accept(0xc208010150, 0x0, 0x566b48, 0xc20802a950)
/usr/local/go/src/net/fd_unix.go:419 +0x40b
net.(_TCPListener).AcceptTCP(0xc20802c048, 0x70cc4, 0x0, 0x0)
/usr/local/go/src/net/tcpsock_posix.go:234 +0x4e
net/http.tcpKeepAliveListener.Accept(0xc20802c048, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/net/http/server.go:1976 +0x4c
net/http.(_Server).Serve(0xc2080504e0, 0x568200, 0xc20802c048, 0x0, 0x0)
/usr/local/go/src/net/http/server.go:1728 +0x92
net/http.(_Server).ListenAndServe(0xc2080504e0, 0x0, 0x0)
/usr/local/go/src/net/http/server.go:1718 +0x154
net/http.ListenAndServe(0xc20802a910, 0x5, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/net/http/server.go:1808 +0xba
created by main.main
/Users/yuansc/go/src/dht/examples/find_infohash_and_wait/main.go:55 +0x769
goroutine 11 [chan receive, 43 minutes]:
main.drainresults(0xc20804e140)
/Users/yuansc/go/src/dht/examples/find_infohash_and_wait/main.go:75 +0x32d
created by main.main
/Users/yuansc/go/src/dht/examples/find_infohash_and_wait/main.go:58 +0x79d
exit status 2
yuansc@/go/src/dht/examples/find_infohash_and_wait:$/go/src/dht/examples/find_infohash_and_wait:$ go run main.go deca7a89a1dbdc4b213de1c0d5351e92582f31fb
yuansc@
panic: runtime error: index out of range
goroutine 1064 [running]:
runtime.panic(0x73b980, 0xba1337)
/usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
github.com/nictuku/dht.commonBits(0xc2109e8fe0, 0x14, 0x0, 0x0, 0xc22ea73680)
/home/nictuku/src/github.com/nictuku/dht/routing.go:241 +0x15f
github.com/nictuku/dht.(_routingTable).neighborhoodUpkeep(0xc210f0cf60, 0xc213537b80)
/home/nictuku/src/github.com/nictuku/dht/routing_table.go:248 +0xa6
github.com/nictuku/dht.(_DHT).processPacket(0xc210fdcf00, 0xc211512000, 0x41, 0x1000, 0xc2308810f0)
/home/nictuku/src/github.com/nictuku/dht/dht.go:476 +0x6a0
github.com/nictuku/dht.(_DHT).Run(0xc210fdcf00, 0x0, 0x0)
/home/nictuku/src/github.com/nictuku/dht/dht.go:374 +0x9ee
github.com/nictuku/dht.(_DHT).DoDHT(0xc210fdcf00)
/home/nictuku/src/github.com/nictuku/dht/deprecated.go:5 +0x27
created by main.main
/home/nictuku/src/github.com/nictuku/magnets/supernode/main.go:127 +0x773
I have recently been using Popcorn Time a lot, and I like the features but dislike the build quality.
So I started thinking about how one could build something similar, but more robust. The first improvement, of course, would be to build it in Go instead of JavaScript.
Another would be to use some other search/browse database than whatever Popcorn Time uses (which isn't very robust at all).
Finally I found https://www.usenix.org/legacy/event/woot10/tech/full_papers/Wolchok.pdf, which describes how to seed the network with pure forwarding nodes that only tap the infohashes it sees in those nodes, and then fetch the metadata from the hosting nodes to put them in a local searchable database.
This made me start looking at your code. Unfortunately I get confused by it - I am used to chord-style networks, and kademlia is like greek to me :)
Where should I add code to enable some kind of callback function whenever the node gets queried about an infohash?
This DHT/BEP-0005 is a great way to find peers for any p2p program, not just torrent clients.
Of course if you aren't a bit-torrent client you likely want to find other similar peers. This would be trivial without evil peers that reply to any infohash. So you could just make an infohash from "I am p2p peer foo version 1.2.3x" and anyone else with that string could find you. Alas some peers will respond to any infohash request.
Can you think of any response from the supported commands that would help differentiate peers? Any idea how different bit-torrent clients that support unique functionality with peers running the same software detect each other? I'm trying to avoid just trying to connect to some socket because of complications for end users to forward extra ports through routers and the like.
A similar Kademlia implementation mentions families at:
https://github.com/telehash/telehash.org/blob/master/protocol.md#family-usage
Sounds ideal:
I realize this may be outside the intended scope, but I figured it's worth mentioning just in case.
It's not clear about possibility to build a DHT router on this library.
It seems that this is possible, because in dht_test.go
there is a test TestDHTLocal
that seems testing exact same case. But it also looks like test itself is incorrect.
If add little bit more logging to it, then output will be
n1 started at port 52361
n2 started at port 52604
n3 started at port 57136
Node n3 found a peer 0: 127.0.0.1:57136
Node n2 found a peer 0: 127.0.0.1:52604
It looks like node found itself as a peer instead of finding at least one more node.
Do I understand meaning of the test correctly? Is it possible after all to use this library for building DHT router?
was running about 5 hours with that settings ... filling in 1000 searches/hashes in parallel and immediately refill it...
I've used a slightly modified dht.go because I had disabled the clientThrottle feature for debugging reason. so use that one regarding line numbers.
s, err = dht.New(&dht.Config{
Address: "",
Port: sPort,
NumTargetPeers: 5000,
DHTRouters: "router.magnets.im:6881,router.bittorrent.com:6881,dht.transmissionbt.com:6881,router.utorrent.com:6881,dht.aelitis.com:6881,dht.libtorrent.org:25401",
MaxNodes: 500,
CleanupPeriod: 3 * time.Minute,
SaveRoutingTable: false,
RateLimit: -1,
MaxInfoHashes: 2,
MaxInfoHashPeers: 2,
ClientPerMinuteLimit: 50,
ThrottlerTrackedClients: 10,
UDPProto: "udp4",
more detailed
it seems 2.5gig of the 8 get’s eaten by dht.go:610 which is
node.pastQueries[r.T] = query
also in krpc.go:189 the jackpal unmarshal eats another 1.123gig
CPU looks fine to me, just the unmarshal eats a plenty.. after I got (and still see) many of dht.go:568] DHT: readResponse Error: unexpected EOF
, I was trying to replace it with https://github.com/IncSW/go-bencode (with is much less cpu intensive regarding the benchmarks there) to see if it solves the issue, but due to my very limited golang skills I was unable to find the right syntax parameters and value type conversations to make it work.
One of the harder parts of P2P is dealing with IP Masq/NAT'd peers. Fortunately there's an awesome fix, IPv6. Google claims 9.85% of Google's traffic in the USA is from IPv6 users, far from a trivial number. I've managed to get IPv6 connectivity working at 2 locations so I can tinker. Comcast is giving out /60's to regular home users!
I'm going to take a shot at it. I've not written any IPv6 code before though.
The resources I'm referencing are https://github.com/jech/dht and http://www.bittorrent.org/beps/bep_0032.html.
Just figured I'd post here in case anyone else is interested or planning similar.
I am using dht
as a library in my application and I don't want it to print any log statements to the output. The output of dht
library does not make sense to the user of my application.
There are messages showing as
ERROR: logging before flag.Parse: W1103 08:59:46.124232 26525 dht.go:566] DHT: readResponse Error: unexpected EOF, "d1:rd2:id20:d\xe9ᢇN>\r\x03-\xc8t\xcd\xfc\xca\x15L.\xe6D5:nodes4368:...
in the output of my program. There are 2 issues that causes this:
glog
requires flag.Parse()
to be called before logging any output. My program does not call flag.Parse()
.dht
logs at level zero (V(0)
).IMO, a good library must not print any output and should provide a way of returning internal events and errors. I propose removing glog
from this library and take a logger implementation from outside that implements dht.Logger
interface. I can provide a PR for this if you are OK with the idea.
If you don't want to remove glog
, for just solving the output problem, we can replace direct calls to glog.Info
and glog.Warning
functions into glog.V(1).Info
calls. In other words, do not log output at level 0. I can provide a PR for this too.
@nictuku what do you think?
panic: runtime error: slice bounds out of range
goroutine 18 [running]:
github.com/nictuku/nettools.DottedPortToBinary(0xc200e0f5a0, 0x1c, 0x1c, 0xc200ece978)
/home/nictuku/src/github.com/nictuku/nettools/addresses.go:25 +0x404
github.com/nictuku/dht.(_DHT).nodesForInfoHash(0xc20010f380, 0xc200e15f40, 0x14, 0x0, 0x0, ...)
/home/nictuku/src/github.com/nictuku/dht/dht.go:525 +0x17a
github.com/nictuku/dht.(_DHT).replyGetPeers(0xc20010f380, 0xc200e20840, 0xc200ece600, 0x4, 0xc200ece748, ...)
/home/nictuku/src/github.com/nictuku/dht/dht.go:515 +0x62d
github.com/nictuku/dht.(_DHT).processPacket(0xc20010f380, 0xc20081d000, 0x6a, 0x1000, 0xc200e20840, ...)
/home/nictuku/src/github.com/nictuku/dht/dht.go:383 +0x1449
github.com/nictuku/dht.(_DHT).DoDHT(0xc20010f380)
/home/nictuku/src/github.com/nictuku/dht/dht.go:252 +0x8f4
created by main.main
/home/nictuku/src/github.com/nictuku/magnets/supernode/main.go:119 +0x8d9
Do you have support BEP044? dht_store , If not , then do you have a plan to support it ? Thanks very much!
nictuku@1:~/src/github.com/nictuku/dht/examples/find_infohash_and_wait$ ./find_infohash_and_wait b04eeb70b231286c47ae61840fc52153768dc83d > log
grep 6730962b722d07086c265c4f6261c73f3ee2f919 log
[03/25/13 00:37:10] [TRAC] DHT: Got new node reference, query 31f8f17ce6be853dfd8c92964f250b333d90cba7: [email protected]:53798 from [email protected]:6881. Distance: 116b102ce885d9e05694e610d0f66ca09fd9db52.
[03/25/13 00:37:10] [TRAC] wasContactedRecently for ih=31f8f17ce6be853dfd8c92964f250b333d90cba7 in node [email protected]:53798 returned false
[03/25/13 00:37:10] [TRAC] [email protected]:53798
[03/25/13 00:37:10] [TRAC] newQuery for 6730962b722d07086c265c4f6261c73f3ee2f919, lastID 1
[03/25/13 00:37:10] [TRAC] DHT sending find_node. nodeID: [email protected]:53798, target ID: 31f8f17ce6be853dfd8c92964f250b333d90cba7 , distance: 56c867579493823591aaced92d44cc0c037232be
[03/25/13 00:37:10] [TRAC] wasContactedRecently for ih=31f8f17ce6be853dfd8c92964f250b333d90cba7 in node [email protected]:53798 returned false
[03/25/13 00:37:10] [TRAC] [email protected]:53798
[03/25/13 00:37:10] [TRAC] newQuery for 6730962b722d07086c265c4f6261c73f3ee2f919, lastID 2
[03/25/13 00:37:10] [TRAC] DHT sending find_node. nodeID: [email protected]:53798, target ID: 31f8f17ce6be853dfd8c92964f250b333d90cba7 , distance: 56c867579493823591aaced92d44cc0c037232be
[03/25/13 00:37:10] [TRAC] wasContactedRecently for ih=31f8f17ce6be853dfd8c92964f250b333d90cba7 in node [email protected]:53798 returned false
[03/25/13 00:37:10] [TRAC] [email protected]:53798
[03/25/13 00:37:10] [TRAC] newQuery for 6730962b722d07086c265c4f6261c73f3ee2f919, lastID 3
[03/25/13 00:37:10] [TRAC] DHT sending find_node. nodeID: [email protected]:53798, target ID: 31f8f17ce6be853dfd8c92964f250b333d90cba7 , distance: 56c867579493823591aaced92d44cc0c037232be
[03/25/13 00:37:10] [TRAC] wasContactedRecently for ih=31f8f17ce6be853dfd8c92964f250b333d90cba7 in node [email protected]:53798 returned false
[03/25/13 00:37:10] [TRAC] [email protected]:53798
[03/25/13 00:37:10] [TRAC] newQuery for 6730962b722d07086c265c4f6261c73f3ee2f919, lastID 4
[03/25/13 00:37:10] [TRAC] DHT sending find_node. nodeID: [email protected]:53798, target ID: 31f8f17ce6be853dfd8c92964f250b333d90cba7 , distance: 56c867579493823591aaced92d44cc0c037232be
[03/25/13 00:37:10] [TRAC] wasContactedRecently for ih=31f8f17ce6be853dfd8c92964f250b333d90cba7 in node [email protected]:53798 returned false
[03/25/13 00:37:10] [TRAC] [email protected]:53798
[03/25/13 00:37:10] [TRAC] newQuery for 6730962b722d07086c265c4f6261c73f3ee2f919, lastID 5
[03/25/13 00:37:10] [TRAC] DHT sending find_node. nodeID: [email protected]:53798, target ID: 31f8f17ce6be853dfd8c92964f250b333d90cba7 , distance: 56c867579493823591aaced92d44cc0c037232be
jackpal/bencode-go currently uses a lot of ressources..
Is it maybe easy to use IncSW/go-bencode instead?
I've tried for a while but couldn't get it into the right format/syntax, to get it to work.
Library | Time | Bytes Allocated | Objects Allocated |
---|---|---|---|
IncSW/go-bencode | 1493 ns/op | 554 B/op | 15 allocs/op |
jackpal/bencode-go | 8497 ns/op | 2289 B/op | 66 allocs/op |
Library | Time | Bytes Allocated | Objects Allocated |
---|---|---|---|
IncSW/go-bencode | 3151 ns/op | 1360 B/op | 46 allocs/op |
jackpal/bencode-go | 6850 ns/op | 3073 B/op | 102 allocs/op |
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x4 pc=0x41059d]
goroutine 28 [running]:
github.com/nictuku/dht.(_peerContactsSet).put(0xc20030b230, 0xc2010e7dc0, 0x6, 0xc20030b230)
/home/nictuku/src/github.com/nictuku/dht/peer_store.go:42 +0xaf
github.com/nictuku/dht.(_peerStore).addContact(0xc2002e59b0, 0xc201309b20, 0x14, 0xc2010e7dc0, 0x6, ...)
/home/nictuku/src/github.com/nictuku/dht/peer_store.go:121 +0xa6
github.com/nictuku/dht.(_DHT).replyAnnouncePeer(0xc2000f6380, 0xc20173a7b0, 0xc20117cf50, 0x8, 0xc2010e7cd0, ...)
/home/nictuku/src/github.com/nictuku/dht/dht.go:484 +0x2cf
github.com/nictuku/dht.(_DHT).processPacket(0xc2000f6380, 0xc2008f0000, 0x86, 0x1000, 0xc20173a7b0, ...)
/home/nictuku/src/github.com/nictuku/dht/dht.go:389 +0x12b7
github.com/nictuku/dht.(*DHT).DoDHT(0xc2000f6380)
/home/nictuku/src/github.com/nictuku/dht/dht.go:253 +0xa91
I wanted to test a very simple IPv4 DHT. I took 2 ubuntu 14.04 boxes with go-1.3.1 and said go get github.com/nictuku/dht. Lets call them left (192.168.1.2), and right (192.168.1.3). I hard coded both to port 8444. On left/192.168.1.2:
Port: 8444, // 0 Picks a random port.
DHTRouters: "192.168.1.3:8444",
On right/192.168.1.3:
Port: 8444, // Picks a random port.
DHTRouters: "192.168.1.2:8444",
If passed in the same infohash I expected them to find each other, and then accept each other as peers. I ran both copies with:
$ go run main.go -log_dir="log" -v=6 12b9b08b325e877d08cc63a75e8fd24699c3dc6b
In the log left did ok:
I1008 01:46:31.709372 29590 dht.go:233] DHT: torrent client asking more peers for 12b9b08b325e877d08cc63a75e8fd24699c3dc6b.
I1008 01:46:31.709727 29590 dht.go:572] DHT: ping => {IP:192.168.1.3 Port:8444 Zone:}
I1008 01:46:31.709739 29590 krpc.go:92] newQuery for , lastID 1
I1008 01:46:31.709743 29590 krpc.go:95] ... new id 2
I1008 01:46:31.709798 29590 dht.go:326] DHT: Starting DHT node 4fc01e6d67478cb3b959b50c66b87b6ee11a9dbd on port 8444.
I1008 01:46:31.710378 29590 dht.go:445] DHT processing packet from 192.168.1.3:8444
I1008 01:46:31.710404 29590 dht.go:465] DHT processing response from 7e6738648a6d2153d779c4b52924c407b3c6bf87
I1008 01:46:31.710413 29590 dht.go:495] DHT: Received reply to ping
I1008 01:46:31.710419 29590 routing_table.go:276] New neighbor added to neighborhood with proximity 2
Right took longer but:
I1008 01:46:25.598368 23507 dht.go:188] Using a new random node ID: 7e6738648a6d2153d779c4b52924c407b3c6bf87 20
I1008 01:46:25.599059 23507 dht.go:233] DHT: torrent client asking more peers for 12b9b08b325e877d08cc63a75e8fd24699c3dc6b.
I1008 01:46:25.599278 23507 dht.go:572] DHT: ping => {IP:192.168.1.2 Port:8444 Zone:}
I1008 01:46:25.599320 23507 krpc.go:92] newQuery for , lastID 1
I1008 01:46:25.599330 23507 krpc.go:95] ... new id 2
I1008 01:46:25.599408 23507 dht.go:326] DHT: Starting DHT node 7e6738648a6d2153d779c4b52924c407b3c6bf87 on port 8444.
...
I1008 02:01:25.647747 23507 dht.go:445] DHT processing packet from 192.168.1.2:8444
I1008 02:01:25.647780 23507 dht.go:465] DHT processing response from 4fc01e6d67478cb3b959b50c66b87b6ee11a9dbd
I1008 02:01:25.647798 23507 dht.go:495] DHT: Received reply to ping
I1008 02:01:25.647809 23507 routing_table.go:276] New neighbor added to neighborhood with proximity 2
I1008 02:01:25.647818 23507 routing.go:223] wasContactedRecently for ih=7e6738648a6d2153d779c4b52924c407b3c6bf87 in node 4fc01e6d67478cb3b959b50c66b87b6ee11a9dbd@{192.168.1.2 8444 } returned false
So there's connectivity (and no firewalls involved) between left and right, they are exchanging UDP packets, and they have accepted each other as neighbors.
However they never accept each other as peers for the same infohash. So no match on stdout, and while totalNodes and totalNodesReached sits at 1, totalPeers stays at zero.
Is this too simple of a DHT (just 2 nodes)? Am I misunderstanding something?
My understanding of get_peers is that you look in your routing table for the host closest to the info_hash desired and send out the queries. Said host returns either A) peers for that infohash or B) peers closer to the infohash. Each time we get closer peers the difference between them and the infohash should be less.
So I start a DHT and let it settle:
[11/17/12 10:26:33] [INFO] DHT: Starting DHT node d5d4ff2c3c14850625af007a0ab8b79feac1863a.
Normal establishing of the DHT, totalNodes=400, reachablenodes=129.
Then we do a get Peers:
[11/17/12 10:38:10] [INFO] querying for infoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a
[11/17/12 10:38:10] [WARN] DHT: torrent client asking more peers for 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a. Calling getPeers()
So we should be looking for hosts with a NodeID close to 2015...
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 251695e4558ae09beaad8dfdcd616f132a0e8d66 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 05037e3fdfe49e06cafb9e9cf3dc94fa896e262c
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 2a5a613ed83277f674f47de80d076b5291b4e22d , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 0a4f8ae5525c096b54a26e8933ba90bb32d44967
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 016fa3c0b2ac375a152a0c32cb946e712488d2c5 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 217a481b38c249c7357c1f53f529959887e8798f
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 060e0faa2f13c486ef191896dd326b09818f982f , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 261be471a57dba1bcf4f0bf7e38f90e022ef3365
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 091c00b6886c41c9906d464eefdad831795b7ec6 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 2909eb6d02023f54b03b552fd16723d8da3bd58c
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 127f5e05a4be28d0378829abf63c717047aa43bf , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 326ab5de2ed0564d17de3acac8818a99e4cae8f5
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 1788fda3fe4b66e7bdff4d0eb1b8024c6fe89912 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 379d16787425187a9da95e6f8f05f9a5cc883258
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 18b3a9a4a34b5d9eda83200a3abbe706b3b3bb42 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 38a6427f29252303fad5336b04061cef10d31008
There is a host "251695e4558ae09beaad8dfdcd616f132a0e8d66" which is pretty close, only "05037e3fdfe49e06cafb9e9cf3dc94fa896e262c" away.
But it fails to converge:
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 21e11cea491b0323df20386e56975ff18f59c94b , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 01f4f731c3757dbeff762b0f682aa4182c396201
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 481938abb30a841d86af884c5e71173f2943661f , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 680cd3703964fa80a6f99b2d60ccecd68a23cd55
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 4805fe36160cd91b48132b2f2f3a67aa70a0fec8 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 681015ed9c62a7866845384e11879c43d3c05582
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 4807fb3c65b1370471cf8fdcceb6931c6d0f798d , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 681210e7efdf499951999cbdf00b68f5ce6fd2c7
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 48348291edf47e3483f27b8ebcb04e36a68d23b4 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 6821694a679a00a9a3a468ef820db5df05ed88fe
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 48340685e2ea8ffba7418fcf0cd6a58c89570ef8 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 6821ed5e6884f16687179cae326b5e652a37a5b2
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 483667cc5cfb711617aad876f27a95c3ec562c97 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 68238c17d6950f8b37fccb17ccc76e2a4f3687dd
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 48365ef72d4d339eb95c194a9582df9aaeaa87ca , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 6823b52ca7234d03990a0a2bab3f24730dca2c80
Still not converging:
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 3b7f8394e54265b33f84749ee3be255a98f98f4e , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 1b6a684f6f2c1b2e1fd267ffdd03deb33b992404
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 487da26e4f402728c39954ff74e12509fdc71f9e , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 686849b5c52e59b5e3cf479e4a5cdee05ea7b4d4
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 487d844f83e86adf326e3ae29d8a2b04edb3fd50 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 68686f940986144212382983a337d0ed4ed3561a
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 487d99965802183012cfd3d7bec3f88b556139b2 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 6868724dd26c66ad3299c0b6807e0362f60192f8
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 487d96828f24e435db79c5b0830e66ef36d7aece , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 68687d59054a9aa8fb2fd6d1bdb39d0695b70584
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 487d7f0585c202cd7844a993351941bf197a34e0 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 686894de0fac7c505812baf20ba4ba56ba1a9faa
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 487d539474f9fd2d98e0762999e51d36f05d9c90 , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 6868b84ffe9783b0b8b66548a758e6df533d37da
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: 487d206f9b133ddc225d1d571f4e0547892e376d , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a , distance: 6868cbb4117d4341020b0e3621f3feae2a4e9c27
Over 3000 get_peers are sent.
Including some pretty ridiculously far peers from 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a:
[11/17/12 10:38:10] [TRAC] DHT sending get_peers. nodeID: fe9408d54927f07bf9d458ebb717d45f6c180c2f , InfoHash: 2015ebdb8a6e7e9d205613613ebdfbe9a360ab4a
The pseudo code should be more like:
That does not seem to be what is happening. Distance between NodeID and Infohash should steadily decrease. Each iteration of the loop should get you a factor of 2 closer to your goal.
thanks~
How to use this lib to search and download files, any example?
I believe there are only two races: one in the call to ping(), another in the call to reachableNodes().
WARNING: DATA RACE
Read by goroutine 9:
_/Users/yves/go/src/github.com/nictuku/dht.(_routingTable).hostPortToNode()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:52 +0x218
_/Users/yves/go/src/github.com/nictuku/dht.(_routingTable).getOrCreateNode()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:121 +0x75
_/Users/yves/go/src/github.com/nictuku/dht.(_DHT).ping()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:404 +0x85
_/Users/yves/go/src/github.com/nictuku/dht.(_DHT).DoDHT()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:200 +0x1c6
Previous write by goroutine 5:
_/Users/yves/go/src/github.com/nictuku/dht.(_routingTable).insert()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:108 +0x16c
_/Users/yves/go/src/github.com/nictuku/dht.(_routingTable).getOrCreateNode()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:144 +0x40f
_/Users/yves/go/src/github.com/nictuku/dht.(*DHT).ping()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:404 +0x85
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:81 +0x1097
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
Goroutine 9 (running) created at:
_/Users/yves/go/src/github.com/nictuku/dht.startDHTNode()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:64 +0x150
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:71 +0x43
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
Goroutine 5 (running) created at:
testing.RunTests()
/Users/yves/go/src/pkg/testing/testing.go:377 +0xaec
testing.Main()
/Users/yves/go/src/pkg/testing/testing.go:313 +0xcd
main.main()
_/Users/yves/go/src/github.com/nictuku/dht/_test/_testmain.go:61 +0xda
runtime.main()
/Users/yves/go/src/pkg/runtime/proc.c:248 +0x91
WARNING: DATA RACE
Read by goroutine 5:
_/Users/yves/go/src/github.com/nictuku/dht.(*routingTable).reachableNodes()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:67 +0x21a
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:87 +0x2db
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
Previous write by goroutine 9:
_/Users/yves/go/src/github.com/nictuku/dht.(_routingTable).getOrCreateNode()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:142 +0x24c
_/Users/yves/go/src/github.com/nictuku/dht.(_DHT).ping()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:404 +0x85
_/Users/yves/go/src/github.com/nictuku/dht.(*DHT).DoDHT()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:200 +0x1c6
Goroutine 5 (running) created at:
testing.RunTests()
/Users/yves/go/src/pkg/testing/testing.go:377 +0xaec
testing.Main()
/Users/yves/go/src/pkg/testing/testing.go:313 +0xcd
main.main()
_/Users/yves/go/src/github.com/nictuku/dht/_test/_testmain.go:61 +0xda
runtime.main()
/Users/yves/go/src/pkg/runtime/proc.c:248 +0x91
Goroutine 9 (running) created at:
_/Users/yves/go/src/github.com/nictuku/dht.startDHTNode()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:64 +0x150
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:71 +0x43
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
WARNING: DATA RACE
Read by goroutine 5:
_/Users/yves/go/src/github.com/nictuku/dht.(*routingTable).reachableNodes()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:67 +0x21a
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:87 +0x2db
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
Previous write by goroutine 9:
Goroutine 5 (running) created at:
testing.RunTests()
/Users/yves/go/src/pkg/testing/testing.go:377 +0xaec
testing.Main()
/Users/yves/go/src/pkg/testing/testing.go:313 +0xcd
main.main()
_/Users/yves/go/src/github.com/nictuku/dht/_test/_testmain.go:61 +0xda
runtime.main()
/Users/yves/go/src/pkg/runtime/proc.c:248 +0x91
Goroutine 9 (running) created at:
_/Users/yves/go/src/github.com/nictuku/dht.startDHTNode()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:64 +0x150
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:71 +0x43
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
WARNING: DATA RACE
Read by goroutine 5:
_/Users/yves/go/src/github.com/nictuku/dht.(*routingTable).reachableNodes()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:68 +0x244
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:87 +0x2db
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
Previous write by goroutine 9:
Goroutine 5 (running) created at:
testing.RunTests()
/Users/yves/go/src/pkg/testing/testing.go:377 +0xaec
testing.Main()
/Users/yves/go/src/pkg/testing/testing.go:313 +0xcd
main.main()
_/Users/yves/go/src/github.com/nictuku/dht/_test/_testmain.go:61 +0xda
runtime.main()
/Users/yves/go/src/pkg/runtime/proc.c:248 +0x91
Goroutine 9 (running) created at:
_/Users/yves/go/src/github.com/nictuku/dht.startDHTNode()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:64 +0x150
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:71 +0x43
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
WARNING: DATA RACE
Read by goroutine 5:
_/Users/yves/go/src/github.com/nictuku/dht.(*routingTable).reachableNodes()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:67 +0x21a
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:87 +0x2db
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
Previous write by goroutine 9:
_/Users/yves/go/src/github.com/nictuku/dht.(_routingTable).getOrCreateNode()
/Users/yves/go/src/github.com/nictuku/dht/routing_table.go:142 +0x24c
_/Users/yves/go/src/github.com/nictuku/dht.(_DHT).processFindNodeResults()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:672 +0x54a
_/Users/yves/go/src/github.com/nictuku/dht.(_DHT).processPacket()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:363 +0xad1
_/Users/yves/go/src/github.com/nictuku/dht.(_DHT).DoDHT()
/Users/yves/go/src/github.com/nictuku/dht/dht.go:244 +0x84b
Goroutine 5 (running) created at:
testing.RunTests()
/Users/yves/go/src/pkg/testing/testing.go:377 +0xaec
testing.Main()
/Users/yves/go/src/pkg/testing/testing.go:313 +0xcd
main.main()
_/Users/yves/go/src/github.com/nictuku/dht/_test/_testmain.go:61 +0xda
runtime.main()
/Users/yves/go/src/pkg/runtime/proc.c:248 +0x91
Goroutine 9 (running) created at:
_/Users/yves/go/src/github.com/nictuku/dht.startDHTNode()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:64 +0x150
_/Users/yves/go/src/github.com/nictuku/dht.TestDHTLarge()
/Users/yves/go/src/github.com/nictuku/dht/dht_test.go:71 +0x43
testing.tRunner()
/Users/yves/go/src/pkg/testing/testing.go:301 +0xe8
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x53c3eb]
goroutine 26 [running]:
runtime.panic(0x74dfe0, 0x9708b3)
/usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
github.com/nictuku/dht.(*DHT).replyAnnouncePeer(0xc208003560, 0x0, 0xc208107d88, 0x4, 0xc208107e8a, 0x1, 0xc208107d50, 0xd, 0x0, 0x0, ...)
/home/nictuku/src/github.com/nictuku/dht/dht.go:659 +0x59b
github.com/nictuku/dht.(*DHT).processPacket(0xc208003560, 0xc2080b0000, 0xea, 0x1000, 0xc20811b408, 0x4, 0x4, 0xceba, 0x0, 0x0)
/home/nictuku/src/github.com/nictuku/dht/dht.go:553 +0x1843
github.com/nictuku/dht.(*DHT).Run(0xc208003560, 0x0, 0x0)
/home/nictuku/src/github.com/nictuku/dht/dht.go:385 +0xca4
created by github.com/jackpal/Taipei-Torrent/torrent.NewTorrentSession
/home/nictuku/src/github.com/jackpal/Taipei-Torrent/torrent/torrent.go:172 +0x510
goroutine 16 [select]:
github.com/jackpal/Taipei-Torrent/torrent.RunTorrents(0xc208042680, 0xc2080040b0, 0x1, 0x1, 0x0, 0x0)
/home/nictuku/src/github.com/jackpal/Taipei-Torrent/torrent/torrentLoop.go:67 +0xea7
main.main()
/home/nictuku/src/github.com/jackpal/Taipei-Torrent/main.go:111 +0x737
Summary of the changes so far:
I have a tarball of some partially working code here. It's the repository + my files. It really is a work in progress -- nowhere near ready for integration right now. Some of the code is likely incorrect; I explain why below.
I've tested libtorrent against my code, and using libtorrent's standalone dht_put
program, I can both put and get immutable data from my modified DHT code. Here's what I did:
I started dht/examples/router
on a server that's reachable from the internet. It's a small program that starts a DHT on port 9882, does not announce itself with the public routers, and waits forever for connections. I started the router with ./router -v=5 -logtostederr=true
so I could see all the activity.
I downloaded and unpacked libtorrent-rasterbar-1.0.1, and added dht_put.cpp to the tools directory. I modified the file to make it use only my router node. To compile it, you can either modify tools/Makefile.am
to add a build target for dht_put
(you'll need automake 1.14
installed) or compile it manually.
After compiling dht_put
, type ./dht_put put "hello there"
. It should talk to the router, and do a get
followed by a put
(you'll see that in the router's output). It'll print out the SHA-1 hash for the string 11:hello there
, and you'll see the router store the value hello there. Next, if you try ./dht_put get <the hash>
, it should talk to the router and return the string hello there. If you give it a different hash, it won't be able to fetch anything.
One thing that I didn't pay attention to carefully is the argument for put
as described in the spec. You have to give it a valid object that can be bencoded -- a string, an integer, a list, or a dictionary. The code on both sides (the sending node and the storage node) will bencode the object before calculating the SHA-1 hash.
I'm sort of aiming for the same public UI for the DHT Get
and Put
methods: GET
takes an infohash, and PUT
takes a bencodable object (maybe as a string?).
One thing I haven't had much success with is using the DHT's methods to actually get/put stuff. I wrote a small amount of code (not in the tarball) to operate the same way as dht_put
, but it seems to spin after it receives the string to be sent out over the network, somewhere in the put
method in getput.go
.
A problem I have is that I haven't looked at the client code (Taipei) yet, so I don't have a good idea on how to integrate things properly. I mean to work on this today (Thursday), but stuff came up at home, and I've been busy.
I am using the library in a torrent client. When a torrent is removed from the client, I would also like to remove the info hash from DHT node. Currently, there isn't any method for this. I can add one if you are okay with it. Would you like to see a PR?
// Read from UDP socket, writes slice of byte into channel.
func readFromSocket(socket *net.UDPConn, conChan chan packetType, bytesArena arena, stop chan bool, log DebugLogger) {
for {
b := bytesArena.Pop()
n, addr, err := socket.ReadFromUDP(b)
if err != nil {
log.Debugf("DHT: readResponse error:%s\n", err)
}
b = b[0:n]
if n == maxUDPPacketSize {
log.Debugf("DHT: Warning. Received packet with len >= %d, some data may have been discarded.\n", maxUDPPacketSize)
}
totalReadBytes.Add(int64(n))
if n > 0 && err == nil {
p := packetType{b, *addr}
select {
case conChan <- p:
continue
case <-stop:
return
}
}
// Do a non-blocking read of the stop channel and stop this goroutine if the channel
// has been closed.
select {
case <-stop:
return
default:
}
}
}
If I get that right you do a bytesArena.Pop() to get a pre-allocated buffer. but in case of a 0 byte package or an error you never return that buffer back, since that happens only for packets in conChan aka socketChan (dht.go:499).
my dht client recently began to randomly stopping to receiving/process any incoming packets until I restart.. so I began digging.. and that might be the reason?
I have a torrent client that serves each torrent on a seperate TCP port. I need to specify port in announce_peer
query. Current PeersRequest
method does not take any port argument and always use Config.Port
. @nictuku can I add another method like:
func (d *DHT) PeersRequestPort(ih string, announce bool, port int)
Annoyingly many peers will claim they are peers for any requested infohash. Some way to black list them would be useful. Two potential strategies:
This should run TestDHTLarge, I updated to the current version just minuts ago?
$ go test
It seems to not complete and expire with a timer. The output should end with:
=== Stats ===
totalReachableNodes:
totalDupes:
totalPeers:
totalSentGetPeers:
Or maybe I misunderstand. Maybe I need to adjust the timers? I'm on a fast machine with a fairly fast network connection (10mbit) without any firewall. I see a fair bit of output, but it doesn't seem to exist normally:
[11/09/12 10:01:41] [TRAC] DHT: Got new node reference: [email protected]:49001 from [email protected]:49001. Distance: d749f235cdd12aa4a3cda5625c8d3887285fbd49.
[11/09/12 10:01:41] [TRAC] DHT sending get_peers. nodeID: aa9d7b2d164d65ea74588378ab7d898d93dfbbeb , InfoHash: b462c0a8bcef1ce5bb56b9fdb8cf37ffd02f5f59 , distance: 1effbb85aaa2790fcf0e3a8513b2be7243f0e4b2
[11/09/12 10:01:41] [TRAC] DHT: Got new node reference: [email protected]:27977 from [email protected]:49001. Distance: d749f235cdd12aa4a3cda5625c8d3887285fbd49.
[11/09/12 10:01:41] [TRAC] DHT sending get_peers. nodeID: d78756c13f577d504599054ee1ee218a2b37d88d , InfoHash: b462c0a8bcef1ce5bb56b9fdb8cf37ffd02f5f59 , distance: 63e5966983b861b5fecfbcb359211675fb1887d4
[11/09/12 10:01:46] [WARN] DHT: torrent client asking more peers for d1c5676ae7ac98e8b19f63565905105e3c4c37a2. Calling getPeers().
PASS
ok _/home/bill/tmp/git/dht 9.062s
$
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.