ooni-probe-cli/internal/cmd/oohelperd/measure.go
Simone Basso 867a243fef
refactor(oohelperd): make performing additional measurements easier (#889)
This diff refactors oohelperd to make performing additional measurements easier. We need:

1. to run the DNS task _before_ other tasks such that we can measure both IP addresses returned by the TH and the ones returned by the probe. When we'll introduce TLS measurements, this will allow us to validate probe-provided IP addresses inside the TH call. If probe-provided addresses work with TLS, they are legitimate for the domain.

2. to tie the number of TCP measurements to a list of endpoints collected by the probe _or_ the TH rather than just to the one provided by the probe. Anticipating this change, let us refactor how we read the results of the TCP task to make it independent of the number of addresses provided by the probe.

This work is part of https://github.com/ooni/probe/issues/2237
2022-08-28 12:17:31 +02:00

104 lines
2.2 KiB
Go

package main
//
// Top-level measurement algorithm
//
import (
"context"
"net"
"net/url"
"sync"
"github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity"
)
type (
// ctrlRequest is the request sent to the test helper
ctrlRequest = webconnectivity.ControlRequest
// ctrlResponse is the response from the test helper
ctrlResponse = webconnectivity.ControlResponse
)
// measure performs the measurement described by the request and
// returns the corresponding response or an error.
func measure(ctx context.Context, config *handler, creq *ctrlRequest) (*ctrlResponse, error) {
// parse input for correctness
URL, err := url.Parse(creq.HTTPRequest)
if err != nil {
return nil, err
}
wg := &sync.WaitGroup{}
// dns: start
dnsch := make(chan ctrlDNSResult, 1)
if net.ParseIP(URL.Hostname()) == nil {
wg.Add(1)
go dnsDo(ctx, &dnsConfig{
Domain: URL.Hostname(),
NewResolver: config.NewResolver,
Out: dnsch,
Wg: wg,
})
}
// wait for DNS measurements to complete
wg.Wait()
// start assembling the response
cresp := new(ctrlResponse)
select {
case cresp.DNS = <-dnsch:
default:
// we need to emit a non-nil Addrs to match exactly
// the behavior of the legacy TH
cresp.DNS = ctrlDNSResult{
Failure: nil,
Addrs: []string{},
}
}
// tcpconnect: start
tcpconnch := make(chan tcpResultPair, len(creq.TCPConnect))
for _, endpoint := range creq.TCPConnect {
wg.Add(1)
go tcpDo(ctx, &tcpConfig{
Endpoint: endpoint,
NewDialer: config.NewDialer,
Out: tcpconnch,
Wg: wg,
})
}
// http: start
httpch := make(chan ctrlHTTPResponse, 1)
wg.Add(1)
go httpDo(ctx, &httpConfig{
Headers: creq.HTTPRequestHeaders,
MaxAcceptableBody: config.MaxAcceptableBody,
NewClient: config.NewClient,
Out: httpch,
URL: creq.HTTPRequest,
Wg: wg,
})
// wait for endpoint measurements to complete
wg.Wait()
// continue assembling the response
cresp.HTTPRequest = <-httpch
cresp.TCPConnect = make(map[string]ctrlTCPResult)
Loop:
for {
select {
case tcpconn := <-tcpconnch:
cresp.TCPConnect[tcpconn.Endpoint] = tcpconn.Result
default:
break Loop
}
}
return cresp, nil
}