2020-06-07 13:43:15 +08:00
|
|
|
// Copyright 2020 xgfone
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package dht
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2023-04-01 21:07:18 +08:00
|
|
|
"github.com/xgfone/go-bt/krpc"
|
|
|
|
"github.com/xgfone/go-bt/metainfo"
|
2020-06-07 13:43:15 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// PeerManager is used to manage the peers.
|
|
|
|
type PeerManager interface {
|
|
|
|
// If ipv6 is true, only return ipv6 addresses. Or return ipv4 addresses.
|
2023-03-01 22:50:46 +08:00
|
|
|
GetPeers(infohash metainfo.Hash, maxnum int, ipv6 bool) []string
|
2020-06-07 13:43:15 +08:00
|
|
|
}
|
|
|
|
|
2023-03-01 22:50:46 +08:00
|
|
|
var _ PeerManager = new(tokenPeerManager)
|
|
|
|
|
2020-06-07 13:43:15 +08:00
|
|
|
type peer struct {
|
|
|
|
ID metainfo.Hash
|
2023-03-01 22:50:46 +08:00
|
|
|
Addr krpc.Addr
|
2020-06-07 13:43:15 +08:00
|
|
|
Token string
|
|
|
|
Time time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
type tokenPeerManager struct {
|
|
|
|
lock sync.RWMutex
|
|
|
|
exit chan struct{}
|
|
|
|
peers map[metainfo.Hash]map[string]peer
|
|
|
|
}
|
|
|
|
|
|
|
|
func newTokenPeerManager() *tokenPeerManager {
|
|
|
|
return &tokenPeerManager{
|
|
|
|
exit: make(chan struct{}),
|
|
|
|
peers: make(map[metainfo.Hash]map[string]peer, 128),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start starts the token-peer manager.
|
|
|
|
func (tpm *tokenPeerManager) Start(interval time.Duration) {
|
|
|
|
tick := time.NewTicker(interval)
|
|
|
|
defer tick.Stop()
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-tpm.exit:
|
|
|
|
return
|
|
|
|
case now := <-tick.C:
|
|
|
|
tpm.lock.Lock()
|
|
|
|
for id, peers := range tpm.peers {
|
|
|
|
for addr, peer := range peers {
|
|
|
|
if now.Sub(peer.Time) > interval {
|
|
|
|
delete(peers, addr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(peers) == 0 {
|
|
|
|
delete(tpm.peers, id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tpm.lock.Unlock()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-01 22:50:46 +08:00
|
|
|
func (tpm *tokenPeerManager) Set(id metainfo.Hash, addr krpc.Addr, token string) {
|
2020-06-07 13:43:15 +08:00
|
|
|
addrkey := addr.String()
|
|
|
|
tpm.lock.Lock()
|
|
|
|
peers, ok := tpm.peers[id]
|
|
|
|
if !ok {
|
|
|
|
peers = make(map[string]peer, 4)
|
|
|
|
tpm.peers[id] = peers
|
|
|
|
}
|
2023-03-01 22:50:46 +08:00
|
|
|
peers[addrkey] = peer{ID: id, Addr: addr, Token: token, Time: time.Now()}
|
2020-06-07 13:43:15 +08:00
|
|
|
tpm.lock.Unlock()
|
|
|
|
}
|
|
|
|
|
2023-03-01 22:50:46 +08:00
|
|
|
func (tpm *tokenPeerManager) Get(id metainfo.Hash, addr krpc.Addr) (token string) {
|
2020-06-07 13:43:15 +08:00
|
|
|
addrkey := addr.String()
|
|
|
|
tpm.lock.RLock()
|
|
|
|
if peers, ok := tpm.peers[id]; ok {
|
|
|
|
if peer, ok := peers[addrkey]; ok {
|
|
|
|
token = peer.Token
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tpm.lock.RUnlock()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tpm *tokenPeerManager) Stop() {
|
|
|
|
select {
|
|
|
|
case <-tpm.exit:
|
|
|
|
default:
|
|
|
|
close(tpm.exit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-01 22:50:46 +08:00
|
|
|
func (tpm *tokenPeerManager) GetPeers(infohash metainfo.Hash, maxnum int, ipv6 bool) (addrs []string) {
|
|
|
|
addrs = make([]string, 0, maxnum)
|
2020-06-07 13:43:15 +08:00
|
|
|
tpm.lock.RLock()
|
|
|
|
if peers, ok := tpm.peers[infohash]; ok {
|
|
|
|
for _, peer := range peers {
|
|
|
|
if maxnum < 1 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if ipv6 { // For IPv6
|
2023-03-01 22:50:46 +08:00
|
|
|
if isIPv6(peer.Addr.IP) {
|
2020-06-07 13:43:15 +08:00
|
|
|
maxnum--
|
2023-03-01 22:50:46 +08:00
|
|
|
addrs = append(addrs, peer.Addr.String())
|
2020-06-07 13:43:15 +08:00
|
|
|
}
|
2023-03-01 22:50:46 +08:00
|
|
|
} else if !isIPv6(peer.Addr.IP) { // For IPv4
|
2020-06-07 13:43:15 +08:00
|
|
|
maxnum--
|
2023-03-01 22:50:46 +08:00
|
|
|
addrs = append(addrs, peer.Addr.String())
|
2020-06-07 13:43:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tpm.lock.RUnlock()
|
|
|
|
return
|
|
|
|
}
|