This diff addresses another point of https://github.com/ooni/probe/issues/1956: > - [ ] observe that we're still using a bunch of private interfaces for common interfaces such as the `Dialer`, so we can get rid of these private interfaces and always use the ones in `model`, which allows us to remove a bunch of legacy wrappers Additional cleanups may still be possible. The more I cleanup, the more I see there's extra legacy code we can dispose of (which seems good?).
101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
package websteps
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/url"
|
|
|
|
"github.com/apex/log"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/experiment/websteps"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
|
)
|
|
|
|
type (
|
|
CtrlRequest = websteps.CtrlRequest
|
|
ControlResponse = websteps.CtrlResponse
|
|
)
|
|
|
|
var ErrInternalServer = errors.New("internal server error")
|
|
|
|
// Config contains the building blocks of the testhelper algorithm
|
|
type Config struct {
|
|
checker InitChecker
|
|
explorer Explorer
|
|
generator Generator
|
|
resolver model.Resolver
|
|
}
|
|
|
|
// Measure performs the three consecutive steps of the testhelper algorithm:
|
|
//
|
|
// 1. InitialChecks
|
|
//
|
|
// 2. Explore
|
|
//
|
|
// 3. Generate
|
|
func Measure(ctx context.Context, creq *CtrlRequest, config *Config) (*ControlResponse, error) {
|
|
var (
|
|
URL *url.URL
|
|
err error
|
|
)
|
|
resolver := config.resolver
|
|
if resolver == nil {
|
|
// use a central resolver
|
|
resolver = newResolver()
|
|
}
|
|
checker := config.checker
|
|
if checker == nil {
|
|
checker = &DefaultInitChecker{resolver: resolver}
|
|
}
|
|
URL, err = checker.InitialChecks(creq.URL)
|
|
if err != nil {
|
|
// return a valid response in case of NXDOMAIN so the probe can compare the failure
|
|
if err == ErrNoSuchHost {
|
|
return newDNSFailedResponse(err, creq.URL), nil
|
|
}
|
|
return nil, err
|
|
}
|
|
explorer := config.explorer
|
|
if explorer == nil {
|
|
explorer = &DefaultExplorer{resolver: resolver}
|
|
}
|
|
rts, err := explorer.Explore(URL, creq.Headers)
|
|
if err != nil {
|
|
return nil, ErrInternalServer
|
|
}
|
|
generator := config.generator
|
|
if generator == nil {
|
|
generator = &DefaultGenerator{resolver: resolver}
|
|
}
|
|
meas, err := generator.Generate(ctx, rts, creq.Addrs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ControlResponse{URLs: meas}, nil
|
|
}
|
|
|
|
// newDNSFailedResponse creates a new response with one URLMeasurement entry
|
|
// indicating that the DNS step failed
|
|
func newDNSFailedResponse(err error, URL string) *ControlResponse {
|
|
resp := &ControlResponse{}
|
|
m := &URLMeasurement{
|
|
URL: URL,
|
|
DNS: &DNSMeasurement{
|
|
Failure: newfailure(err),
|
|
},
|
|
}
|
|
resp.URLs = append(resp.URLs, m)
|
|
return resp
|
|
}
|
|
|
|
// newResolver creates a new DNS resolver instance
|
|
func newResolver() model.Resolver {
|
|
childResolver, err := netx.NewDNSClient(netx.Config{Logger: log.Log}, "doh://google")
|
|
runtimex.PanicOnError(err, "NewDNSClient failed")
|
|
var r model.Resolver = childResolver
|
|
r = &netxlite.ResolverIDNA{Resolver: r}
|
|
return r
|
|
}
|