passt, funktion unklar
This commit is contained in:
81
main.go
81
main.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"expvar"
|
||||
"fmt"
|
||||
@@ -151,31 +152,79 @@ func handleCheck(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// liefert alle möglichen Präfixe dieser IP, beginnend beim längsten (/32 oder /128)
|
||||
func supernets(ip netip.Addr) []string {
|
||||
if ip.Is4() {
|
||||
a := ip.As4() // Kopie addressierbar machen
|
||||
u := binary.BigEndian.Uint32(a[:]) // jetzt darf man slicen
|
||||
|
||||
supers := make([]string, 33) // /32 … /0
|
||||
for bits := 32; bits >= 0; bits-- {
|
||||
mask := uint32(0xffffffff) << (32 - bits)
|
||||
n := u & mask
|
||||
addr := netip.AddrFrom4([4]byte{
|
||||
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
|
||||
})
|
||||
supers[32-bits] = fmt.Sprintf("%s/%d", addr, bits)
|
||||
}
|
||||
return supers
|
||||
}
|
||||
|
||||
a := ip.As16() // Kopie addressierbar
|
||||
supers := make([]string, 129) // /128 … /0
|
||||
for bits := 128; bits >= 0; bits-- {
|
||||
b := a // Wert-Kopie für Modifikation
|
||||
|
||||
// vollständige Bytes auf 0 setzen
|
||||
full := (128 - bits) / 8
|
||||
for i := 0; i < full; i++ {
|
||||
b[15-i] = 0
|
||||
}
|
||||
// Restbits maskieren
|
||||
rem := (128 - bits) % 8
|
||||
if rem != 0 {
|
||||
b[15-full] &= 0xFF << rem
|
||||
}
|
||||
|
||||
addr := netip.AddrFrom16(b)
|
||||
supers[128-bits] = fmt.Sprintf("%s/%d", addr, bits)
|
||||
}
|
||||
return supers
|
||||
}
|
||||
|
||||
func checkIP(ip netip.Addr, cats []string) ([]string, error) {
|
||||
if res, ok := ipCache.Get(ip.String()); ok {
|
||||
hits.Add(1)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
matches := []string{}
|
||||
supers := supernets(ip)
|
||||
pipe := rdb.Pipeline()
|
||||
cmds := make([]*redis.IntCmd, 0, len(cats)*len(supers))
|
||||
|
||||
// *einen* Redis-Roundtrip bauen
|
||||
for _, cat := range cats {
|
||||
iter := rdb.Scan(ctx, 0, "bl:"+cat+":*", 0).Iterator()
|
||||
for iter.Next(ctx) {
|
||||
key := iter.Val()
|
||||
parts := strings.SplitN(key, ":", 3)
|
||||
if len(parts) != 3 {
|
||||
continue
|
||||
}
|
||||
pfx, err := netip.ParsePrefix(parts[2])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if pfx.Contains(ip) {
|
||||
matches = append(matches, cat)
|
||||
break
|
||||
}
|
||||
for _, pfx := range supers {
|
||||
key := "bl:" + cat + ":" + pfx
|
||||
cmds = append(cmds, pipe.Exists(ctx, key))
|
||||
}
|
||||
}
|
||||
if _, err := pipe.Exec(ctx); err != nil && err != redis.Nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
matches := make([]string, 0, len(cats))
|
||||
idx := 0
|
||||
for _, cat := range cats {
|
||||
for range supers {
|
||||
if cmds[idx].Val() == 1 {
|
||||
matches = append(matches, cat)
|
||||
break // Kategorie gefunden → nächste
|
||||
}
|
||||
idx++
|
||||
}
|
||||
}
|
||||
|
||||
misses.Add(1)
|
||||
ipCache.Add(ip.String(), matches)
|
||||
return matches, nil
|
||||
|
Reference in New Issue
Block a user