ooni-probe-cli/internal/engine/experiment/ndt7/upload.go
Simone Basso 3265bc670a
refactor(ndt7): use netxlite rather than netx (#768)
This diff required us to move some code around, but no major
change actually happened, except better tests.

While there, I also slightly refactored ndt7's implementation and
removed the ProxyURL setting, which was actually unused.

See https://github.com/ooni/probe/issues/2121
2022-05-30 23:14:07 +02:00

85 lines
2.0 KiB
Go

package ndt7
import (
"context"
"time"
"github.com/gorilla/websocket"
)
func newMessage(n int) (*websocket.PreparedMessage, error) {
return websocket.NewPreparedMessage(websocket.BinaryMessage, make([]byte, n))
}
type uploadManager struct {
conn wsConn
fractionForScaling int64
maxRuntime time.Duration
maxMessageSize int
maxScaledMessageSize int
measureInterval time.Duration
minMessageSize int
newMessage func(int) (*websocket.PreparedMessage, error)
onPerformance callbackPerformance
}
func newUploadManager(
conn wsConn, onPerformance callbackPerformance,
) uploadManager {
return uploadManager{
conn: conn,
fractionForScaling: paramFractionForScaling,
maxRuntime: paramMaxRuntime,
maxMessageSize: paramMaxMessageSize,
maxScaledMessageSize: paramMaxScaledMessageSize,
measureInterval: paramMeasureInterval,
minMessageSize: paramMinMessageSize,
newMessage: newMessage,
onPerformance: onPerformance,
}
}
func (mgr uploadManager) run(ctx context.Context) error {
var total int64
start := time.Now()
if err := mgr.conn.SetWriteDeadline(time.Now().Add(mgr.maxRuntime)); err != nil {
return err
}
size := mgr.minMessageSize
message, err := mgr.newMessage(size)
if err != nil {
return err
}
ticker := time.NewTicker(mgr.measureInterval)
defer ticker.Stop()
// goroutine that just reads and discards all incoming websockets messages
go func() {
for {
_, _, err := mgr.conn.NextReader()
if err != nil {
return
}
}
}()
for ctx.Err() == nil {
if err := mgr.conn.WritePreparedMessage(message); err != nil {
return err
}
total += int64(size)
select {
case now := <-ticker.C:
mgr.onPerformance(now.Sub(start), total)
default:
// NOTHING
}
if size >= mgr.maxScaledMessageSize || int64(size) >= (total/mgr.fractionForScaling) {
continue
}
size <<= 1
if message, err = mgr.newMessage(size); err != nil {
return err
}
}
return nil
}