Package ready for go get & import usage
This commit is contained in:
parent
d6ad25efdb
commit
5853af0490
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
```bash
|
```bash
|
||||||
go install github.com/acidvegas/golcg
|
go install github.com/acidvegas/golcg/cmd/golcg@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -91,7 +91,6 @@ Every IPv4 address is fundamentally a 32-bit number. For example, the IP address
|
|||||||
192.168.1.1 = (192 × 256³) + (168 × 256²) + (1 × 256¹) + (1 × 256⁰)
|
192.168.1.1 = (192 × 256³) + (168 × 256²) + (1 × 256¹) + (1 × 256⁰)
|
||||||
= 3232235777
|
= 3232235777
|
||||||
```
|
```
|
||||||
|
|
||||||
This integer representation allows us to treat IP ranges as simple number sequences. A CIDR block like "192.168.0.0/16" becomes a continuous range of integers:
|
This integer representation allows us to treat IP ranges as simple number sequences. A CIDR block like "192.168.0.0/16" becomes a continuous range of integers:
|
||||||
- Start: 192.168.0.0 → 3232235520
|
- Start: 192.168.0.0 → 3232235520
|
||||||
- End: 192.168.255.255 → 3232301055
|
- End: 192.168.255.255 → 3232301055
|
||||||
@ -143,3 +142,4 @@ The sharding system employs an interleaved approach that ensures even distributi
|
|||||||
---
|
---
|
||||||
|
|
||||||
###### Mirrors: [acid.vegas](https://git.acid.vegas/golcg) • [SuperNETs](https://git.supernets.org/acidvegas/golcg) • [GitHub](https://github.com/acidvegas/golcg) • [GitLab](https://gitlab.com/acidvegas/golcg) • [Codeberg](https://codeberg.org/acidvegas/golcg)
|
###### Mirrors: [acid.vegas](https://git.acid.vegas/golcg) • [SuperNETs](https://git.supernets.org/acidvegas/golcg) • [GitHub](https://github.com/acidvegas/golcg) • [GitLab](https://gitlab.com/acidvegas/golcg) • [Codeberg](https://codeberg.org/acidvegas/golcg)
|
||||||
|
|
||||||
|
54
cmd/golcg/main.go
Normal file
54
cmd/golcg/main.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/acidvegas/golcg"
|
||||||
|
)
|
||||||
|
|
||||||
|
const Version = "1.0.0"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cidr := flag.String("cidr", "", "Target IP range in CIDR format")
|
||||||
|
shardNum := flag.Int("shard-num", 1, "Shard number (1-based)")
|
||||||
|
totalShards := flag.Int("total-shards", 1, "Total number of shards")
|
||||||
|
seed := flag.Int("seed", 0, "Random seed for LCG")
|
||||||
|
stateStr := flag.String("state", "", "Resume from specific LCG state")
|
||||||
|
version := flag.Bool("version", false, "Show version information")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *version {
|
||||||
|
fmt.Printf("golcg version %s\n", Version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *cidr == "" {
|
||||||
|
fmt.Println("Error: CIDR is required")
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var state *uint32
|
||||||
|
if *stateStr != "" {
|
||||||
|
stateVal, err := strconv.ParseUint(*stateStr, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error parsing state: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
stateUint32 := uint32(stateVal)
|
||||||
|
state = &stateUint32
|
||||||
|
}
|
||||||
|
|
||||||
|
stream, err := golcg.IPStream(*cidr, *shardNum, *totalShards, *seed, state)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ip := range stream {
|
||||||
|
fmt.Println(ip)
|
||||||
|
}
|
||||||
|
}
|
82
golcg.go
82
golcg.go
@ -1,42 +1,40 @@
|
|||||||
package main
|
package golcg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LCG struct {
|
type LCG struct {
|
||||||
m uint32
|
M uint32
|
||||||
a uint32
|
A uint32
|
||||||
c uint32
|
C uint32
|
||||||
current uint32
|
Current uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLCG(seed int, m uint32) *LCG {
|
func NewLCG(seed int, m uint32) *LCG {
|
||||||
return &LCG{
|
return &LCG{
|
||||||
m: m,
|
M: m,
|
||||||
a: 1664525,
|
A: 1664525,
|
||||||
c: 1013904223,
|
C: 1013904223,
|
||||||
current: uint32(seed),
|
Current: uint32(seed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LCG) Next() uint32 {
|
func (l *LCG) Next() uint32 {
|
||||||
l.current = (l.a*l.current + l.c) % l.m
|
l.Current = (l.A*l.Current + l.C) % l.M
|
||||||
return l.current
|
return l.Current
|
||||||
}
|
}
|
||||||
|
|
||||||
type IPRange struct {
|
type IPRange struct {
|
||||||
start uint32
|
Start uint32
|
||||||
total uint32
|
Total uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIPRange(cidr string) (*IPRange, error) {
|
func NewIPRange(cidr string) (*IPRange, error) {
|
||||||
@ -52,17 +50,17 @@ func NewIPRange(cidr string) (*IPRange, error) {
|
|||||||
total := broadcast - start + 1
|
total := broadcast - start + 1
|
||||||
|
|
||||||
return &IPRange{
|
return &IPRange{
|
||||||
start: start,
|
Start: start,
|
||||||
total: uint32(total),
|
Total: uint32(total),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *IPRange) GetIPAtIndex(index uint32) (string, error) {
|
func (r *IPRange) GetIPAtIndex(index uint32) (string, error) {
|
||||||
if index >= r.total {
|
if index >= r.Total {
|
||||||
return "", errors.New("IP index out of range")
|
return "", errors.New("IP index out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := uint32ToIP(r.start + index)
|
ip := uint32ToIP(r.Start + index)
|
||||||
return ip.String(), nil
|
return ip.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,12 +100,12 @@ func IPStream(cidr string, shardNum, totalShards, seed int, state *uint32) (<-ch
|
|||||||
|
|
||||||
lcg := NewLCG(seed+shardIndex, 1<<32-1)
|
lcg := NewLCG(seed+shardIndex, 1<<32-1)
|
||||||
if state != nil {
|
if state != nil {
|
||||||
lcg.current = *state
|
lcg.Current = *state
|
||||||
}
|
}
|
||||||
|
|
||||||
shardSize := ipRange.total / uint32(totalShards)
|
shardSize := ipRange.Total / uint32(totalShards)
|
||||||
|
|
||||||
if uint32(shardIndex) < (ipRange.total % uint32(totalShards)) {
|
if uint32(shardIndex) < (ipRange.Total % uint32(totalShards)) {
|
||||||
shardSize++
|
shardSize++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +115,7 @@ func IPStream(cidr string, shardNum, totalShards, seed int, state *uint32) (<-ch
|
|||||||
remaining := shardSize
|
remaining := shardSize
|
||||||
|
|
||||||
for remaining > 0 {
|
for remaining > 0 {
|
||||||
index := lcg.Next() % ipRange.total
|
index := lcg.Next() % ipRange.Total
|
||||||
if totalShards == 1 || index%uint32(totalShards) == uint32(shardIndex) {
|
if totalShards == 1 || index%uint32(totalShards) == uint32(shardIndex) {
|
||||||
ip, err := ipRange.GetIPAtIndex(index)
|
ip, err := ipRange.GetIPAtIndex(index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -127,7 +125,7 @@ func IPStream(cidr string, shardNum, totalShards, seed int, state *uint32) (<-ch
|
|||||||
remaining--
|
remaining--
|
||||||
|
|
||||||
if remaining%1000 == 0 {
|
if remaining%1000 == 0 {
|
||||||
SaveState(seed, cidr, shardNum, totalShards, lcg.current)
|
SaveState(seed, cidr, shardNum, totalShards, lcg.Current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,39 +133,3 @@ func IPStream(cidr string, shardNum, totalShards, seed int, state *uint32) (<-ch
|
|||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
|
||||||
cidr := flag.String("cidr", "", "Target IP range in CIDR format")
|
|
||||||
shardNum := flag.Int("shard-num", 1, "Shard number (1-based)")
|
|
||||||
totalShards := flag.Int("total-shards", 1, "Total number of shards")
|
|
||||||
seed := flag.Int("seed", 0, "Random seed for LCG")
|
|
||||||
stateStr := flag.String("state", "", "Resume from specific LCG state")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if *cidr == "" {
|
|
||||||
fmt.Println("Error: CIDR is required")
|
|
||||||
flag.Usage()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var state *uint32
|
|
||||||
if *stateStr != "" {
|
|
||||||
stateVal, err := strconv.ParseUint(*stateStr, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error parsing state: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
stateUint32 := uint32(stateVal)
|
|
||||||
state = &stateUint32
|
|
||||||
}
|
|
||||||
|
|
||||||
stream, err := IPStream(*cidr, *shardNum, *totalShards, *seed, state)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
for ip := range stream {
|
|
||||||
fmt.Println(ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user