Skip to content

Commit 15f4596

Browse files
committed
dialers: sample ip & hosts from cache
1 parent 8f0cb50 commit 15f4596

2 files changed

Lines changed: 87 additions & 0 deletions

File tree

intra/dialers/dns.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ func ResolveForUrl(s string) []netip.Addr {
5151
return For(u.Hostname())
5252
}
5353

54+
func SampleHosts(n uint8) []string {
55+
return ipm.ReverseGetMany(n)
56+
}
57+
58+
func SampleIPs(n uint8) []netip.Addr {
59+
return ipm.GetMany(n)
60+
}
61+
5462
// ECH returns the ECH config, if any, for the given hostname.
5563
// The query is resolved using IPMapper's default resolver.
5664
func ECH(hostname string) ([]byte, error) {

intra/protect/ipmap/ipmap.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,16 @@ type IPMap interface {
101101
// Subsequent calls to GetAny return the same IPSet. Never returns nil.
102102
// hostOrIP may be host:port, or ip:port, or host, or ip.
103103
GetAny(hostOrIP string) *IPSet
104+
// GetMany returns a list of sampled IPs from the ipmap cache.
105+
GetMany(n uint8) []netip.Addr
104106
// MakeIPSet creates an IPSet for this hostname bootstrapped with given IPs
105107
// or IP:Ports. Subsequent calls to MakeIPSet return a new, overridden IPSet.
106108
// hostOrIP may be host:port, or ip:port, or host, or ip.
107109
MakeIPSet(hostOrIP string, ipps []string, typ IPSetType) *IPSet
108110
// Reverse lookup; returns hostnames for the given IP address.
109111
ReverseGet(ip netip.Addr) []string
112+
// ReverseGetMany returns a list of sampled hostnames from the ipmap cache.
113+
ReverseGetMany(n uint8) []string
110114
// With sets the default resolver to use for hostname resolution.
111115
With(r IPMapper)
112116
// Clear removes all IPSets from the map.
@@ -253,6 +257,34 @@ func (m *ipmap) Add(hostOrIP string) *IPSet {
253257
return s
254258
}
255259

260+
func (m *ipmap) ReverseGetMany(n uint8) []string {
261+
hosts := make([]string, 0, n)
262+
m.RLock()
263+
defer m.RUnlock()
264+
265+
for host := range m.m {
266+
if len(hosts) >= int(n) {
267+
break
268+
}
269+
if _, err := netip.ParseAddr(host); err != nil {
270+
// append if not an IP address
271+
hosts = append(hosts, host)
272+
}
273+
}
274+
for host := range m.p {
275+
if len(hosts) >= int(n) {
276+
break
277+
}
278+
if _, err := netip.ParseAddr(host); err != nil {
279+
// append if not an IP address
280+
hosts = append(hosts, host)
281+
}
282+
}
283+
284+
log.I("ipmap: ReverseGetMany: sampled %d hosts", len(hosts))
285+
return hosts
286+
}
287+
256288
func (m *ipmap) ReverseGet(ip netip.Addr) []string {
257289
q := x.StrOf(ip.String())
258290

@@ -317,6 +349,53 @@ func (m *ipmap) get(hostOrIP string, typ IPSetType) (s *IPSet) {
317349
return s
318350
}
319351

352+
func (m *ipmap) GetMany(n uint8) []netip.Addr {
353+
m.RLock()
354+
defer m.RUnlock()
355+
356+
ips := make([]netip.Addr, 0, n)
357+
358+
oneip := func(s *IPSet) (zz netip.Addr) {
359+
confirmed := s.confirmed.Load()
360+
if confirmed.IsGlobalUnicast() {
361+
return confirmed
362+
}
363+
for _, ip := range s.ips {
364+
if ip.IsGlobalUnicast() {
365+
return ip
366+
}
367+
}
368+
return
369+
}
370+
for _, s := range m.m {
371+
if len(ips) >= int(n) {
372+
break
373+
}
374+
if ip := oneip(s); ip.IsGlobalUnicast() {
375+
ips = append(ips, ip)
376+
}
377+
}
378+
for _, s := range m.p {
379+
if len(ips) >= int(n) {
380+
break
381+
}
382+
if ip := oneip(s); ip.IsGlobalUnicast() {
383+
ips = append(ips, ip)
384+
}
385+
}
386+
for _, s := range m.ip {
387+
if len(ips) >= int(n) {
388+
break
389+
}
390+
if ip := oneip(s); ip.IsGlobalUnicast() {
391+
ips = append(ips, ip)
392+
}
393+
}
394+
395+
log.I("ipmap: GetMany: sampled %d ips", len(ips))
396+
return ips
397+
}
398+
320399
func (m *ipmap) MakeIPSet(hostOrIP string, ipps []string, typ IPSetType) *IPSet {
321400
if host, _, err := net.SplitHostPort(hostOrIP); err == nil {
322401
hostOrIP = host

0 commit comments

Comments
 (0)