From 26de6d2e9c1a6888fe47cba99ce40e87168b6864 Mon Sep 17 00:00:00 2001
From: Cooper Lees <cooper@fb.com>
Date: Wed, 20 Aug 2014 16:24:33 -0700
Subject: [PATCH] Respect a clients AF Optional Support - config driven

---
 config/config.go          |  2 ++
 tracker/models/peermap.go | 35 +++++++++++++++++++++--------------
 2 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/config/config.go b/config/config.go
index b1b4661..d518899 100644
--- a/config/config.go
+++ b/config/config.go
@@ -45,6 +45,7 @@ type NetConfig struct {
 	AllowIPSpoofing  bool   `json:"allow_ip_spoofing"`
 	DualStackedPeers bool   `json:"dual_stacked_peers"`
 	RealIPHeader     string `json:"real_ip_header"`
+	RespectAF        bool   `json:"respect_af"`
 
 	PreferredSubnet     bool `json:"preferred_subnet,omitempty"`
 	PreferredIPv4Subnet int  `json:"preferred_ipv4_subnet,omitempty"`
@@ -113,6 +114,7 @@ var DefaultConfig = Config{
 	NetConfig: NetConfig{
 		AllowIPSpoofing:  true,
 		DualStackedPeers: true,
+		RespectAF: false,
 	},
 
 	ClientWhitelistEnabled: false,
diff --git a/tracker/models/peermap.go b/tracker/models/peermap.go
index 571318f..4b6fb33 100644
--- a/tracker/models/peermap.go
+++ b/tracker/models/peermap.go
@@ -129,13 +129,8 @@ func (pm *PeerMap) AppendPeers(ipv4s, ipv6s PeerList, ann *Announce, wanted int)
 			continue
 		}
 
-		if ann.HasIPv6() && peer.HasIPv6() {
-			ipv6s = append(ipv6s, peer)
-			count++
-		} else if peer.HasIPv4() {
-			ipv4s = append(ipv4s, peer)
-			count++
-		}
+		// Add the peers optionally respecting AF
+		appendPeers(&ipv4s, &ipv6s, ann, &peer, &count)
 	}
 
 	return ipv4s, ipv6s
@@ -174,19 +169,31 @@ func (pm *PeerMap) AppendSubnetPeers(ipv4s, ipv6s PeerList, ann *Announce, wante
 				continue
 			}
 
-			if ann.HasIPv6() && peer.HasIPv6() {
-				ipv6s = append(ipv6s, peer)
-				count++
-			} else if peer.HasIPv4() {
-				ipv4s = append(ipv4s, peer)
-				count++
-			}
+			// Add the peers optionally respecting AF
+			appendPeers(&ipv4s, &ipv6s, ann, &peer, &count)
 		}
 	}
 
 	return ipv4s, ipv6s
 }
 
+// Optionally Respect AF for peers returned and avoid copy-pasta
+func appendPeers(ipv4s, ipv6s *PeerList, ann *Announce, peer *Peer, count *int) {
+		// v6 to only v6 announcements
+		if ann.HasIPv6() && peer.HasIPv6() {
+			*ipv6s = append(*ipv6s, *peer)
+			*count++
+		// v4 to only dual stacked requests if we are respecting AF of annoucement
+		} else if ann.Config.RespectAF && ann.HasIPv4() && peer.HasIPv4() {
+			*ipv4s = append(*ipv4s, *peer)
+			*count++
+		// Default everything else to get IPv4 if we are not respecting AF
+		} else if !ann.Config.RespectAF && peer.HasIPv4() {
+			*ipv4s = append(*ipv4s, *peer)
+			*count++
+		}
+}
+
 // peersEquivalent checks if two peers represent the same entity.
 func peersEquivalent(a, b *Peer) bool {
 	return a.ID == b.ID || a.UserID != 0 && a.UserID == b.UserID