3265bc670a
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
85 lines
2.0 KiB
Go
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
|
|
}
|