-
-
Notifications
You must be signed in to change notification settings - Fork 189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
*: migrate to netip #567
base: main
Are you sure you want to change the base?
*: migrate to netip #567
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I'm mostly okay with this. Something about the redis implementation seems odd, and I don't remember how exactly that was laid out.
Now that I think about it, wasn't there also some markdown doc about that, which should maybe be updated with the new redis keys?
ct := ps.getClock() | ||
addr := p.AddrPort.Addr() | ||
sk := swarmKey(ih, true, addr) | ||
ihKey := sk[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe name this differently, took me a while to see that this holds information about the address family...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this confused me a bit too looking back. I'm open to suggestions because it's non obvious to me, haha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe just af
or addrFamily
or something like that?
This is a bit weird, not sure what I was thinking back then. We store a modtime (ok) at a key like 4S12345...
in a hashmap called 4
. So the leading 4
in the swarm key is redundant here. It's not redundant for it's actual use to identify a hashmap, though...
So, we could remove one byte off that key, but meh.
The first byte is the address family. We could return that as a second value from swarmKey
or maybe have a function to extract it from an IP. I think both of those would clear up some of the confusion here.
EDIT: Maybe we can even remove the leading two bytes? The second byte is S/L
, but if we only use the address family hashmap for garbage collection, do we need to distinguish between seeder and leecher side for the modtime of a swarm?
I still don't have the full overview of what I was doing with this, tbh. Maybe I'll open an issue to look into it at some point in the future...
This should reduce the number programmer errors producing keys.
(replying to this via email, hope that works)Yeah, that makes sense. I've looked this up for another project a while back: these 4-in-6 constructions were added for backwards compatibility: for applications that only support IPv6, on hosts that are dual stacked or IPv4, the OS can wrap those into IPv6. Maybe that also applies if we bind to IPv6 only and some netfilter stuff translates IPv4 to that. All in all probably somewhat unlikely... Maybe we should have never opened this can of worms 😅Anyway. Sanitizing in the sanitization Middleware seems like the sane thing. On Apr 16, 2022 18:47, Jimmy Zelinskie ***@***.***> wrote:
@jzelinskie commented on this pull request.
In storage/redis/peer_store.go:
… }
-func (ps *peerStore) seederCountKey(af string) string {
- return af + "_S_count"
+// Key that stores the cardinality of the peers of an IP version.
+//
+// "4L" => IPv4 Leechers
+// "6S" => IPv6 Seeders
+func peerCountKey(seed bool, addr netip.Addr) string {
+ key := "4"
+ if addr.Is6() {
We call addr.Unmap() in SanitizeAnnounce so there really should never be any time that the storage systems have to deal with 4in6.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because your review was requested.Message ID: ***@***.***>
|
I think this is good to go now @mrd0ll4r. I'd like to create some follow ups before I add too many changes to this one PR. |
skip-pkg-cache: true | ||
skip-build-cache: false | ||
go-version: "^1.18" | ||
- uses: "authzed/actions/gofumpt@main" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will steal your github actions for my personal stuff :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright. A few more small ones and one more relevant one about sanitization of scrapes.
The redis stuff is still unclear in my head. I hope the tests catch the bugs...
// String implements fmt.Stringer, returning the base16 encoded PeerID. | ||
func (p PeerID) String() string { return fmt.Sprintf("%x", p[:]) } | ||
|
||
// MarshalBinary returns a 20-byte string of the raw bytes of the ID. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Not a string
func (i InfoHash) RawString() string { | ||
return string(i[:]) | ||
} | ||
// MarshalBinary returns a 20-byte string of the raw bytes of the InfoHash. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
r.Peer.IP.AddressFamily = IPv6 | ||
} else { | ||
r.AddrPort = netip.AddrPortFrom(r.AddrPort.Addr().Unmap(), r.AddrPort.Port()) | ||
if !r.AddrPort.Addr().IsValid() || r.AddrPort.Addr().IsUnspecified() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sanitization is missing for scrape requests! Maybe add that, since we now have a Peer
in the scrape request, instead of just an address family.
@@ -317,7 +300,7 @@ func (t *Frontend) handleRequest(r Request, w ResponseWriter) (actionName string | |||
return | |||
} | |||
|
|||
WriteAnnounce(w, txID, resp, actionID == announceV6ActionID, req.IP.AddressFamily == bittorrent.IPv6) | |||
WriteAnnounce(w, txID, resp, actionID == announceV6ActionID, r.IP.Unmap().Is6()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: This should already be Unmap
ped, from line 211 above. Maybe add a doc comment about that somewhere...
// There are twice the amount of shards specified by the user, the first | ||
// half is dedicated to IPv4 swarms and the second half is dedicated to | ||
// IPv6 swarms. | ||
idx := binary.BigEndian.Uint32(infoHash[:4]) % (uint32(len(ps.shards)) / 2) | ||
if af == bittorrent.IPv6 { | ||
if addr.Is6() && !addr.Is4In6() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in favor of removing these Is4In6
checks (in everything but the sanitization middleware and frontends, of course). What do you think?
select { | ||
case <-ps.closed: | ||
panic("attempted to interact with stopped memory store") | ||
default: | ||
} | ||
|
||
resp.InfoHash = ih | ||
shard := ps.shards[ps.shardIndex(ih, addressFamily)] | ||
shard := ps.shards[ps.shardIndex(ih, p.AddrPort.Addr())] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this breaks if we don't have the Is4In6
check and no sanitization for scrapes.
ct := ps.getClock() | ||
addr := p.AddrPort.Addr() | ||
sk := swarmKey(ih, true, addr) | ||
ihKey := sk[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe just af
or addrFamily
or something like that?
This is a bit weird, not sure what I was thinking back then. We store a modtime (ok) at a key like 4S12345...
in a hashmap called 4
. So the leading 4
in the swarm key is redundant here. It's not redundant for it's actual use to identify a hashmap, though...
So, we could remove one byte off that key, but meh.
The first byte is the address family. We could return that as a second value from swarmKey
or maybe have a function to extract it from an IP. I think both of those would clear up some of the confusion here.
EDIT: Maybe we can even remove the leading two bytes? The second byte is S/L
, but if we only use the address family hashmap for garbage collection, do we need to distinguish between seeder and leecher side for the modtime of a swarm?
I still don't have the full overview of what I was doing with this, tbh. Maybe I'll open an issue to look into it at some point in the future...
@@ -581,38 +586,38 @@ func (ps *peerStore) AnnouncePeers(ih bittorrent.InfoHash, seeder bool, numWant | |||
|
|||
if seeder { | |||
// Append leechers as possible. | |||
for _, pk := range conLeechers { | |||
for _, sk := range conLeechers { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer these to stay pk
as in peerKey, since they are encoded peers.
benchHookList(b, hooks, req) | ||
} | ||
|
||
func benchHookListV6(b *testing.B, hooks hookList) { | ||
req := &bittorrent.AnnounceRequest{Peer: bittorrent.Peer{IP: bittorrent.IP{IP: net.ParseIP("fc00::0001"), AddressFamily: bittorrent.IPv6}}} | ||
req := &bittorrent.AnnounceRequest{Peer: bittorrent.Peer{ | ||
AddrPort: netip.AddrPortFrom(netip.MustParseAddr("fc00:0001"), 0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
netip.MustParseAddr
will panic here. You forgot second colon in ipv6 address.
This change replaces
net.IP
usage withnetip.AddrPort
.As a part of changing
bittorrent.Peer
to embed anetip.AddrPort
, this introducesPeer.MarshalBinary()
and replaces ad-hoc storage peer keys with this implementation.Closes #540
Fixes #538