ce7cb702218693d08ea6d83464d2457c9250027c
This commit is contained in:
commit
34c5f8963c
1 changed files with 145336 additions and 0 deletions
110
packages/oci-l4-relay-publisher/ranges.go
Normal file
110
packages/oci-l4-relay-publisher/ranges.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net/netip"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type addressRange struct {
|
||||
start uint32
|
||||
end uint32
|
||||
}
|
||||
|
||||
func rangeFromPrefix(value string) (addressRange, bool) {
|
||||
prefix, err := netip.ParsePrefix(value)
|
||||
if err != nil || !prefix.Addr().Is4() {
|
||||
return addressRange{}, false
|
||||
}
|
||||
address := prefix.Masked().Addr().As4()
|
||||
start := binary.BigEndian.Uint32(address[:])
|
||||
hostBits := 32 - prefix.Bits()
|
||||
end := start
|
||||
if hostBits == 32 {
|
||||
end = ^uint32(0)
|
||||
} else if hostBits > 0 {
|
||||
end |= (uint32(1) << hostBits) - 1
|
||||
}
|
||||
return addressRange{start: start, end: end}, true
|
||||
}
|
||||
|
||||
func mergeRanges(ranges []addressRange) []addressRange {
|
||||
if len(ranges) == 0 {
|
||||
return nil
|
||||
}
|
||||
sort.Slice(ranges, func(i, j int) bool {
|
||||
if ranges[i].start == ranges[j].start {
|
||||
return ranges[i].end < ranges[j].end
|
||||
}
|
||||
return ranges[i].start < ranges[j].start
|
||||
})
|
||||
merged := []addressRange{ranges[0]}
|
||||
for _, candidate := range ranges[1:] {
|
||||
current := &merged[len(merged)-1]
|
||||
adjacent := current.end != ^uint32(0) && candidate.start == current.end+1
|
||||
if candidate.start <= current.end || adjacent {
|
||||
if candidate.end > current.end {
|
||||
current.end = candidate.end
|
||||
}
|
||||
continue
|
||||
}
|
||||
merged = append(merged, candidate)
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
func intersectRanges(left, right []addressRange) []addressRange {
|
||||
left = mergeRanges(left)
|
||||
right = mergeRanges(right)
|
||||
var result []addressRange
|
||||
for leftIndex, rightIndex := 0, 0; leftIndex < len(left) && rightIndex < len(right); {
|
||||
start := max(left[leftIndex].start, right[rightIndex].start)
|
||||
end := min(left[leftIndex].end, right[rightIndex].end)
|
||||
if start <= end {
|
||||
result = append(result, addressRange{start: start, end: end})
|
||||
}
|
||||
if left[leftIndex].end < right[rightIndex].end {
|
||||
leftIndex++
|
||||
} else {
|
||||
rightIndex++
|
||||
}
|
||||
}
|
||||
return mergeRanges(result)
|
||||
}
|
||||
|
||||
func subtractRanges(base, denied []addressRange) []addressRange {
|
||||
base = mergeRanges(base)
|
||||
denied = mergeRanges(denied)
|
||||
var result []addressRange
|
||||
denyIndex := 0
|
||||
for _, candidate := range base {
|
||||
cursor := uint64(candidate.start)
|
||||
end := uint64(candidate.end)
|
||||
for denyIndex < len(denied) && uint64(denied[denyIndex].end) < cursor {
|
||||
denyIndex++
|
||||
}
|
||||
for index := denyIndex; index < len(denied) && uint64(denied[index].start) <= end; index++ {
|
||||
if uint64(denied[index].start) > cursor {
|
||||
result = append(result, addressRange{start: uint32(cursor), end: denied[index].start - 1})
|
||||
}
|
||||
if uint64(denied[index].end)+1 > cursor {
|
||||
cursor = uint64(denied[index].end) + 1
|
||||
}
|
||||
if cursor > end {
|
||||
break
|
||||
}
|
||||
}
|
||||
if cursor <= end {
|
||||
result = append(result, addressRange{start: uint32(cursor), end: uint32(end)})
|
||||
}
|
||||
}
|
||||
return mergeRanges(result)
|
||||
}
|
||||
|
||||
func addressCount(ranges []addressRange) uint64 {
|
||||
var result uint64
|
||||
for _, current := range mergeRanges(ranges) {
|
||||
result += uint64(current.end) - uint64(current.start) + 1
|
||||
}
|
||||
return result
|
||||
}
|
||||
Loading…
Reference in a new issue