git » chasquid » commit 45580da

Update to math/rand/v2

author Alberto Bertogli
2025-02-16 20:18:16 UTC
committer Alberto Bertogli
2025-02-16 20:18:16 UTC
parent cef7bb079d3096a1ae5f046e150c60fddab7de4d

Update to math/rand/v2

This commit updates the uses of math/rand to math/rand/v2, which was
released in Go 1.22 (2024-02).

The new package is generally safer, see https://go.dev/blog/randv2 for
the details.

There are no user-visible changes, it is only adjusting the name of
functions, simplify some code thanks to v2 having a better API, etc.

chasquid.go +0 -4
go.mod +1 -1
internal/auth/auth.go +2 -2
internal/nettrace/test_server.go +12 -12
internal/nettrace/trace.go +1 -1
internal/queue/queue.go +5 -10
internal/smtpsrv/conn.go +1 -1

diff --git a/chasquid.go b/chasquid.go
index aba7886..c1a35cd 100644
--- a/chasquid.go
+++ b/chasquid.go
@@ -8,7 +8,6 @@ import (
 	"context"
 	"flag"
 	"fmt"
-	"math/rand"
 	"net"
 	"os"
 	"os/signal"
@@ -52,9 +51,6 @@ func main() {
 
 	log.Infof("chasquid starting (version %s)", version)
 
-	// Seed the PRNG, just to prevent for it to be totally predictable.
-	rand.Seed(time.Now().UnixNano())
-
 	conf, err := config.Load(*configDir+"/chasquid.conf", *configOverrides)
 	if err != nil {
 		log.Fatalf("Error loading config: %v", err)
diff --git a/go.mod b/go.mod
index e34cdfa..31b07b1 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module blitiri.com.ar/go/chasquid
 
-go 1.21
+go 1.22
 
 require (
 	blitiri.com.ar/go/log v1.1.0
diff --git a/internal/auth/auth.go b/internal/auth/auth.go
index c7a5be8..8ab86e9 100644
--- a/internal/auth/auth.go
+++ b/internal/auth/auth.go
@@ -6,7 +6,7 @@ import (
 	"encoding/base64"
 	"errors"
 	"fmt"
-	"math/rand"
+	"math/rand/v2"
 	"strings"
 	"time"
 
@@ -76,7 +76,7 @@ func (a *Authenticator) Authenticate(tr *trace.Trace, user, domain, password str
 		delay := a.AuthDuration - elapsed
 		if delay > 0 {
 			maxDelta := int64(float64(delay) * 0.2)
-			delay += time.Duration(rand.Int63n(maxDelta))
+			delay += time.Duration(rand.Int64N(maxDelta))
 			time.Sleep(delay)
 		}
 	}(time.Now())
diff --git a/internal/nettrace/test_server.go b/internal/nettrace/test_server.go
index 75f1d96..b5ca148 100644
--- a/internal/nettrace/test_server.go
+++ b/internal/nettrace/test_server.go
@@ -5,7 +5,7 @@ package main
 import (
 	"flag"
 	"fmt"
-	"math/rand"
+	"math/rand/v2"
 	"net/http"
 	"time"
 
@@ -48,23 +48,23 @@ func RandomEvents(family string) {
 func randomTrace(family string, tr nettrace.Trace) {
 	tr.Printf("this is a random event")
 	tr.Printf("and it has a random delay")
-	delay := time.Duration(rand.Intn(1000)) * time.Millisecond
+	delay := rand.N(1000 * time.Millisecond)
 	tr.Printf("sleeping %v", delay)
 	time.Sleep(delay)
 
-	if rand.Intn(100) < 1 {
+	if rand.IntN(100) < 1 {
 		tr.Printf("this unlucky one is an error")
 		tr.SetError()
 	}
 
-	if rand.Intn(100) < 10 {
+	if rand.IntN(100) < 10 {
 		tr.Printf("this one got super verbose!")
 		for j := 0; j < 100; j++ {
 			tr.Printf("message %d", j)
 		}
 	}
 
-	if rand.Intn(100) < 30 {
+	if rand.IntN(100) < 30 {
 		tr.Printf("this one had a child")
 		c := tr.NewChild(family, "achild")
 		go randomTrace(family, c)
@@ -78,7 +78,7 @@ func RandomLongEvent(family, title string) {
 	tr := nettrace.New(family, title)
 	tr.Printf("this is a random long event")
 	for i := 0; ; i++ {
-		delay := time.Duration(rand.Intn(100)) * time.Millisecond
+		delay := rand.N(100 * time.Millisecond)
 		time.Sleep(delay)
 		tr.Printf("message %d, slept %v", i, delay)
 	}
@@ -90,16 +90,16 @@ func RandomBunny(family, title string) {
 	tr.SetMaxEvents(100)
 	tr.Printf("this is the top 🐇")
 	for i := 0; ; i++ {
-		delay := time.Duration(rand.Intn(100)) * time.Millisecond
+		delay := rand.N(100 * time.Millisecond)
 		time.Sleep(delay)
 		tr.Printf("message %d, slept %v", i, delay)
 
-		if rand.Intn(100) < 40 {
+		if rand.IntN(100) < 40 {
 			c := tr.NewChild(family, fmt.Sprintf("child-%d", i))
 			go randomTrace(family, c)
 		}
 
-		if rand.Intn(100) < 40 {
+		if rand.IntN(100) < 40 {
 			n := nettrace.New(family, fmt.Sprintf("linked-%d", i))
 			go randomTrace(family, n)
 			tr.Link(n, "linking with this guy")
@@ -114,7 +114,7 @@ func randomNested(family string, depth int, parent nettrace.Trace) {
 
 	tr.Printf("I am a spoiled child")
 
-	delay := time.Duration(rand.Intn(100)) * time.Millisecond
+	delay := rand.N(100 * time.Millisecond)
 	time.Sleep(delay)
 	tr.Printf("slept %v", delay)
 
@@ -124,12 +124,12 @@ func randomNested(family string, depth int, parent nettrace.Trace) {
 	}
 
 	// If we make this < 50, then it grows forever.
-	if rand.Intn(100) < 75 {
+	if rand.IntN(100) < 75 {
 		tr.Printf("I sang really well")
 		return
 	}
 
-	max := rand.Intn(5)
+	max := rand.IntN(5)
 	for i := 0; i < max; i++ {
 		tr.Printf("spawning %d", i)
 		go randomNested(family, depth+1, tr)
diff --git a/internal/nettrace/trace.go b/internal/nettrace/trace.go
index 700d6ff..7ee539d 100644
--- a/internal/nettrace/trace.go
+++ b/internal/nettrace/trace.go
@@ -5,7 +5,7 @@ package nettrace
 import (
 	"container/ring"
 	"fmt"
-	"math/rand"
+	"math/rand/v2"
 	"sort"
 	"strconv"
 	"strings"
diff --git a/internal/queue/queue.go b/internal/queue/queue.go
index a459f56..71ff42f 100644
--- a/internal/queue/queue.go
+++ b/internal/queue/queue.go
@@ -9,8 +9,9 @@ import (
 	"bytes"
 	"context"
 	"encoding/base64"
+	"encoding/binary"
 	"fmt"
-	"math/rand"
+	"math/rand/v2"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -67,17 +68,11 @@ var newID chan string
 
 func generateNewIDs() {
 	// The IDs are only used internally, we are ok with using a PRNG.
-	// We create our own to avoid relying on external sources initializing it
-	// properly.
-	prng := rand.New(rand.NewSource(time.Now().UnixNano()))
-
 	// IDs are base64(8 random bytes), but the code doesn't care.
 	buf := make([]byte, 8)
-	id := ""
 	for {
-		prng.Read(buf)
-		id = base64.RawURLEncoding.EncodeToString(buf)
-		newID <- id
+		binary.NativeEndian.PutUint64(buf, rand.Uint64())
+		newID <- base64.RawURLEncoding.EncodeToString(buf)
 	}
 }
 
@@ -485,7 +480,7 @@ func nextDelay(createdAt time.Time) time.Duration {
 
 	// Perturb the delay, to avoid all queued emails to be retried at the
 	// exact same time after a restart.
-	delay += time.Duration(rand.Intn(60)) * time.Second
+	delay += rand.N(60 * time.Second)
 	return delay
 }
 
diff --git a/internal/smtpsrv/conn.go b/internal/smtpsrv/conn.go
index 8073f28..af90d82 100644
--- a/internal/smtpsrv/conn.go
+++ b/internal/smtpsrv/conn.go
@@ -8,7 +8,7 @@ import (
 	"flag"
 	"fmt"
 	"io"
-	"math/rand"
+	"math/rand/v2"
 	"net"
 	"net/mail"
 	"os"