@@ -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+
256288func (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+
320399func (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