freeway

package module
v0.0.0-...-0c76441 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2014 License: MIT Imports: 17 Imported by: 0

README

#Freeway

Freeway is a partial implementation of the distributed hash table that powers the BitTorrent network.

About

Most queries and replies defined in the KRPC protocol are implemented.

This project was an experiment and is unlikely to be maintained. The code provided should not be used in any serious project.

Example

package main

import (
    "log"

    "github.com/mohamedattahri/freeway"
)

const port int = 6881

func main() {
    dht, err := freeway.NewDHT(freeway.NewRandomID(), port)
    if err != nil {
        log.Fatal(err)
    }

    if err := dht.Start(); err != nil {
        log.Fatal(err)
    }

    //Bootstrap
    bittorrent, _ := freeway.NewPeerFromIP(dht, "router.bittorrent.com", 6881, freeway.NewRandomID())
    transmission, _ := freeway.NewPeerFromIP(dht, "dht.transmissionbt.com", 6881, freeway.NewRandomID())
    magnets, _ := freeway.NewPeerFromIP(dht, "1.a.magnets.im", 6881, freeway.NewRandomID())
    utorrent, _ := freeway.NewPeerFromIP(dht, "router.utorrent.com", 6881, freeway.NewRandomID())
    dht.Bootstrap([]*freeway.Peer{bittorrent, utorrent, transmission, magnets})

    log.Println("This machine is now known as", dht.LocalPeer())
    <-make(chan int)
}

Documentation

Index

Constants

View Source
const (
	// Alpha represents the redundancy factor used in the DHT.
	Alpha int = 3
	// K represents the maximum capacity of a Bucket
	K int = 20
	// KeySize for a typical node ID (bits)
	KeySize int = 160
	// Freshness represents the minutes during which a node is considered fresh.
	Freshness time.Duration = 10 * time.Minute
	// Timeout delay for requests. 80% of peers should reply within 20%.
	Timeout time.Duration = 20 * time.Second
)
View Source
const (
	CompactNodeInfoLength = IDLength + 6
)
View Source
const (
	// IDLength in bytes
	IDLength int = (KeySize / 8)
)

Variables

View Source
var ErrBucketMustSplit = errors.New("bucket is full and must be split")

ErrBucketMustSplit is the error returned by a bucket when it's full and needs a split.

Functions

func PeerCompactNodeInfo

func PeerCompactNodeInfo(addr *net.UDPAddr, id ID) []byte

Types

type Bucket

type Bucket struct {
	// contains filtered or unexported fields
}

A Bucket is a collection of nodes grouped by their distance from the local peer's ID. The index int here is a reference to the precision-bit at which the nodes it contains are considered as "close" to the local peer.

func NewBucket

func NewBucket(set *BucketSet, index int) (instance *Bucket)

NewBucket returns an instance of the Bucket struct and ties it to the parent bucket set. The index int refers to the Kademlia kBucket index that will assigned to the newly created instance.

func (*Bucket) Len

func (bucket *Bucket) Len() int

Len returns the number of peers currently in the bucket

func (*Bucket) PeerSlice

func (bucket *Bucket) PeerSlice(from, length int) []*Peer

PeerSlice returns a slice of the nodes contained in the bucket with no risk of index over-flow.

func (*Bucket) Peers

func (bucket *Bucket) Peers() []*Peer

Peers simply returns the list of peers stored in the current bucket

type BucketSet

type BucketSet struct {
	// contains filtered or unexported fields
}

A BucketSet is the basis of the Kademlia routing table. It represents a binary tree of kBuckets structured to cover the entire range of the KeySize space.

func NewBucketSet

func NewBucketSet(dht *DHT) (instance *BucketSet)

NewBucketSet returns a new instance of the BucketSet struct, and ties it to a DHT instance. The local Peer will automatically be inserted.

func (*BucketSet) ClosestPeersFrom

func (set *BucketSet) ClosestPeersFrom(key ID) (nodes []*Peer)

ClosestPeersFrom returns the Alpha peers which are the closest to a given key

func (*BucketSet) Contains

func (set *BucketSet) Contains(id ID) (exists bool)

Contains returns a value indicating whether the bucket set contains a peer with a given HEX value.

func (*BucketSet) Insert

func (set *BucketSet) Insert(peer *Peer)

Insert attempts to insert a Peer instance in the right kBucket. If the Bucket is full and requests splitting, the method will proceed and and make another attempt.

func (*BucketSet) InsertRange

func (set *BucketSet) InsertRange(peers []*Peer)

InsertRange is a handy method to insert more than one peer a time.

func (*BucketSet) Len

func (set *BucketSet) Len() (length int)

Len returns the number of peers stored in the bucket set.

func (*BucketSet) Peer

func (set *BucketSet) Peer(id ID) *Peer

Peer returns a peer stored in the bucket set using its HEX value.

type DHT

type DHT struct {
	// contains filtered or unexported fields
}

DHT represents a Kadmelia-inspired Distributed Hash Table.

func NewDHT

func NewDHT(id ID, port int) (instance *DHT, err error)

NewDHT returns a DHT operating on UDP address:port

func (*DHT) Bootstrap

func (dht *DHT) Bootstrap(peers []*Peer) error

Bootstrap the node in the DHT by contacting peers.

func (*DHT) FindNode

func (dht *DHT) FindNode(key ID, completed chan *Peer)

FindNode uses the FIND_NODE-RPC lookup method

func (*DHT) LocalPeer

func (dht *DHT) LocalPeer() *Peer

LocalPeer representing the identity of the current peer on the network.

func (*DHT) Start

func (dht *DHT) Start() error

Start boostraps the DHT and connects it to the network using UDP address:port. No need to call this method if you used NewDHT.

type FindNodeResponse

type FindNodeResponse struct {
	Source *Peer
	Peers  []*Peer
}

Structure of a FindNode RPC-reply.

type ID

type ID [IDLength]byte

ID represents a node ID.

func NewID

func NewID(data []byte) (id ID, err error)

NewID creates and returns a Node ID from an hex representation of a ID.

func NewRandomID

func NewRandomID() (id ID)

NewRandomID generates and returns a random Node ID

func (ID) BucketIndex

func (id ID) BucketIndex(root ID, limit int) int

BucketIndex returns the index of the kBucket where the ID is located or should be inserted. It's determined using the formula index = Log2(distance) where d is the distance

func (ID) Bytes

func (id ID) Bytes() []byte

Bytes return a byte array representation of the ID.

func (ID) Distance

func (id ID) Distance(other ID) (result ID)

Distance returns the distance between two nodes

func (ID) Equals

func (id ID) Equals(other ID) bool

Equals compares two IDs and returns a value indicating whether they are equal or not.

func (ID) GreaterThan

func (id ID) GreaterThan(other ID) bool

GreaterThan compares two IDs and returns a value indicating whether an ID is greater than another

func (ID) Hex

func (id ID) Hex() string

Hex returns a hex string representation of the ID

func (ID) Int

func (id ID) Int() *big.Int

Int converts the byte array to an integer

func (ID) LesserThan

func (id ID) LesserThan(other ID) bool

LesserThan compares two IDs and returns a value indicating whether an ID is lesser than another.

func (ID) String

func (id ID) String() string

String returns a string with the hex representation of the ID

type IDArray

type IDArray []ID

IDArray is a simple type aliasing to refer to an array of IDs.

func (IDArray) Contains

func (items IDArray) Contains(id ID) bool

Contains returns true if the id is in the array.

func (IDArray) Len

func (items IDArray) Len() int

func (IDArray) Less

func (items IDArray) Less(a, b int) bool

func (IDArray) Sort

func (items IDArray) Sort()

Sort the array by ID value

func (IDArray) Swap

func (items IDArray) Swap(a, b int)

type IncomingQueryPacket

type IncomingQueryPacket struct {
	QueryPacket // Anonymous field
	Source      *net.UDPAddr
}

type IncomingReplyPacket

type IncomingReplyPacket struct {
	ReplyPacket
	Source *net.UDPAddr
}

type KRPC

type KRPC struct {
	// contains filtered or unexported fields
}

KRPC server listening on UDP

func NewKRPC

func NewKRPC(port int) (*KRPC, error)

NewKRPC returns a new KRPC server

func (*KRPC) Addr

func (krpc *KRPC) Addr() *net.UDPAddr

Address on which the server is listening

func (*KRPC) Listening

func (krpc *KRPC) Listening() bool

Listening returns a value indicating whether the server is running

func (*KRPC) Reply

func (krpc *KRPC) Reply(resp *Response) (err error)

Reply sends a reponse to a query that was processed.

func (*KRPC) Send

func (krpc *KRPC) Send(req *Request) (err error)

Send a request after bencoding its message

func (*KRPC) Start

func (krpc *KRPC) Start(incomingQueries chan *IncomingQueryPacket) (err error)

Start listening on the network.

func (*KRPC) Stop

func (krpc *KRPC) Stop()

Stop listening

type Peer

type Peer struct {
	// contains filtered or unexported fields
}

A peer is a contact on the network.

func NewPeer

func NewPeer(dht *DHT, addr *net.UDPAddr, id ID) *Peer

func NewPeerFromAddr

func NewPeerFromAddr(dht *DHT, addr *net.UDPAddr, id ID) (*Peer, error)

NewPeerFromAddr creates a new peer from a UDP address

func NewPeerFromCompactAddressPort

func NewPeerFromCompactAddressPort(dht *DHT, info []byte) (*Peer, error)

NewPeerFromCompactAddressPort creates a new peer from a KRPC compact address format. Contact information for peers is encoded as a 6-byte string. Also known as "Compact IP-address/port info" the 4-byte IP address is in network byte order with the 2 byte port in network byte order concatenated onto the end.

func NewPeerFromCompactNodeInfo

func NewPeerFromCompactNodeInfo(dht *DHT, info []byte) (*Peer, error)

Contact information for nodes is encoded as a 26-byte string. Also known as "Compact node info" the 20-byte Node ID in network byte order has the compact IP-address/port info concatenated to the end.

func NewPeerFromIP

func NewPeerFromIP(dht *DHT, ip string, port int, id ID) (*Peer, error)

NewPeerFromIP creates a new peer from an ip and port

func (*Peer) Addr

func (peer *Peer) Addr() *net.UDPAddr

Host on which the peer can be contacted.

func (*Peer) BucketIndex

func (peer *Peer) BucketIndex(limit int) int

BucketIndex returns the index of the kBucket where the ID is located or should be inserted. It's determined using the formula i = Log2(d) where d is the distance and i is the index we're looking for.

func (*Peer) CompactNodeInfo

func (peer *Peer) CompactNodeInfo() []byte

Returns a CompactNodeInfo representation

func (*Peer) DHT

func (peer *Peer) DHT() *DHT

DHT to which this Peer is attached

func (*Peer) DistanceFrom

func (peer *Peer) DistanceFrom(other *Peer) ID

The distance represented as an ID between this Peer and another.

func (*Peer) DistanceFromRoot

func (peer *Peer) DistanceFromRoot() ID

func (*Peer) Equals

func (peer *Peer) Equals(other *Peer) bool

func (*Peer) FindNode

func (peer *Peer) FindNode(key ID, closestPeers chan *FindNodeResponse)

Sends a find_node RPC request to the current Peer

func (*Peer) Hex

func (peer *Peer) Hex() string

Returns a unique HEX value for this peer. Most Kademlia implementation will only hash the ID. We chose to include the host and the port to allow multiple nodes to live on the machine.

func (*Peer) ID

func (peer *Peer) ID() ID

ID of the peer

func (*Peer) IsAlive

func (peer *Peer) IsAlive() (bool, bool)

Evaluates the health status of a peer. IsAlive returns two boolean. The first one indicates whether the peer is considered active or not. The second indicates whether the peer is worth to be pinged.

func (*Peer) Ping

func (peer *Peer) Ping()

Send a ping RPC request to the current Peer

func (*Peer) String

func (peer *Peer) String() string

type PeerArray

type PeerArray []*Peer

Simple type aliasing to represent an array of Peers

func (PeerArray) CompactInfo

func (peers PeerArray) CompactInfo() []byte

func (PeerArray) Contains

func (peers PeerArray) Contains(peer *Peer) bool

Returns true if the id is in the array.

func (PeerArray) Len

func (peers PeerArray) Len() int

func (PeerArray) Less

func (peers PeerArray) Less(a, b int) bool

func (PeerArray) Sort

func (peers PeerArray) Sort()

func (PeerArray) Swap

func (peers PeerArray) Swap(a, b int)

type PeerState

type PeerState struct {
	// contains filtered or unexported fields
}

Represents a peer item stored in the Tree Map.

type QueryPacket

type QueryPacket struct {
	Args        map[string]interface{} `bencode:"a"`
	QueryMethod string                 `bencode:"q"`
	PacketType  string                 `bencode:"y"`
	Transaction string                 `bencode:"t"`
}

The content of a KRPC request UDP packet.

func NewFindNodeQuery

func NewFindNodeQuery(queryingNodeID, targetNodeID ID) *QueryPacket

Find node is used to find the contact information for the node with targetNodeID

func NewGetPeersQuery

func NewGetPeersQuery(queryingNodeID, infoHash ID) *QueryPacket

Get peers associated with a torrent infohash

func NewPingQuery

func NewPingQuery(queryingNodeID ID) *QueryPacket

Most basic KRPC query.

func NewQuery

func NewQuery(method string, args map[string]interface{}) (query *QueryPacket)

Returns a message instance fit for a KRPC query.

type ReplyPacket

type ReplyPacket struct {
	NamedReturns map[string]interface{} `bencode:"r"`
	PacketType   string                 `bencode:"y"`
	Transaction  string                 `bencode:"t"`
}

The content of an RPC reponse UDP packet

func NewFindNodeReply

func NewFindNodeReply(transaction string, localPeerID ID, peers []*Peer) *ReplyPacket

func NewPingReply

func NewPingReply(transaction string, localPeerID ID) *ReplyPacket

func NewReplyPacket

func NewReplyPacket(transaction string, args map[string]interface{}) *ReplyPacket

type Request

type Request struct {
	// contains filtered or unexported fields
}

func NewRequest

func NewRequest(dht *DHT, dest *Peer, message *QueryPacket, responseChan chan *IncomingReplyPacket) *Request

func (*Request) TransactionID

func (req *Request) TransactionID() string

type Response

type Response struct {
	// contains filtered or unexported fields
}

func NewResponse

func NewResponse(dht *DHT, dest *Peer, message *ReplyPacket) *Response

type TreeMap

type TreeMap struct {
	// contains filtered or unexported fields
}

A data structure used to keep track of the peers discovered during an ID lookup. Peers discovered are stored and sorted by distance from a given key. PeersCloserThan and UnqueriedPeers are there to feed different rounds of a FIND_NODE-RPC with peers to query.

func NewTreeMap

func NewTreeMap(key ID) *TreeMap

func (*TreeMap) Len

func (tree *TreeMap) Len() int

func (*TreeMap) Less

func (tree *TreeMap) Less(a, b int) bool

func (*TreeMap) Peers

func (tree *TreeMap) Peers() []*Peer

Returns the sorted list of peers stored in the tree.

func (*TreeMap) Sort

func (tree *TreeMap) Sort()

func (*TreeMap) Swap

func (tree *TreeMap) Swap(a, b int)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL