2021-02-02 12:05:47 +01:00
|
|
|
package webconnectivity
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2022-08-28 20:00:25 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/geoipx"
|
2022-11-21 16:28:53 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/httpapi"
|
2022-01-03 13:53:23 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/model"
|
2021-09-28 12:42:01 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
2022-11-21 16:28:53 +01:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
2021-02-02 12:05:47 +01:00
|
|
|
)
|
|
|
|
|
2022-08-28 20:20:12 +02:00
|
|
|
// Redirect to types defined inside the model package
|
|
|
|
type (
|
|
|
|
ControlRequest = model.THRequest
|
|
|
|
ControlResponse = model.THResponse
|
|
|
|
ControlDNSResult = model.THDNSResult
|
|
|
|
ControlHTTPRequestResult = model.THHTTPRequestResult
|
|
|
|
ControlTCPConnectResult = model.THTCPConnectResult
|
2022-08-28 13:49:24 +02:00
|
|
|
)
|
|
|
|
|
2021-02-02 12:05:47 +01:00
|
|
|
// Control performs the control request and returns the response.
|
|
|
|
func Control(
|
|
|
|
ctx context.Context, sess model.ExperimentSession,
|
2022-11-21 16:28:53 +01:00
|
|
|
testhelpers []model.OOAPIService, creq ControlRequest) (ControlResponse, *model.OOAPIService, error) {
|
|
|
|
seqCaller := httpapi.NewSequenceCaller(
|
|
|
|
httpapi.MustNewPOSTJSONWithJSONResponseDescriptor(sess.Logger(), "/", creq).WithBodyLogging(true),
|
|
|
|
httpapi.NewEndpointList(sess.DefaultHTTPClient(), sess.UserAgent(), testhelpers...)...,
|
|
|
|
)
|
2021-03-08 12:05:43 +01:00
|
|
|
sess.Logger().Infof("control for %s...", creq.HTTPRequest)
|
2022-11-21 16:28:53 +01:00
|
|
|
var out ControlResponse
|
|
|
|
idx, err := seqCaller.CallWithJSONResponse(ctx, &out)
|
|
|
|
sess.Logger().Infof("control for %s... %+v", creq.HTTPRequest, model.ErrorToStringOrOK(err))
|
2022-01-07 17:31:21 +01:00
|
|
|
if err != nil {
|
2022-11-21 16:28:53 +01:00
|
|
|
// make sure error is wrapped
|
2022-01-07 17:31:21 +01:00
|
|
|
err = netxlite.NewTopLevelGenericErrWrapper(err)
|
2022-11-21 16:28:53 +01:00
|
|
|
return ControlResponse{}, nil, err
|
2022-01-07 17:31:21 +01:00
|
|
|
}
|
2022-08-28 20:20:12 +02:00
|
|
|
fillASNs(&out.DNS)
|
2022-11-21 16:28:53 +01:00
|
|
|
runtimex.Assert(idx >= 0 && idx < len(testhelpers), "idx out of bounds")
|
|
|
|
return out, &testhelpers[idx], nil
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
|
2022-08-28 20:20:12 +02:00
|
|
|
// fillASNs fills the ASNs array of ControlDNSResult. For each Addr inside
|
2021-02-02 12:05:47 +01:00
|
|
|
// of the ControlDNSResult structure, we obtain the corresponding ASN.
|
|
|
|
//
|
|
|
|
// This is very useful to know what ASNs were the IP addresses returned by
|
|
|
|
// the control according to the probe's ASN database.
|
2022-08-28 20:20:12 +02:00
|
|
|
func fillASNs(dns *ControlDNSResult) {
|
2021-02-02 12:05:47 +01:00
|
|
|
dns.ASNs = []int64{}
|
|
|
|
for _, ip := range dns.Addrs {
|
2022-08-28 20:00:25 +02:00
|
|
|
asn, _, _ := geoipx.LookupASN(ip)
|
2021-02-02 12:05:47 +01:00
|
|
|
dns.ASNs = append(dns.ASNs, int64(asn))
|
|
|
|
}
|
|
|
|
}
|