diff --git a/README.md b/README.md
@@ -19,7 +19,7 @@
## Installation
```bash
-go install github.com/acidvegas/golcg
+go install github.com/acidvegas/golcg/cmd/golcg@latest
```
## 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⁰)
= 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:
- Start: 192.168.0.0 → 3232235520
- 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)
+
diff --git a/cmd/golcg/main.go b/cmd/golcg/main.go
@@ -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)
+ }
+}
diff --git a/go.mod b/go.mod
@@ -1,3 +1,3 @@
-module golcg
+module github.com/acidvegas/golcg
-go 1.23.2
+go 1.21
diff --git a/golcg.go b/golcg.go
@@ -1,42 +1,40 @@
-package main
+package golcg
import (
"errors"
- "flag"
"fmt"
"math/rand"
"net"
"os"
"path/filepath"
- "strconv"
"strings"
"time"
)
type LCG struct {
- m uint32
- a uint32
- c uint32
- current uint32
+ M uint32
+ A uint32
+ C uint32
+ Current uint32
}
func NewLCG(seed int, m uint32) *LCG {
return &LCG{
- m: m,
- a: 1664525,
- c: 1013904223,
- current: uint32(seed),
+ M: m,
+ A: 1664525,
+ C: 1013904223,
+ Current: uint32(seed),
}
}
func (l *LCG) Next() uint32 {
- l.current = (l.a*l.current + l.c) % l.m
- return l.current
+ l.Current = (l.A*l.Current + l.C) % l.M
+ return l.Current
}
type IPRange struct {
- start uint32
- total uint32
+ Start uint32
+ Total uint32
}
func NewIPRange(cidr string) (*IPRange, error) {
@@ -52,17 +50,17 @@ func NewIPRange(cidr string) (*IPRange, error) {
total := broadcast - start + 1
return &IPRange{
- start: start,
- total: uint32(total),
+ Start: start,
+ Total: uint32(total),
}, nil
}
func (r *IPRange) GetIPAtIndex(index uint32) (string, error) {
- if index >= r.total {
+ if index >= r.Total {
return "", errors.New("IP index out of range")
}
- ip := uint32ToIP(r.start + index)
+ ip := uint32ToIP(r.Start + index)
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)
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++
}
@@ -117,7 +115,7 @@ func IPStream(cidr string, shardNum, totalShards, seed int, state *uint32) (<-ch
remaining := shardSize
for remaining > 0 {
- index := lcg.Next() % ipRange.total
+ index := lcg.Next() % ipRange.Total
if totalShards == 1 || index%uint32(totalShards) == uint32(shardIndex) {
ip, err := ipRange.GetIPAtIndex(index)
if err != nil {
@@ -127,7 +125,7 @@ func IPStream(cidr string, shardNum, totalShards, seed int, state *uint32) (<-ch
remaining--
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
}
-
-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)
- }
-}
| | | |