feat(webconnectivity): long-term-evolution prototype (#882)
See https://github.com/ooni/probe/issues/2237
This commit is contained in:
parent
9ba6f8dcbb
commit
1a1d3126ae
20 changed files with 3067 additions and 1 deletions
135
internal/experiment/webconnectivity/measurer.go
Normal file
135
internal/experiment/webconnectivity/measurer.go
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
package webconnectivity
|
||||
|
||||
//
|
||||
// Measurer
|
||||
//
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http/cookiejar"
|
||||
"sync"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/atomicx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"golang.org/x/net/publicsuffix"
|
||||
)
|
||||
|
||||
// Measurer for the web_connectivity experiment.
|
||||
type Measurer struct {
|
||||
// Contains the experiment's config.
|
||||
Config *Config
|
||||
}
|
||||
|
||||
// NewExperimentMeasurer creates a new model.ExperimentMeasurer.
|
||||
func NewExperimentMeasurer(config *Config) model.ExperimentMeasurer {
|
||||
return &Measurer{
|
||||
Config: config,
|
||||
}
|
||||
}
|
||||
|
||||
// ExperimentName implements model.ExperimentMeasurer.
|
||||
func (m *Measurer) ExperimentName() string {
|
||||
return "web_connectivity"
|
||||
}
|
||||
|
||||
// ExperimentVersion implements model.ExperimentMeasurer.
|
||||
func (m *Measurer) ExperimentVersion() string {
|
||||
return "0.5.0"
|
||||
}
|
||||
|
||||
// Run implements model.ExperimentMeasurer.
|
||||
func (m *Measurer) Run(ctx context.Context, sess model.ExperimentSession,
|
||||
measurement *model.Measurement, callbacks model.ExperimentCallbacks) error {
|
||||
// Reminder: when this function returns an error, the measurement result
|
||||
// WILL NOT be submitted to the OONI backend. You SHOULD only return an error
|
||||
// for fundamental errors (e.g., the input is invalid or missing).
|
||||
|
||||
// honour InputOrQueryBackend
|
||||
input := measurement.Input
|
||||
if input == "" {
|
||||
return errors.New("no input provided")
|
||||
}
|
||||
|
||||
// convert the input string to a URL
|
||||
inputParser := &InputParser{
|
||||
AcceptedSchemes: []string{
|
||||
"http",
|
||||
"https",
|
||||
},
|
||||
AllowEndpoints: false,
|
||||
DefaultScheme: "",
|
||||
}
|
||||
URL, err := inputParser.Parse(string(measurement.Input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// initialize the experiment's test keys
|
||||
tk := NewTestKeys()
|
||||
measurement.TestKeys = tk
|
||||
|
||||
// create variables required to run parallel tasks
|
||||
idGenerator := &atomicx.Int64{}
|
||||
wg := &sync.WaitGroup{}
|
||||
|
||||
// create cookiejar
|
||||
jar, err := cookiejar.New(&cookiejar.Options{
|
||||
PublicSuffixList: publicsuffix.List,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// obtain the test helper's address
|
||||
testhelpers, _ := sess.GetTestHelpersByName("web-connectivity")
|
||||
var thAddr string
|
||||
for _, th := range testhelpers {
|
||||
if th.Type == "https" {
|
||||
thAddr = th.Address
|
||||
measurement.TestHelpers = map[string]any{
|
||||
"backend": &th,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if thAddr == "" {
|
||||
sess.Logger().Warnf("continuing without a valid TH address")
|
||||
tk.SetControlFailure(webconnectivity.ErrNoAvailableTestHelpers)
|
||||
}
|
||||
|
||||
// start background tasks
|
||||
resos := &DNSResolvers{
|
||||
DNSCache: NewDNSCache(),
|
||||
Domain: URL.Hostname(),
|
||||
IDGenerator: idGenerator,
|
||||
Logger: sess.Logger(),
|
||||
TestKeys: tk,
|
||||
URL: URL,
|
||||
ZeroTime: measurement.MeasurementStartTimeSaved,
|
||||
WaitGroup: wg,
|
||||
CookieJar: jar,
|
||||
Referer: "",
|
||||
Session: sess,
|
||||
THAddr: thAddr,
|
||||
UDPAddress: "",
|
||||
}
|
||||
resos.Start(ctx)
|
||||
|
||||
// wait for background tasks to join
|
||||
wg.Wait()
|
||||
|
||||
// If the context passed to us has been cancelled, we cannot
|
||||
// trust this experiment's results to be okay.
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// perform any deferred computation on the test keys
|
||||
tk.Finalize(sess.Logger())
|
||||
|
||||
// return whether there was a fundamental failure, which would prevent
|
||||
// the measurement from being submitted to the OONI collector.
|
||||
return tk.fundamentalFailure
|
||||
}
|
||||
Loading…
Reference in a new issue