Move tracker-specific logic out of http/query and into http
This commit is contained in:
parent
9292900afc
commit
98542c0ff1
3 changed files with 97 additions and 96 deletions
|
@ -7,13 +7,9 @@ package query
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/chihaya/chihaya/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Query represents a parsed URL.Query.
|
// Query represents a parsed URL.Query.
|
||||||
|
@ -94,8 +90,8 @@ func New(query string) (*Query, error) {
|
||||||
return q, nil
|
return q, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint64 is a helper to obtain a uints of any base from a Query. After being
|
// Uint64 is a helper to obtain a uint of any length from a Query. After being
|
||||||
// called, you can safely cast the uint64 to your desired base.
|
// called, you can safely cast the uint64 to your desired length.
|
||||||
func (q *Query) Uint64(key string) (uint64, error) {
|
func (q *Query) Uint64(key string) (uint64, error) {
|
||||||
str, exists := q.Params[key]
|
str, exists := q.Params[key]
|
||||||
if !exists {
|
if !exists {
|
||||||
|
@ -109,89 +105,3 @@ func (q *Query) Uint64(key string) (uint64, error) {
|
||||||
|
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestedPeerCount returns the request peer count or the provided fallback.
|
|
||||||
func (q Query) RequestedPeerCount(fallback int) int {
|
|
||||||
if numWantStr, exists := q.Params["numwant"]; exists {
|
|
||||||
numWant, err := strconv.Atoi(numWantStr)
|
|
||||||
if err != nil {
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
return numWant
|
|
||||||
}
|
|
||||||
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIPs(ipstr string, ipv4, ipv6 net.IP, cfg *config.NetConfig) (net.IP, net.IP, bool) {
|
|
||||||
var done bool
|
|
||||||
|
|
||||||
if ip := net.ParseIP(ipstr); ip != nil {
|
|
||||||
newIPv4 := ip.To4()
|
|
||||||
|
|
||||||
if ipv4 == nil && newIPv4 != nil {
|
|
||||||
ipv4 = newIPv4
|
|
||||||
} else if ipv6 == nil && newIPv4 == nil {
|
|
||||||
ipv6 = ip
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.DualStackedPeers {
|
|
||||||
done = ipv4 != nil && ipv6 != nil
|
|
||||||
} else {
|
|
||||||
done = ipv4 != nil || ipv6 != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return ipv4, ipv6, done
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequestedIP returns the requested IP address from a Query.
|
|
||||||
func (q Query) RequestedIP(r *http.Request, cfg *config.NetConfig) (v4, v6 net.IP, err error) {
|
|
||||||
var done bool
|
|
||||||
|
|
||||||
if cfg.AllowIPSpoofing {
|
|
||||||
if str, ok := q.Params["ip"]; ok {
|
|
||||||
if v4, v6, done = getIPs(str, v4, v6, cfg); done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if str, ok := q.Params["ipv4"]; ok {
|
|
||||||
if v4, v6, done = getIPs(str, v4, v6, cfg); done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if str, ok := q.Params["ipv6"]; ok {
|
|
||||||
if v4, v6, done = getIPs(str, v4, v6, cfg); done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.RealIPHeader != "" {
|
|
||||||
if xRealIPs, ok := q.Params[cfg.RealIPHeader]; ok {
|
|
||||||
if v4, v6, done = getIPs(string(xRealIPs[0]), v4, v6, cfg); done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if r.RemoteAddr == "" {
|
|
||||||
if v4 == nil {
|
|
||||||
v4 = net.ParseIP("127.0.0.1")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx := strings.LastIndex(r.RemoteAddr, ":"); idx != -1 {
|
|
||||||
if v4, v6, done = getIPs(r.RemoteAddr[0:idx], v4, v6, cfg); done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v4 == nil && v6 == nil {
|
|
||||||
err = errors.New("failed to parse IP address")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,7 +5,11 @@
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
|
||||||
|
@ -23,7 +27,7 @@ func NewAnnounce(cfg *config.Config, r *http.Request, p httprouter.Params) (*mod
|
||||||
|
|
||||||
compact := q.Params["compact"] != "0"
|
compact := q.Params["compact"] != "0"
|
||||||
event, _ := q.Params["event"]
|
event, _ := q.Params["event"]
|
||||||
numWant := q.RequestedPeerCount(cfg.NumWantFallback)
|
numWant := requestedPeerCount(q, cfg.NumWantFallback)
|
||||||
|
|
||||||
infohash, exists := q.Params["info_hash"]
|
infohash, exists := q.Params["info_hash"]
|
||||||
if !exists {
|
if !exists {
|
||||||
|
@ -35,7 +39,7 @@ func NewAnnounce(cfg *config.Config, r *http.Request, p httprouter.Params) (*mod
|
||||||
return nil, models.ErrMalformedRequest
|
return nil, models.ErrMalformedRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
ipv4, ipv6, err := q.RequestedIP(r, &cfg.NetConfig)
|
ipv4, ipv6, err := requestedIP(q, r, &cfg.NetConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, models.ErrMalformedRequest
|
return nil, models.ErrMalformedRequest
|
||||||
}
|
}
|
||||||
|
@ -99,3 +103,90 @@ func NewScrape(cfg *config.Config, r *http.Request, p httprouter.Params) (*model
|
||||||
Infohashes: q.Infohashes,
|
Infohashes: q.Infohashes,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// requestedPeerCount returns the wanted peer count or the provided fallback.
|
||||||
|
func requestedPeerCount(q *query.Query, fallback int) int {
|
||||||
|
if numWantStr, exists := q.Params["numwant"]; exists {
|
||||||
|
numWant, err := strconv.Atoi(numWantStr)
|
||||||
|
if err != nil {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
return numWant
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// requestedIP returns the IP addresses for a request. If there are multiple
|
||||||
|
// IP addresses in the request, one IPv4 and one IPv6 will be returned.
|
||||||
|
func requestedIP(q *query.Query, r *http.Request, cfg *config.NetConfig) (v4, v6 net.IP, err error) {
|
||||||
|
var done bool
|
||||||
|
|
||||||
|
if cfg.AllowIPSpoofing {
|
||||||
|
if str, ok := q.Params["ip"]; ok {
|
||||||
|
if v4, v6, done = getIPs(str, v4, v6, cfg); done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if str, ok := q.Params["ipv4"]; ok {
|
||||||
|
if v4, v6, done = getIPs(str, v4, v6, cfg); done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if str, ok := q.Params["ipv6"]; ok {
|
||||||
|
if v4, v6, done = getIPs(str, v4, v6, cfg); done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.RealIPHeader != "" {
|
||||||
|
if xRealIPs, ok := q.Params[cfg.RealIPHeader]; ok {
|
||||||
|
if v4, v6, done = getIPs(string(xRealIPs[0]), v4, v6, cfg); done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if r.RemoteAddr == "" {
|
||||||
|
if v4 == nil {
|
||||||
|
v4 = net.ParseIP("127.0.0.1")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx := strings.LastIndex(r.RemoteAddr, ":"); idx != -1 {
|
||||||
|
if v4, v6, done = getIPs(r.RemoteAddr[0:idx], v4, v6, cfg); done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v4 == nil && v6 == nil {
|
||||||
|
err = errors.New("failed to parse IP address")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIPs(ipstr string, ipv4, ipv6 net.IP, cfg *config.NetConfig) (net.IP, net.IP, bool) {
|
||||||
|
var done bool
|
||||||
|
|
||||||
|
if ip := net.ParseIP(ipstr); ip != nil {
|
||||||
|
newIPv4 := ip.To4()
|
||||||
|
|
||||||
|
if ipv4 == nil && newIPv4 != nil {
|
||||||
|
ipv4 = newIPv4
|
||||||
|
} else if ipv6 == nil && newIPv4 == nil {
|
||||||
|
ipv6 = ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.DualStackedPeers {
|
||||||
|
done = ipv4 != nil && ipv6 != nil
|
||||||
|
} else {
|
||||||
|
done = ipv4 != nil || ipv6 != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipv4, ipv6, done
|
||||||
|
}
|
||||||
|
|
|
@ -285,7 +285,7 @@ func appendSubnetPeers(ipv4s, ipv6s models.PeerList, ann *models.Announce, annou
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over the peers twice: first add only peers in the same subnet and
|
// Iterate over the peers twice: first add only peers in the same subnet and
|
||||||
// if we still need more peers grab any that haven't already been added.
|
// if we still need more peers grab ones that haven't already been added.
|
||||||
count := 0
|
count := 0
|
||||||
for _, checkInSubnet := range [2]bool{true, false} {
|
for _, checkInSubnet := range [2]bool{true, false} {
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
|
@ -313,7 +313,7 @@ func appendSubnetPeers(ipv4s, ipv6s models.PeerList, ann *models.Announce, annou
|
||||||
return ipv4s, ipv6s
|
return ipv4s, ipv6s
|
||||||
}
|
}
|
||||||
|
|
||||||
// peersEquivalent checks if two peers are one in the same.
|
// peersEquivalent checks if two peers represent the same entity.
|
||||||
func peersEquivalent(a, b *models.Peer) bool {
|
func peersEquivalent(a, b *models.Peer) bool {
|
||||||
return a.ID == b.ID || a.UserID != 0 && a.UserID == b.UserID
|
return a.ID == b.ID || a.UserID != 0 && a.UserID == b.UserID
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue