Example #1
0
func (d *DHT) replyAnnouncePeer(addr net.UDPAddr, node *remoteNode, r responseType) {
	ih := InfoHash(r.A.InfoHash)
	if log.V(3) {
		log.Infof("DHT: announce_peer. Host %v, nodeID: %x, infoHash: %x, peerPort %d, distance to me %x",
			addr, r.A.Id, ih, r.A.Port, hashDistance(ih, InfoHash(d.nodeId)),
		)
	}
	// node can be nil if, for example, the server just restarted and received an announce_peer
	// from a node it doesn't yet know about.
	if node != nil && d.checkToken(addr, r.A.Token) {
		peerAddr := net.TCPAddr{IP: addr.IP, Port: r.A.Port}
		d.peerStore.addContact(ih, nettools.DottedPortToBinary(peerAddr.String()))
		// Allow searching this node immediately, since it's telling us
		// it has an infohash. Enables faster upgrade of other nodes to
		// "peer" of an infohash, if the announcement is valid.
		node.lastResponseTime = time.Now().Add(-searchRetryPeriod)
		if d.peerStore.hasLocalDownload(ih) {
			d.PeersRequestResults <- map[InfoHash][]string{ih: []string{nettools.DottedPortToBinary(peerAddr.String())}}
		}
	}
	// Always reply positively. jech says this is to avoid "back-tracking", not sure what that means.
	reply := replyMessage{
		T: r.T,
		Y: "r",
		R: map[string]interface{}{"id": d.nodeId},
	}
	sendMsg(d.conn, addr, reply)
}
Example #2
0
// The main loop.
// Every minute, we calculate the new pex message and send it to
// everyone. After it's sent, this new pex message becomes the last
// pex message.
//
// A Pex Message has three fields: "added", "addedf" and "dropped".
//
// "added" represents the set of peers we are currently connected to
// that we weren't connected to last time.
//
// "addedf" contains the same peers but instead of their address, it's
// their flags (See the Flag structure for more details)
//
// "dropped" is the set of peers we were connected to last time that
// we aren't currently connected to.
func (t *TorrentSession) StartPex() {
	for _ = range time.Tick(1 * time.Minute) {
		newLastPeers := make([]pexPeer, 0)

		numadded := 0
		added := ""
		addedf := ""

		// TODO randomize to distribute more evenly
		for _, peer := range t.peers.All() {
			newLastPeers = append(newLastPeers, pexPeer{peer.address, peer.id})

			if contains(lastPeers, peer) {
				continue
			}
			added += nettools.DottedPortToBinary(peer.address)

			// We don't manage those yet
			addedf += string(0x00)

			numadded += 1
			if numadded >= MAX_PEERS {
				break
			}
		}

		dropped := ""
		for _, lastPeer := range lastPeers {
			if !t.peers.Know(lastPeer.address, lastPeer.id) {
				dropped += nettools.DottedPortToBinary(lastPeer.address)
			}
		}

		for _, p := range t.peers.All() {
			p.sendExtensionMessage("ut_pex", PexMessage{
				Added:   added,
				AddedF:  addedf,
				Dropped: dropped,
			})
		}

		lastPeers = newLastPeers
	}
}
Example #3
0
func newRemoteNode(addr net.UDPAddr, id string) *remoteNode {
	return &remoteNode{
		address:             addr,
		addressBinaryFormat: nettools.DottedPortToBinary(addr.String()),
		lastQueryID:         newTransactionId(),
		id:                  id,
		reachable:           false,
		pendingQueries:      map[string]*queryType{},
		pastQueries:         map[string]*queryType{},
	}
}
Example #4
0
File: dht.go Project: screscent/dht
func (d *DHT) nodesForInfoHash(ih InfoHash) string {
	n := make([]string, 0, kNodes)
	for _, r := range d.routingTable.lookup(ih) {
		// r is nil when the node was filtered.
		if r != nil {
			n = append(n, r.id+nettools.DottedPortToBinary(r.address.String()))
		}
	}
	l4g.Trace("replyGetPeers: Nodes only. Giving %d", len(n))
	return strings.Join(n, "")
}
Example #5
0
func (d *DHT) nodesForInfoHash(ih InfoHash) string {
	n := make([]string, 0, kNodes)
	for _, r := range d.routingTable.lookup(ih) {
		// r is nil when the node was filtered.
		if r != nil {
			binaryHost := r.id + nettools.DottedPortToBinary(r.address.String())
			if binaryHost == "" {
				log.V(3).Infof("killing node with bogus address %v", r.address.String())
				d.routingTable.kill(r, d.peerStore)
			} else {
				n = append(n, binaryHost)
			}
		}
	}
	log.V(3).Infof("replyGetPeers: Nodes only. Giving %d", len(n))
	return strings.Join(n, "")
}
Example #6
0
File: dht.go Project: screscent/dht
func (d *DHT) replyAnnouncePeer(addr *net.UDPAddr, r responseType) {
	l4g.Trace(func() string {
		ih := InfoHash(r.A.InfoHash)
		return fmt.Sprintf("DHT: announce_peer. Host %v, nodeID: %x, infoHash: %x, peerPort %d, distance to me %x",
			addr, r.A.Id, ih, r.A.Port, hashDistance(ih, InfoHash(d.nodeId)),
		)
	})
	peerAddr := net.TCPAddr{IP: addr.IP, Port: r.A.Port}
	d.peerStore.addContact(InfoHash(r.A.InfoHash), nettools.DottedPortToBinary(peerAddr.String()))
	// Always reply positively. jech says this is to avoid "back-tracking", not sure what that means.
	reply := replyMessage{
		T: r.T,
		Y: "r",
		R: map[string]interface{}{"id": d.nodeId},
	}
	sendMsg(d.conn, addr, reply)
}
Example #7
0
File: dht.go Project: hlandauf/dht
func (d *DHT) replyAnnouncePeer(node *remoteNode, r responseType) {
	addr := node.address
	ih := InfoHash(r.A.InfoHash)
	if log.V(3) {
		log.Infof("DHT: announce_peer. Host %v, nodeID: %x, infoHash: %x, peerPort %d, distance to me %x",
			addr, r.A.Id, ih, r.A.Port, hashDistance(ih, InfoHash(d.nodeId)),
		)
	}
	if d.checkToken(addr, r.A.Token) {
		peerAddr := net.TCPAddr{IP: addr.IP, Port: r.A.Port}
		d.peerStore.addContact(ih, nettools.DottedPortToBinary(peerAddr.String()))
		// Allow searching this node immediately, since it's telling us
		// it has an infohash. Enables faster upgrade of other nodes to
		// "peer" of an infohash, if the announcement is valid.
		node.lastResponseTime = time.Now().Add(-searchRetryPeriod)
	}
	// Always reply positively. jech says this is to avoid "back-tracking", not sure what that means.
	reply := replyMessage{
		T: r.T,
		Y: "r",
		R: map[string]interface{}{"id": d.nodeId},
	}
	d.sendMsg(d.conn, addr, reply)
}