diff --git a/pixelflut/api.go b/pixelflut/api.go index 59f15e1..a9a599c 100644 --- a/pixelflut/api.go +++ b/pixelflut/api.go @@ -6,7 +6,6 @@ import ( "image" "image/color" "log" - "math/rand" "net" "sync" @@ -37,9 +36,11 @@ func Flut(img *image.NRGBA, position image.Point, shuffle, rgbsplit, randoffset, } var messages [][]byte - var maxX, maxY int + var maxOffsetX, maxOffsetY int if randoffset { - maxX, maxY = CanvasSize(address) + maxX, maxY := CanvasSize(address) + maxOffsetX = maxX - img.Bounds().Canon().Dx() + maxOffsetY = maxY - img.Bounds().Canon().Dy() messages = cmds.Chunk(1) // each connection should send the full img } else { messages = cmds.Chunk(conns) @@ -52,15 +53,7 @@ func Flut(img *image.NRGBA, position image.Point, shuffle, rgbsplit, randoffset, msg = messages[i] } - bombWg.Add(1) - if randoffset { - msg = append(OffsetCmd( - rand.Intn(maxX-img.Bounds().Canon().Dx()), - rand.Intn(maxY-img.Bounds().Canon().Dy()), - ), msg...) - } - - go bombAddress(msg, address, stop, &bombWg) + go bombAddress(msg, address, maxOffsetX, maxOffsetY, stop, &bombWg) } bombWg.Wait() if wg != nil { @@ -98,7 +91,7 @@ func FetchImage(bounds image.Rectangle, address string, conns int, stop chan boo } go readPixels(img, conn, stop) - go bombConn(cmds[i], conn, stop) + go bombConn(cmds[i], 0, 0, conn, stop) } return img diff --git a/pixelflut/commands.go b/pixelflut/commands.go index 828cd2c..4130f70 100644 --- a/pixelflut/commands.go +++ b/pixelflut/commands.go @@ -32,7 +32,7 @@ func (c commands) Shuffle() { } } -// AddOffset uses the OFFSET command to send the image at a specific place (not supported by all servers. example: https://github.com/TobleMiner/shoreline) +// OffsetCmd applies offset to all following requests. Not supported by all servers. example: https://github.com/TobleMiner/shoreline. func OffsetCmd(x, y int) []byte { return []byte(fmt.Sprintf("OFFSET %d %d\n", x, y)) } diff --git a/pixelflut/net.go b/pixelflut/net.go index fc0ec4c..5c1d98d 100644 --- a/pixelflut/net.go +++ b/pixelflut/net.go @@ -3,6 +3,7 @@ package pixelflut import ( "fmt" "log" + "math/rand" "net" "sync" "time" @@ -74,26 +75,37 @@ func initPerfReporter() *Performance { // bombAddress writes the given message via plain TCP to the given address, // as fast as possible, until stop is closed. -func bombAddress(message []byte, address string, stop chan bool, wg *sync.WaitGroup) { +func bombAddress(message []byte, address string, maxOffsetX, maxOffsetY int, stop chan bool, wg *sync.WaitGroup) { + wg.Add(1) + defer wg.Done() conn, err := net.Dial("tcp", address) if err != nil { log.Fatal(err) } defer conn.Close() - bombConn(message, conn, stop) - wg.Done() + bombConn(message, maxOffsetX, maxOffsetY, conn, stop) } -func bombConn(message []byte, conn net.Conn, stop chan bool) { +func bombConn(message []byte, maxOffsetX, maxOffsetY int, conn net.Conn, stop chan bool) { PerformanceReporter.connsReporter <- 1 defer func() { PerformanceReporter.connsReporter <- -1 }() + var msg = make([]byte, len(message)+16) // leave some space for offset cmd + msg = message + randOffset := maxOffsetX > 1 && maxOffsetY > 0 + for { select { case <-stop: return default: - b, err := conn.Write(message) + if randOffset { + msg = append( + OffsetCmd(rand.Intn(maxOffsetX), rand.Intn(maxOffsetY)), + message..., + ) + } + b, err := conn.Write(msg) if err != nil { log.Fatal(err) }