-// Package DHT implements a DHT for use with the BitTorrent protocol,
-// described in BEP 5: http://www.bittorrent.org/beps/bep_0005.html.
-//
-// Standard use involves creating a NewServer, and calling Announce on it with
-// the details of your local torrent client and infohash of interest.
package dht
import (
T string // The KRPC transaction ID.
}
+// A Server defines parameters for a DHT node server that is able to
+// send queries, and respond to the ones from the network.
+// Each node has a globally unique identifier known as the "node ID."
+// Node IDs are chosen at random from the same 160-bit space
+// as BitTorrent infohashes [2] and define the behaviour of the node.
+// Zero valued Server does not have a valid ID and thus
+// is unable to function properly. Use `NewServer(nil)`
+// to initialize a default node.
type Server struct {
id string
socket net.PacketConn
config ServerConfig
}
+// ServerConfig allows to set up a configuration of the `Server` instance
+// to be created with NewServer
type ServerConfig struct {
Addr string // Listen address. Used if Conn is nil.
Conn net.PacketConn
PublicIP net.IP
}
+// ServerStats instance is returned by Server.Stats() and stores Server metrics
type ServerStats struct {
// Count of nodes in the node table that responded to our last query or
// haven't yet been queried.
BadNodes uint
}
-// Returns statistics for the server.
+// Stats returns statistics for the server.
func (s *Server) Stats() (ss ServerStats) {
s.mu.Lock()
defer s.mu.Unlock()
return
}
-// Returns the listen address for the server. Packets arriving to this address
+// Addr returns the listen address for the server. Packets arriving to this address
// are processed by the server (unless aliens are involved).
func (s *Server) Addr() net.Addr {
return s.socket.LocalAddr()
return
}
-// Create a new DHT server.
+// NewServer initializes a new DHT node server.
func NewServer(c *ServerConfig) (s *Server, err error) {
if c == nil {
c = &ServerConfig{}
return true
}
+// Transaction keeps track of a message exchange between nodes,
+// such as a query message and a response message
type Transaction struct {
mu sync.Mutex
remoteAddr dHTAddr
s.transactions[t.key()] = t
}
-// Returns the 20-byte server ID. This is the ID used to communicate with the
+// ID returns the 20-byte server ID. This is the ID used to communicate with the
// DHT network.
func (s *Server) ID() string {
if len(s.id) != 20 {
--- /dev/null
+/*
+ Package dht implements a Distributed Hash Table (DHT) part of
+ the BitTorrent protocol,
+ as specified by BEP 5: http://www.bittorrent.org/beps/bep_0005.html.
+
+ BitTorrent uses a "distributed hash table" (DHT)
+ for storing peer contact information for "trackerless" torrents.
+ In effect, each peer becomes a tracker.
+ The protocol is based on Kademila DHT protocol and is implemented over UDP.
+
+ Please note the terminology used to avoid confusion.
+ A "peer" is a client/server listening on a TCP port that
+ implements the BitTorrent protocol.
+ A "node" is a client/server listening on a UDP port implementing
+ the distributed hash table protocol.
+ The DHT is composed of nodes and stores the location of peers.
+ BitTorrent clients include a DHT node, which is used to contact other nodes
+ in the DHT to get the location of peers to
+ download from using the BitTorrent protocol.
+
+ Standard use involves creating a Server, and calling Announce on it with
+ the details of your local torrent client and infohash of interest.
+*/
+
+package dht
"github.com/anacrolix/torrent/util"
)
-// The unmarshalled KRPC dict message.
+// Msg represents messages that nodes in the network send to each other as specified by the protocol.
+// They are also refered to as the KRPC messages.
+// There are three types of messages: QUERY, RESPONSE, ERROR
+// The message is a dictonary that is then
+// "bencoded" (serialization & compression format adopted by the BitTorrent)
+// and sent via the UDP connection to peers.
+//
+// A KRPC message is a single dictionary with two keys common to every message and additional keys depending on the type of message.
+// Every message has a key "t" with a string value representing a transaction ID.
+// This transaction ID is generated by the querying node and is echoed in the response, so responses
+// may be correlated with multiple queries to the same node. The transaction ID should be encoded as a short string of binary numbers, typically 2 characters are enough as they cover 2^16 outstanding queries. The other key contained in every KRPC message is "y" with a single character value describing the type of message. The value of the "y" key is one of "q" for query, "r" for response, or "e" for error.
+// 3 message types: QUERY, RESPONSE, ERROR
type Msg struct {
- Q string `bencode:"q,omitempty"`
+ Q string `bencode:"q,omitempty"` // method name of the query (on of 4: "ping", "find_node", "get_peers", "announce_peer")
A *struct {
- ID string `bencode:"id"`
- InfoHash string `bencode:"info_hash"`
- Target string `bencode:"target"`
- } `bencode:"a,omitempty"`
- T string `bencode:"t"`
- Y string `bencode:"y"`
- R *Return `bencode:"r,omitempty"`
- E *KRPCError `bencode:"e,omitempty"`
+ ID string `bencode:"id"` // ID of the quirying Node
+ InfoHash string `bencode:"info_hash"` // InfoHash of the torrent
+ Target string `bencode:"target"` // ID of the node sought
+ } `bencode:"a,omitempty"` // named arguments sent with a query
+ T string `bencode:"t"` // required: transaction ID
+ Y string `bencode:"y"` // required: type of the message: q for QUERY, r for RESPONSE, e for ERROR
+ R *Return `bencode:"r,omitempty"` // RESPONSE type only
+ E *KRPCError `bencode:"e,omitempty"` // ERROR type only
}
type Return struct {
- ID string `bencode:"id"`
+ ID string `bencode:"id"` // ID of the querying node
Nodes CompactIPv4NodeInfo `bencode:"nodes,omitempty"`
Token string `bencode:"token"`
Values []util.CompactPeer `bencode:"values,omitempty"`