mirror of
https://github.com/sot-tech/mochi.git
synced 2026-06-22 03:58:52 -07:00
Support dual-stacked peers
This commit is contained in:
+33
-15
@@ -121,38 +121,53 @@ func (q Query) RequestedPeerCount(fallback int) int {
|
||||
return fallback
|
||||
}
|
||||
|
||||
func getIPs(ipstr string, ipv4, ipv6 net.IP) (net.IP, net.IP, 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
|
||||
}
|
||||
}
|
||||
|
||||
return ipv4, ipv6, ipv4 != nil && ipv6 != nil
|
||||
}
|
||||
|
||||
// RequestedIP returns the requested IP address from a Query.
|
||||
func (q Query) RequestedIP(r *http.Request, allowSpoofing bool) (net.IP, error) {
|
||||
func (q Query) RequestedIP(r *http.Request, allowSpoofing bool) (ipv4, ipv6 net.IP, err error) {
|
||||
var done bool
|
||||
|
||||
if allowSpoofing {
|
||||
if ipstr, ok := q.Params["ip"]; ok {
|
||||
if ip := net.ParseIP(ipstr); ip != nil {
|
||||
return ip, nil
|
||||
}
|
||||
ipv4, ipv6, done = getIPs(ipstr, ipv4, ipv6)
|
||||
}
|
||||
|
||||
if ipstr, ok := q.Params["ipv4"]; ok {
|
||||
if ip := net.ParseIP(ipstr); ip != nil {
|
||||
return ip, nil
|
||||
if ipv4, ipv6, done = getIPs(ipstr, ipv4, ipv6); done {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ipstr, ok := q.Params["ipv6"]; ok {
|
||||
if ip := net.ParseIP(ipstr); ip != nil {
|
||||
return ip, nil
|
||||
if ipv4, ipv6, done = getIPs(ipstr, ipv4, ipv6); done {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if xRealIPs, ok := q.Params["x-real-ip"]; ok {
|
||||
if ip := net.ParseIP(string(xRealIPs[0])); ip != nil {
|
||||
return ip, nil
|
||||
if ipv4, ipv6, done = getIPs(string(xRealIPs[0]), ipv4, ipv6); done {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if r.RemoteAddr == "" {
|
||||
if ip := net.ParseIP("127.0.0.1"); ip != nil {
|
||||
return ip, nil
|
||||
if ipv4 == nil {
|
||||
ipv4 = net.ParseIP("127.0.0.1")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
portIndex := len(r.RemoteAddr) - 1
|
||||
@@ -164,10 +179,13 @@ func (q Query) RequestedIP(r *http.Request, allowSpoofing bool) (net.IP, error)
|
||||
|
||||
if portIndex != -1 {
|
||||
ipstr := r.RemoteAddr[0:portIndex]
|
||||
if ip := net.ParseIP(ipstr); ip != nil {
|
||||
return ip, nil
|
||||
if ipv4, ipv6, done = getIPs(ipstr, ipv4, ipv6); done {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("failed to parse IP address")
|
||||
if ipv4 == nil && ipv6 == nil {
|
||||
err = errors.New("failed to parse IP address")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
+3
-2
@@ -35,7 +35,7 @@ func NewAnnounce(cfg *config.Config, r *http.Request, p httprouter.Params) (*mod
|
||||
return nil, models.ErrMalformedRequest
|
||||
}
|
||||
|
||||
ip, err := q.RequestedIP(r, cfg.AllowIPSpoofing)
|
||||
ipv4, ipv6, err := q.RequestedIP(r, cfg.AllowIPSpoofing)
|
||||
if err != nil {
|
||||
return nil, models.ErrMalformedRequest
|
||||
}
|
||||
@@ -65,7 +65,8 @@ func NewAnnounce(cfg *config.Config, r *http.Request, p httprouter.Params) (*mod
|
||||
Compact: compact,
|
||||
Downloaded: downloaded,
|
||||
Event: event,
|
||||
IP: ip,
|
||||
IPv4: ipv4,
|
||||
IPv6: ipv6,
|
||||
Infohash: infohash,
|
||||
Left: left,
|
||||
NumWant: numWant,
|
||||
|
||||
+16
-12
@@ -70,17 +70,13 @@ func compactPeers(ipv6 bool, peers models.PeerList) []byte {
|
||||
|
||||
if ipv6 {
|
||||
for _, peer := range peers {
|
||||
if ip := peer.IP.To16(); ip != nil {
|
||||
compactPeers.Write(ip)
|
||||
compactPeers.Write([]byte{byte(peer.Port >> 8), byte(peer.Port & 0xff)})
|
||||
}
|
||||
compactPeers.Write(peer.IPv6)
|
||||
compactPeers.Write([]byte{byte(peer.Port >> 8), byte(peer.Port & 0xff)})
|
||||
}
|
||||
} else {
|
||||
for _, peer := range peers {
|
||||
if ip := peer.IP.To4(); ip != nil {
|
||||
compactPeers.Write(ip)
|
||||
compactPeers.Write([]byte{byte(peer.Port >> 8), byte(peer.Port & 0xff)})
|
||||
}
|
||||
compactPeers.Write(peer.IPv4)
|
||||
compactPeers.Write([]byte{byte(peer.Port >> 8), byte(peer.Port & 0xff)})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,17 +85,25 @@ func compactPeers(ipv6 bool, peers models.PeerList) []byte {
|
||||
|
||||
func peersList(ipv4s, ipv6s models.PeerList) (peers []bencode.Dict) {
|
||||
for _, peer := range ipv4s {
|
||||
peers = append(peers, peerDict(&peer))
|
||||
peers = append(peers, peerDict(&peer, false))
|
||||
}
|
||||
for _, peer := range ipv6s {
|
||||
peers = append(peers, peerDict(&peer))
|
||||
peers = append(peers, peerDict(&peer, true))
|
||||
}
|
||||
return peers
|
||||
}
|
||||
|
||||
func peerDict(peer *models.Peer) bencode.Dict {
|
||||
func peerDict(peer *models.Peer, ipv6 bool) bencode.Dict {
|
||||
var ip string
|
||||
|
||||
if ipv6 {
|
||||
ip = peer.IPv6.String()
|
||||
} else {
|
||||
ip = peer.IPv4.String()
|
||||
}
|
||||
|
||||
return bencode.Dict{
|
||||
"ip": peer.IP.String(),
|
||||
"ip": ip,
|
||||
"peer id": peer.ID,
|
||||
"port": peer.Port,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user