add license && golint

This commit is contained in:
Lime
2016-08-10 11:27:32 +08:00
parent 4f125f4817
commit ba80173b6a
6 changed files with 165 additions and 136 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Dean Karn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+4 -3
View File
@@ -1,6 +1,5 @@
// Package dht implements the bittorrent dht protocol. For more information
// see http://www.bittorrent.org/beps/bep_0005.html.
package dht
import (
@@ -18,7 +17,9 @@ var (
)
const (
// StandardMode follows the standard protocol
StandardMode = iota
// CrawlMode for crawling the dht network.
CrawlMode
)
@@ -132,7 +133,7 @@ func (dht *DHT) IsStandardMode() bool {
return dht.Mode == StandardMode
}
// IsStandardMode returns whether mode is CrawlMode.
// IsCrawlMode returns whether mode is CrawlMode.
func (dht *DHT) IsCrawlMode() bool {
return dht.Mode == CrawlMode
}
@@ -196,7 +197,7 @@ func (dht *DHT) id(target string) string {
}
// GetPeers returns peers who have announced having infoHash.
func (dht *DHT) GetPeers(infoHash string) ([]*peer, error) {
func (dht *DHT) GetPeers(infoHash string) ([]*Peer, error) {
if !dht.Ready {
return nil, errors.New("dht not ready")
}
+22 -22
View File
@@ -68,11 +68,11 @@ func (tm *tokenManager) token(addr *net.UDPAddr) string {
}
// check returns whether the token is valid.
func (tm *tokenManager) check(addr *net.UDPAddr, token_ string) bool {
func (tm *tokenManager) check(addr *net.UDPAddr, tokenString string) bool {
v, ok := tm.Get(addr.IP.String())
tk, _ := v.(token)
return ok && token_ == tk.data
return ok && tokenString == tk.data
}
// makeQuery returns a query-formed data.
@@ -148,8 +148,8 @@ func newTransactionManager(maxCursor uint64, dht *DHT) *transactionManager {
}
}
// genTransId generates a transaction id and returns it.
func (tm *transactionManager) genTransId() string {
// genTransID generates a transaction id and returns it.
func (tm *transactionManager) genTransID() string {
tm.Lock()
defer tm.Unlock()
@@ -187,8 +187,8 @@ func (tm *transactionManager) insert(trans *transaction) {
}
// delete removes a transaction from transactionManager.
func (tm *transactionManager) delete(transId string) {
v, ok := tm.transactions.Get(transId)
func (tm *transactionManager) delete(transID string) {
v, ok := tm.transactions.Get(transID)
if !ok {
return
}
@@ -224,9 +224,9 @@ func (tm *transactionManager) transaction(
return v.(*transaction)
}
// getByTransId returns a transaction by transId.
func (tm *transactionManager) getByTransId(transId string) *transaction {
return tm.transaction(transId, 0)
// getByTransID returns a transaction by transID.
func (tm *transactionManager) getByTransID(transID string) *transaction {
return tm.transaction(transID, 0)
}
// getByIndex returns a transaction by indexed key.
@@ -237,9 +237,9 @@ func (tm *transactionManager) getByIndex(index string) *transaction {
// transaction gets the proper transaction with whose id is transId and
// address is addr.
func (tm *transactionManager) filterOne(
transId string, addr *net.UDPAddr) *transaction {
transID string, addr *net.UDPAddr) *transaction {
trans := tm.getByTransId(transId)
trans := tm.getByTransID(transID)
if trans == nil || trans.node.addr.String() != addr.String() {
return nil
}
@@ -251,8 +251,8 @@ func (tm *transactionManager) filterOne(
// When timeout, it will retry `try - 1` times, which means it will query
// `try` times totally.
func (tm *transactionManager) query(q *query, try int) {
transId := q.data["t"].(string)
trans := tm.newTransaction(transId, q)
transID := q.data["t"].(string)
trans := tm.newTransaction(transID, q)
tm.insert(trans)
defer tm.delete(trans.id)
@@ -300,7 +300,7 @@ func (tm *transactionManager) sendQuery(
return
}
data := makeQuery(tm.genTransId(), queryType, a)
data := makeQuery(tm.genTransID(), queryType, a)
tm.queryChan <- &query{
node: no,
data: data,
@@ -465,14 +465,14 @@ func handleRequest(dht *DHT, addr *net.UDPAddr,
var nodes string
if dht.IsStandardMode() {
targetId := newBitmapFromString(target)
targetID := newBitmapFromString(target)
no, _ := dht.routingTable.GetNodeKBucktById(targetId)
no, _ := dht.routingTable.GetNodeKBucktByID(targetID)
if no != nil {
nodes = no.CompactNodeInfo()
} else {
nodes = strings.Join(
dht.routingTable.GetNeighborCompactInfos(targetId, dht.K),
dht.routingTable.GetNeighborCompactInfos(targetID, dht.K),
"",
)
}
@@ -546,8 +546,8 @@ func handleRequest(dht *DHT, addr *net.UDPAddr,
return
}
if implied_port, ok := a["implied_port"]; ok &&
implied_port.(int) != 0 {
if impliedPort, ok := a["implied_port"]; ok &&
impliedPort.(int) != 0 {
port = addr.Port
}
@@ -603,13 +603,13 @@ func findOn(dht *DHT, r map[string]interface{}, target *bitmap,
return nil
}
targetId := target.RawString()
targetID := target.RawString()
for _, no := range dht.routingTable.GetNeighbors(target, dht.K) {
switch queryType {
case findNodeType:
dht.transactionManager.findNode(no, targetId)
dht.transactionManager.findNode(no, targetID)
case getPeersType:
dht.transactionManager.getPeers(no, targetId)
dht.transactionManager.getPeers(no, targetID)
default:
panic("invalid find type")
}
+17 -10
View File
@@ -13,16 +13,23 @@ import (
)
const (
// REQUEST represents request message type
REQUEST = iota
// DATA represents data message type
DATA
// REJECT represents reject message type
REJECT
)
const (
BLOCK = 16384 // 2 ^ 14
MAX_METADATA_SIZE = BLOCK * 1000
EXTENDED = 20
HANDSHAKE = 0
// BLOCK is 2 ^ 14
BLOCK = 16384
// MaxMetadataSize represents the max medata it can accept
MaxMetadataSize = BLOCK * 1000
// EXTENDED represents it is a extended message
EXTENDED = 20
// HANDSHAKE represents handshake bit
HANDSHAKE = 0
)
var handshakePrefix = []byte{
@@ -65,7 +72,7 @@ func readMessage(conn *net.TCPConn, data *bytes.Buffer) (
// sendMessage sends data to the connection.
func sendMessage(conn *net.TCPConn, data []byte) error {
var length int32 = int32(len(data))
length := int32(len(data))
buffer := bytes.NewBuffer(nil)
binary.Write(buffer, binary.BigEndian, length)
@@ -75,11 +82,11 @@ func sendMessage(conn *net.TCPConn, data []byte) error {
}
// sendHandshake sends handshake message to conn.
func sendHandshake(conn *net.TCPConn, infoHash, peerId []byte) error {
func sendHandshake(conn *net.TCPConn, infoHash, peerID []byte) error {
data := make([]byte, 68)
copy(data[:28], handshakePrefix)
copy(data[28:48], infoHash)
copy(data[48:], peerId)
copy(data[48:], peerID)
_, err := conn.Write(data)
return err
@@ -133,7 +140,7 @@ func getUTMetaSize(data []byte) (
utMetadata = m["ut_metadata"].(int)
metadataSize = dict["metadata_size"].(int)
if metadataSize > MAX_METADATA_SIZE {
if metadataSize > MaxMetadataSize {
err = errors.New("metadata_size too long")
}
return
@@ -264,7 +271,7 @@ func (wire *Wire) fetchMetadata(r Request) {
switch msgType {
case EXTENDED:
extendedId, err := data.ReadByte()
extendedID, err := data.ReadByte()
if err != nil {
return
}
@@ -274,7 +281,7 @@ func (wire *Wire) fetchMetadata(r Request) {
return
}
if extendedId == 0 {
if extendedID == 0 {
if pieces != nil {
return
}
+92 -92
View File
@@ -62,24 +62,24 @@ func (node *node) CompactNodeInfo() string {
}, "")
}
// peer represents a peer contact.
type peer struct {
ip net.IP
port int
// Peer represents a peer contact.
type Peer struct {
IP net.IP
Port int
token string
}
// newPeer returns a new peer pointer.
func newPeer(ip net.IP, port int, token string) *peer {
return &peer{
ip: ip,
port: port,
func newPeer(ip net.IP, port int, token string) *Peer {
return &Peer{
IP: ip,
Port: port,
token: token,
}
}
// newPeerFromCompactIPPortInfo create a peer pointer by compact ip/port info.
func newPeerFromCompactIPPortInfo(compactInfo, token string) (*peer, error) {
func newPeerFromCompactIPPortInfo(compactInfo, token string) (*Peer, error) {
ip, port, err := decodeCompactIPPortInfo(compactInfo)
if err != nil {
return nil, err
@@ -88,10 +88,10 @@ func newPeerFromCompactIPPortInfo(compactInfo, token string) (*peer, error) {
return newPeer(ip, port, token), nil
}
// CompactNodeInfo returns "Compact node info".
// CompactIPPortInfo returns "Compact node info".
// See http://www.bittorrent.org/beps/bep_0005.html.
func (p *peer) CompactIPPortInfo() string {
info, _ := encodeCompactIPPortInfo(p.ip, p.port)
func (p *Peer) CompactIPPortInfo() string {
info, _ := encodeCompactIPPortInfo(p.IP, p.Port)
return info
}
@@ -111,7 +111,7 @@ func newPeersManager(dht *DHT) *peersManager {
}
// Insert adds a peer into peersManager.
func (pm *peersManager) Insert(infoHash string, peer *peer) {
func (pm *peersManager) Insert(infoHash string, peer *Peer) {
pm.Lock()
if _, ok := pm.table.Get(infoHash); !ok {
pm.table.Set(infoHash, newKeyedDeque())
@@ -123,8 +123,8 @@ func (pm *peersManager) Insert(infoHash string, peer *peer) {
}
// GetPeers returns size-length peers who announces having infoHash.
func (pm *peersManager) GetPeers(infoHash string, size int) []*peer {
peers := make([]*peer, 0, size)
func (pm *peersManager) GetPeers(infoHash string, size int) []*Peer {
peers := make([]*Peer, 0, size)
v, ok := pm.table.Get(infoHash)
if !ok {
@@ -132,7 +132,7 @@ func (pm *peersManager) GetPeers(infoHash string, size int) []*peer {
}
for e := range v.(*keyedDeque).Iter() {
peers = append(peers, e.Value.(*peer))
peers = append(peers, e.Value.(*Peer))
}
if len(peers) > size {
@@ -141,105 +141,105 @@ func (pm *peersManager) GetPeers(infoHash string, size int) []*peer {
return peers
}
// kBucket represents a k-size bucket.
type kBucket struct {
// kbucket represents a k-size bucket.
type kbucket struct {
sync.RWMutex
nodes, candidates *keyedDeque
lastChanged time.Time
prefix *bitmap
}
// newKBucket returns a new kBucket pointer.
func newKBucket(prefix *bitmap) *kBucket {
kbucket := &kBucket{
// newKBucket returns a new kbucket pointer.
func newKBucket(prefix *bitmap) *kbucket {
bucket := &kbucket{
nodes: newKeyedDeque(),
candidates: newKeyedDeque(),
lastChanged: time.Now(),
prefix: prefix,
}
return kbucket
return bucket
}
// LastChanged return the last time when it changes.
func (kbucket *kBucket) LastChanged() time.Time {
kbucket.RLock()
defer kbucket.RUnlock()
func (bucket *kbucket) LastChanged() time.Time {
bucket.RLock()
defer bucket.RUnlock()
return kbucket.lastChanged
return bucket.lastChanged
}
// RandomChildID returns a random id that has the same prefix with kbucket.
func (kbucket *kBucket) RandomChildID() string {
prefixLen := kbucket.prefix.Size / 8
// RandomChildID returns a random id that has the same prefix with bucket.
func (bucket *kbucket) RandomChildID() string {
prefixLen := bucket.prefix.Size / 8
return strings.Join([]string{
kbucket.prefix.RawString()[:prefixLen],
bucket.prefix.RawString()[:prefixLen],
randomString(20 - prefixLen),
}, "")
}
// UpdateTimestamp update kbucket's last changed time..
func (kbucket *kBucket) UpdateTimestamp() {
kbucket.Lock()
defer kbucket.Unlock()
// UpdateTimestamp update bucket's last changed time..
func (bucket *kbucket) UpdateTimestamp() {
bucket.Lock()
defer bucket.Unlock()
kbucket.lastChanged = time.Now()
bucket.lastChanged = time.Now()
}
// Insert inserts node to the kbucket. It returns whether the node is new in
// the kbucket.
func (kbucket *kBucket) Insert(no *node, rt *routingTable) bool {
isNew := !kbucket.nodes.HasKey(no.id.RawString())
// Insert inserts node to the bucket. It returns whether the node is new in
// the bucket.
func (bucket *kbucket) Insert(no *node, rt *routingTable) bool {
isNew := !bucket.nodes.HasKey(no.id.RawString())
kbucket.nodes.Push(no.id.RawString(), no)
bucket.nodes.Push(no.id.RawString(), no)
rt.cachedNodes.Set(no.addr.String(), no)
rt.Touch(kbucket)
rt.Touch(bucket)
return isNew
}
// Replace removes node, then put kbucket.candidates.Back() to the right
// place of kbucket.nodes.
func (kbucket *kBucket) Replace(no *node, rt *routingTable) {
kbucket.nodes.Delete(no.id.RawString())
// Replace removes node, then put bucket.candidates.Back() to the right
// place of bucket.nodes.
func (bucket *kbucket) Replace(no *node, rt *routingTable) {
bucket.nodes.Delete(no.id.RawString())
rt.cachedNodes.Delete(no.addr.String())
rt.Touch(kbucket)
rt.Touch(bucket)
if kbucket.candidates.Len() == 0 {
if bucket.candidates.Len() == 0 {
return
}
no = kbucket.candidates.Remove(kbucket.candidates.Back()).(*node)
no = bucket.candidates.Remove(bucket.candidates.Back()).(*node)
inserted := false
for e := range kbucket.nodes.Iter() {
for e := range bucket.nodes.Iter() {
if e.Value.(*node).lastActiveTime.After(
no.lastActiveTime) && !inserted {
kbucket.nodes.InsertBefore(no, e)
bucket.nodes.InsertBefore(no, e)
inserted = true
}
}
if !inserted {
kbucket.nodes.PushBack(no)
bucket.nodes.PushBack(no)
}
}
// Clear resets the kbucket.
func (kbucket *kBucket) Clear() {
kbucket.Lock()
defer kbucket.Unlock()
// Clear resets the bucket.
func (bucket *kbucket) Clear() {
bucket.Lock()
defer bucket.Unlock()
kbucket.nodes.Clear()
kbucket.candidates.Clear()
kbucket.lastChanged = time.Now()
bucket.nodes.Clear()
bucket.candidates.Clear()
bucket.lastChanged = time.Now()
}
// Fresh pings the expired nodes in the kbucket.
func (kbucket *kBucket) Fresh(dht *DHT) {
for e := range kbucket.nodes.Iter() {
// Fresh pings the expired nodes in the bucket.
func (bucket *kbucket) Fresh(dht *DHT) {
for e := range bucket.nodes.Iter() {
no := e.Value.(*node)
if time.Since(no.lastActiveTime) > dht.NodeExpriedAfter {
dht.transactionManager.ping(no)
@@ -251,14 +251,14 @@ func (kbucket *kBucket) Fresh(dht *DHT) {
type routingTableNode struct {
sync.RWMutex
children []*routingTableNode
kbucket *kBucket
bucket *kbucket
}
// newRoutingTableNode returns a new routingTableNode pointer.
func newRoutingTableNode(prefix *bitmap) *routingTableNode {
return &routingTableNode{
children: make([]*routingTableNode, 2),
kbucket: newKBucket(prefix),
bucket: newKBucket(prefix),
}
}
@@ -283,20 +283,20 @@ func (tableNode *routingTableNode) SetChild(index int, c *routingTableNode) {
tableNode.children[index] = c
}
// KBucket returns the kbucket routingTableNode holds.
func (tableNode *routingTableNode) KBucket() *kBucket {
// KBucket returns the bucket routingTableNode holds.
func (tableNode *routingTableNode) KBucket() *kbucket {
tableNode.RLock()
defer tableNode.RUnlock()
return tableNode.kbucket
return tableNode.bucket
}
// SetKBucket sets the kbucket.
func (tableNode *routingTableNode) SetKBucket(kbucket *kBucket) {
// SetKBucket sets the bucket.
func (tableNode *routingTableNode) SetKBucket(bucket *kbucket) {
tableNode.Lock()
defer tableNode.Unlock()
tableNode.kbucket = kbucket
tableNode.bucket = bucket
}
// Split splits current routingTableNode and sets it's two children.
@@ -313,7 +313,7 @@ func (tableNode *routingTableNode) Split(rt *routingTable) {
}
tableNode.Lock()
tableNode.children[1].kbucket.prefix.Set(prefixLen)
tableNode.children[1].bucket.prefix.Set(prefixLen)
tableNode.Unlock()
for e := range tableNode.KBucket().nodes.Iter() {
@@ -340,7 +340,7 @@ func (tableNode *routingTableNode) Clear() {
defer tableNode.Unlock()
tableNode.children = make([]*routingTableNode, 2)
tableNode.kbucket.Clear()
tableNode.bucket.Clear()
}
// routingTable implements the routing table in DHT protocol.
@@ -366,15 +366,15 @@ func newRoutingTable(k int, dht *DHT) *routingTable {
dht: dht,
}
rt.cachedKBuckets.Push(root.kbucket.prefix.String(), root.kbucket)
rt.cachedKBuckets.Push(root.bucket.prefix.String(), root.bucket)
return rt
}
// Touch updates the routing table. It will put the kbucket to the end of
// kbucket list.
func (rt *routingTable) Touch(kbucket *kBucket) {
kbucket.UpdateTimestamp()
rt.cachedKBuckets.Push(kbucket.prefix.String(), kbucket)
// Touch updates the routing table. It will put the bucket to the end of
// bucket list.
func (rt *routingTable) Touch(bucket *kbucket) {
bucket.UpdateTimestamp()
rt.cachedKBuckets.Push(bucket.prefix.String(), bucket)
}
// Insert adds a node to routing table. It returns whether the node is new
@@ -402,12 +402,12 @@ func (rt *routingTable) Insert(nd *node) bool {
return root.KBucket().Insert(nd, rt)
} else if root.KBucket().prefix.Compare(nd.id, prefixLen-1) == 0 {
// If node has the same prefix with kbucket, split it.
// If node has the same prefix with bucket, split it.
root.Split(rt)
root = root.Child(nd.id.Bit(prefixLen - 1))
} else {
// Finally, store node as a candidate and fresh the kbucket.
// Finally, store node as a candidate and fresh the bucket.
root.KBucket().candidates.PushBack(nd)
if root.KBucket().candidates.Len() > rt.k {
root.KBucket().candidates.Remove(
@@ -451,10 +451,10 @@ func (rt *routingTable) GetNeighborCompactInfos(id *bitmap, size int) []string {
return infos
}
// GetNodeKBucktById returns node whose id is `id` and the kbucket it
// GetNodeKBucktById returns node whose id is `id` and the bucket it
// belongs to.
func (rt *routingTable) GetNodeKBucktById(id *bitmap) (
nd *node, kbucket *kBucket) {
func (rt *routingTable) GetNodeKBucktByID(id *bitmap) (
nd *node, bucket *kbucket) {
rt.RLock()
defer rt.RUnlock()
@@ -469,7 +469,7 @@ func (rt *routingTable) GetNodeKBucktById(id *bitmap) (
if !ok {
return
}
nd, kbucket = v.Value.(*node), root.KBucket()
nd, bucket = v.Value.(*node), root.KBucket()
return
}
root = next
@@ -491,9 +491,9 @@ func (rt *routingTable) GetNodeByAddress(address string) (no *node, ok bool) {
// Remove deletes the node whose id is `id`.
func (rt *routingTable) Remove(id *bitmap) {
if nd, kbucket := rt.GetNodeKBucktById(id); nd != nil {
if nd, bucket := rt.GetNodeKBucktByID(id); nd != nil {
rt.Lock()
kbucket.Replace(nd, rt)
bucket.Replace(nd, rt)
rt.Unlock()
}
}
@@ -514,7 +514,7 @@ func (rt *routingTable) Clear() {
rt.root.Clear()
rt.cachedNodes.Clear()
rt.cachedKBuckets.Clear()
rt.cachedKBuckets.Push(rt.root.kbucket.prefix.String(), rt.root.kbucket)
rt.cachedKBuckets.Push(rt.root.bucket.prefix.String(), rt.root.bucket)
}
// Fresh sends findNode to all nodes in the expired nodes.
@@ -522,15 +522,15 @@ func (rt *routingTable) Fresh() {
now := time.Now()
for e := range rt.cachedKBuckets.Iter() {
kbucket := e.Value.(*kBucket)
if now.Sub(kbucket.LastChanged()) < rt.dht.KBucketExpiredAfter ||
kbucket.nodes.Len() == 0 {
bucket := e.Value.(*kbucket)
if now.Sub(bucket.LastChanged()) < rt.dht.KBucketExpiredAfter ||
bucket.nodes.Len() == 0 {
continue
}
for e := range kbucket.nodes.Iter() {
for e := range bucket.nodes.Iter() {
no := e.Value.(*node)
rt.dht.transactionManager.findNode(no, kbucket.RandomChildID())
rt.dht.transactionManager.findNode(no, bucket.RandomChildID())
}
}
@@ -547,7 +547,7 @@ func (rt *routingTable) Len() int {
return rt.cachedNodes.Len()
}
// Implemention of heap with heap.Interface.
// Implementation of heap with heap.Interface.
type heapItem struct {
distance *bitmap
value interface{}
+9 -9
View File
@@ -7,15 +7,15 @@ import (
"github.com/shiyanhui/dht"
)
type File struct {
type file struct {
Path []interface{} `json:"path"`
Length int `json:"length"`
}
type BitTorrent struct {
type bitTorrent struct {
InfoHash string `json:"infohash"`
Name string `json:"name"`
Files []File `json:"files,omitempty"`
Files []file `json:"files,omitempty"`
Length int `json:"length,omitempty"`
}
@@ -33,20 +33,20 @@ func main() {
continue
}
bt := BitTorrent{
bt := bitTorrent{
InfoHash: hex.EncodeToString(resp.InfoHash),
Name: info["name"].(string),
}
if v, ok := info["files"]; ok {
files := v.([]interface{})
bt.Files = make([]File, len(files))
bt.Files = make([]file, len(files))
for i, item := range files {
file := item.(map[string]interface{})
bt.Files[i] = File{
Path: file["path"].([]interface{}),
Length: file["length"].(int),
f := item.(map[string]interface{})
bt.Files[i] = file{
Path: f["path"].([]interface{}),
Length: f["length"].(int),
}
}
} else if _, ok := info["length"]; ok {