diff --git a/internal/cmd/oohelper/internal/client.go b/internal/cmd/oohelper/internal/client.go index 1d0a690..f175d5c 100644 --- a/internal/cmd/oohelper/internal/client.go +++ b/internal/cmd/oohelper/internal/client.go @@ -11,7 +11,6 @@ import ( "net/url" "github.com/apex/log" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" "github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/netxlite" "github.com/ooni/probe-cli/v3/internal/runtimex" @@ -20,10 +19,10 @@ import ( type ( // CtrlResponse is the type of response returned by the test helper. - CtrlResponse = webconnectivity.ControlResponse + CtrlResponse = model.THResponse // ctrlRequest is the type of the request sent to the test helper. - ctrlRequest = webconnectivity.ControlRequest + ctrlRequest = model.THRequest ) // The following errors may be returned by this implementation. diff --git a/internal/cmd/oohelperd/dns.go b/internal/cmd/oohelperd/dns.go index 2e4cb24..ce4ef91 100644 --- a/internal/cmd/oohelperd/dns.go +++ b/internal/cmd/oohelperd/dns.go @@ -9,7 +9,6 @@ import ( "sync" "time" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" "github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/netxlite" "github.com/ooni/probe-cli/v3/internal/tracex" @@ -20,7 +19,7 @@ var newfailure = tracex.NewFailure // ctrlDNSResult is the result of the DNS check performed by // the Web Connectivity test helper. -type ctrlDNSResult = webconnectivity.ControlDNSResult +type ctrlDNSResult = model.THDNSResult // dnsConfig configures the DNS check. type dnsConfig struct { @@ -70,7 +69,7 @@ func dnsMapFailure(failure *string) *string { case netxlite.FailureDNSNXDOMAINError: // We have a name for this string because dnsanalysis.go is // already checking for this specific error string. - s := webconnectivity.DNSNameError + s := model.THDNSNameError return &s case netxlite.FailureDNSNoAnswer: // In this case the legacy TH would produce an empty diff --git a/internal/cmd/oohelperd/dns_test.go b/internal/cmd/oohelperd/dns_test.go index 9823eb2..c925cbe 100644 --- a/internal/cmd/oohelperd/dns_test.go +++ b/internal/cmd/oohelperd/dns_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" "github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/model/mocks" "github.com/ooni/probe-cli/v3/internal/netxlite" @@ -28,7 +27,7 @@ func Test_dnsMapFailure(t *testing.T) { }, { name: "nxdomain", failure: stringPointerForString(netxlite.FailureDNSNXDOMAINError), - want: stringPointerForString(webconnectivity.DNSNameError), + want: stringPointerForString(model.THDNSNameError), }, { name: "no answer", failure: stringPointerForString(netxlite.FailureDNSNoAnswer), @@ -79,7 +78,7 @@ func TestDNSDo(t *testing.T) { }, } }, - Out: make(chan webconnectivity.ControlDNSResult, 1), + Out: make(chan model.THDNSResult, 1), Wg: &sync.WaitGroup{}, } config.Wg.Add(1) diff --git a/internal/cmd/oohelperd/http.go b/internal/cmd/oohelperd/http.go index 43a34c2..9b987eb 100644 --- a/internal/cmd/oohelperd/http.go +++ b/internal/cmd/oohelperd/http.go @@ -23,7 +23,7 @@ import ( // ctrlHTTPResponse is the result of the HTTP check performed by // the Web Connectivity test helper. -type ctrlHTTPResponse = webconnectivity.ControlHTTPRequestResult +type ctrlHTTPResponse = model.THHTTPRequestResult // httpConfig configures the HTTP check. type httpConfig struct { diff --git a/internal/cmd/oohelperd/ipinfo.go b/internal/cmd/oohelperd/ipinfo.go index 75fe0c8..5b33a41 100644 --- a/internal/cmd/oohelperd/ipinfo.go +++ b/internal/cmd/oohelperd/ipinfo.go @@ -10,34 +10,34 @@ import ( "sort" "strings" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" "github.com/ooni/probe-cli/v3/internal/geoipx" + "github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/netxlite" ) // newIPInfo creates an IP to IPInfo mapping from addresses resolved // by the probe (inside [creq]) or the TH (inside [addrs]). -func newIPInfo(creq *ctrlRequest, addrs []string) map[string]*webconnectivity.ControlIPInfo { +func newIPInfo(creq *ctrlRequest, addrs []string) map[string]*model.THIPInfo { discoveredby := make(map[string]int64) for _, epnt := range creq.TCPConnect { addr, _, err := net.SplitHostPort(epnt) if err != nil || net.ParseIP(addr) == nil { continue } - discoveredby[addr] |= webconnectivity.ControlIPInfoFlagResolvedByProbe + discoveredby[addr] |= model.THIPInfoFlagResolvedByProbe } for _, addr := range addrs { if net.ParseIP(addr) != nil { - discoveredby[addr] |= webconnectivity.ControlIPInfoFlagResolvedByTH + discoveredby[addr] |= model.THIPInfoFlagResolvedByTH } } - ipinfo := make(map[string]*webconnectivity.ControlIPInfo) + ipinfo := make(map[string]*model.THIPInfo) for addr, flags := range discoveredby { if netxlite.IsBogon(addr) { // note: we already excluded non-IP addrs above - flags |= webconnectivity.ControlIPInfoFlagIsBogon + flags |= model.THIPInfoFlagIsBogon } asn, _, _ := geoipx.LookupASN(addr) // AS0 on failure - ipinfo[addr] = &webconnectivity.ControlIPInfo{ + ipinfo[addr] = &model.THIPInfo{ ASN: int64(asn), Flags: flags, } @@ -70,7 +70,7 @@ type endpointInfo struct { // whether an IP address is valid for a domain; // // 4. otherwise, we don't generate any endpoint to measure. -func ipInfoToEndpoints(URL *url.URL, ipinfo map[string]*webconnectivity.ControlIPInfo) []endpointInfo { +func ipInfoToEndpoints(URL *url.URL, ipinfo map[string]*model.THIPInfo) []endpointInfo { var ports []string if port := URL.Port(); port != "" { ports = []string{port} // as documented @@ -81,7 +81,7 @@ func ipInfoToEndpoints(URL *url.URL, ipinfo map[string]*webconnectivity.ControlI } out := []endpointInfo{} for addr, info := range ipinfo { - if (info.Flags & webconnectivity.ControlIPInfoFlagIsBogon) != 0 { + if (info.Flags & model.THIPInfoFlagIsBogon) != 0 { continue // as documented } for _, port := range ports { diff --git a/internal/cmd/oohelperd/ipinfo_test.go b/internal/cmd/oohelperd/ipinfo_test.go index ab1a965..5515c73 100644 --- a/internal/cmd/oohelperd/ipinfo_test.go +++ b/internal/cmd/oohelperd/ipinfo_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" + "github.com/ooni/probe-cli/v3/internal/model" ) func Test_newIPInfo(t *testing.T) { @@ -16,22 +16,22 @@ func Test_newIPInfo(t *testing.T) { tests := []struct { name string args args - want map[string]*webconnectivity.ControlIPInfo + want map[string]*model.THIPInfo }{{ name: "with empty input", args: args{ - creq: &webconnectivity.ControlRequest{ + creq: &model.THRequest{ HTTPRequest: "", HTTPRequestHeaders: map[string][]string{}, TCPConnect: []string{}, }, addrs: []string{}, }, - want: map[string]*webconnectivity.ControlIPInfo{}, + want: map[string]*model.THIPInfo{}, }, { name: "typical case with also bogons", args: args{ - creq: &webconnectivity.ControlRequest{ + creq: &model.THRequest{ HTTPRequest: "", HTTPRequestHeaders: map[string][]string{}, TCPConnect: []string{ @@ -44,24 +44,24 @@ func Test_newIPInfo(t *testing.T) { "8.8.4.4", }, }, - want: map[string]*webconnectivity.ControlIPInfo{ + want: map[string]*model.THIPInfo{ "10.0.0.1": { ASN: 0, - Flags: webconnectivity.ControlIPInfoFlagIsBogon | webconnectivity.ControlIPInfoFlagResolvedByProbe, + Flags: model.THIPInfoFlagIsBogon | model.THIPInfoFlagResolvedByProbe, }, "8.8.8.8": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByProbe | webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByProbe | model.THIPInfoFlagResolvedByTH, }, "8.8.4.4": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByTH, }, }, }, { name: "with invalid endpoint", args: args{ - creq: &webconnectivity.ControlRequest{ + creq: &model.THRequest{ HTTPRequest: "", HTTPRequestHeaders: map[string][]string{}, TCPConnect: []string{ @@ -70,11 +70,11 @@ func Test_newIPInfo(t *testing.T) { }, addrs: []string{}, }, - want: map[string]*webconnectivity.ControlIPInfo{}, + want: map[string]*model.THIPInfo{}, }, { name: "with invalid IP addr", args: args{ - creq: &webconnectivity.ControlRequest{ + creq: &model.THRequest{ HTTPRequest: "", HTTPRequestHeaders: map[string][]string{}, TCPConnect: []string{ @@ -83,7 +83,7 @@ func Test_newIPInfo(t *testing.T) { }, addrs: []string{}, }, - want: map[string]*webconnectivity.ControlIPInfo{}, + want: map[string]*model.THIPInfo{}, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -98,7 +98,7 @@ func Test_newIPInfo(t *testing.T) { func Test_ipInfoToEndpoints(t *testing.T) { type args struct { URL *url.URL - ipinfo map[string]*webconnectivity.ControlIPInfo + ipinfo map[string]*model.THIPInfo } tests := []struct { name string @@ -115,7 +115,7 @@ func Test_ipInfoToEndpoints(t *testing.T) { name: "with empty map and empty URL", args: args{ URL: &url.URL{}, - ipinfo: map[string]*webconnectivity.ControlIPInfo{}, + ipinfo: map[string]*model.THIPInfo{}, }, want: []endpointInfo{}, }, { @@ -124,18 +124,18 @@ func Test_ipInfoToEndpoints(t *testing.T) { URL: &url.URL{ Scheme: "http", }, - ipinfo: map[string]*webconnectivity.ControlIPInfo{ + ipinfo: map[string]*model.THIPInfo{ "10.0.0.1": { ASN: 0, - Flags: webconnectivity.ControlIPInfoFlagIsBogon | webconnectivity.ControlIPInfoFlagResolvedByProbe, + Flags: model.THIPInfoFlagIsBogon | model.THIPInfoFlagResolvedByProbe, }, "8.8.8.8": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByProbe | webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByProbe | model.THIPInfoFlagResolvedByTH, }, "8.8.4.4": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByTH, }, }, }, @@ -162,18 +162,18 @@ func Test_ipInfoToEndpoints(t *testing.T) { URL: &url.URL{ Host: "dns.google:5432", }, - ipinfo: map[string]*webconnectivity.ControlIPInfo{ + ipinfo: map[string]*model.THIPInfo{ "10.0.0.1": { ASN: 0, - Flags: webconnectivity.ControlIPInfoFlagIsBogon | webconnectivity.ControlIPInfoFlagResolvedByProbe, + Flags: model.THIPInfoFlagIsBogon | model.THIPInfoFlagResolvedByProbe, }, "8.8.8.8": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByProbe | webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByProbe | model.THIPInfoFlagResolvedByTH, }, "8.8.4.4": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByTH, }, }, }, @@ -190,18 +190,18 @@ func Test_ipInfoToEndpoints(t *testing.T) { name: "with addresses and some bogons, no port, and unknown scheme", args: args{ URL: &url.URL{}, - ipinfo: map[string]*webconnectivity.ControlIPInfo{ + ipinfo: map[string]*model.THIPInfo{ "10.0.0.1": { ASN: 0, - Flags: webconnectivity.ControlIPInfoFlagIsBogon | webconnectivity.ControlIPInfoFlagResolvedByProbe, + Flags: model.THIPInfoFlagIsBogon | model.THIPInfoFlagResolvedByProbe, }, "8.8.8.8": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByProbe | webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByProbe | model.THIPInfoFlagResolvedByTH, }, "8.8.4.4": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByTH, }, }, }, @@ -212,18 +212,18 @@ func Test_ipInfoToEndpoints(t *testing.T) { URL: &url.URL{ Scheme: "https", }, - ipinfo: map[string]*webconnectivity.ControlIPInfo{ + ipinfo: map[string]*model.THIPInfo{ "10.0.0.1": { ASN: 0, - Flags: webconnectivity.ControlIPInfoFlagIsBogon | webconnectivity.ControlIPInfoFlagResolvedByProbe, + Flags: model.THIPInfoFlagIsBogon | model.THIPInfoFlagResolvedByProbe, }, "8.8.8.8": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByProbe | webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByProbe | model.THIPInfoFlagResolvedByTH, }, "8.8.4.4": { ASN: 15169, - Flags: webconnectivity.ControlIPInfoFlagResolvedByTH, + Flags: model.THIPInfoFlagResolvedByTH, }, }, }, diff --git a/internal/cmd/oohelperd/measure.go b/internal/cmd/oohelperd/measure.go index c65ae4b..e11a043 100644 --- a/internal/cmd/oohelperd/measure.go +++ b/internal/cmd/oohelperd/measure.go @@ -10,15 +10,15 @@ import ( "net/url" "sync" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" + "github.com/ooni/probe-cli/v3/internal/model" ) type ( // ctrlRequest is the request sent to the test helper - ctrlRequest = webconnectivity.ControlRequest + ctrlRequest = model.THRequest // ctrlResponse is the response from the test helper - ctrlResponse = webconnectivity.ControlResponse + ctrlResponse = model.THResponse ) // measure performs the measurement described by the request and @@ -48,11 +48,11 @@ func measure(ctx context.Context, config *handler, creq *ctrlRequest) (*ctrlResp // start assembling the response cresp := &ctrlResponse{ - TCPConnect: map[string]webconnectivity.ControlTCPConnectResult{}, - TLSHandshake: map[string]webconnectivity.ControlTLSHandshakeResult{}, - HTTPRequest: webconnectivity.ControlHTTPRequestResult{}, - DNS: webconnectivity.ControlDNSResult{}, - IPInfo: map[string]*webconnectivity.ControlIPInfo{}, + TCPConnect: map[string]model.THTCPConnectResult{}, + TLSHandshake: map[string]model.THTLSHandshakeResult{}, + HTTPRequest: model.THHTTPRequestResult{}, + DNS: model.THDNSResult{}, + IPInfo: map[string]*model.THIPInfo{}, } select { case cresp.DNS = <-dnsch: @@ -111,7 +111,7 @@ Loop: if tcpconn.TLS != nil { cresp.TLSHandshake[tcpconn.Endpoint] = *tcpconn.TLS if info := cresp.IPInfo[tcpconn.Address]; info != nil && tcpconn.TLS.Failure == nil { - info.Flags |= webconnectivity.ControlIPInfoFlagValidForDomain + info.Flags |= model.THIPInfoFlagValidForDomain } } default: diff --git a/internal/cmd/oohelperd/tcpconnect.go b/internal/cmd/oohelperd/tcpconnect.go index fa20e29..bd71942 100644 --- a/internal/cmd/oohelperd/tcpconnect.go +++ b/internal/cmd/oohelperd/tcpconnect.go @@ -10,17 +10,16 @@ import ( "sync" "time" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" "github.com/ooni/probe-cli/v3/internal/measurexlite" "github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/netxlite" ) // ctrlTCPResult is the result of the TCP check performed by the test helper. -type ctrlTCPResult = webconnectivity.ControlTCPConnectResult +type ctrlTCPResult = model.THTCPConnectResult // ctrlTLSResult is the result of the TLS check performed by the test helper. -type ctrlTLSResult = webconnectivity.ControlTLSHandshakeResult +type ctrlTLSResult = model.THTLSHandshakeResult // tcpResultPair contains the endpoint and the corresponding result. type tcpResultPair struct { @@ -73,7 +72,7 @@ func tcpDo(ctx context.Context, config *tcpConfig) { out := &tcpResultPair{ Address: config.Address, Endpoint: config.Endpoint, - TCP: webconnectivity.ControlTCPConnectResult{}, + TCP: model.THTCPConnectResult{}, TLS: nil, // means: not measured } defer func() { diff --git a/internal/engine/experiment/webconnectivity/control.go b/internal/engine/experiment/webconnectivity/control.go index 639d76d..ccaf870 100644 --- a/internal/engine/experiment/webconnectivity/control.go +++ b/internal/engine/experiment/webconnectivity/control.go @@ -9,90 +9,15 @@ import ( "github.com/ooni/probe-cli/v3/internal/netxlite" ) -// TODO(bassosimone): these struct definitions should be moved outside the -// specific implementation of Web Connectivity v0.4. - -// ControlRequest is the request that we send to the control -type ControlRequest struct { - HTTPRequest string `json:"http_request"` - HTTPRequestHeaders map[string][]string `json:"http_request_headers"` - TCPConnect []string `json:"tcp_connect"` -} - -// ControlTCPConnectResult is the result of the TCP connect -// attempt performed by the control vantage point. -type ControlTCPConnectResult struct { - Status bool `json:"status"` - Failure *string `json:"failure"` -} - -// ControlTLSHandshakeResult is the result of the TLS handshake -// attempt performed by the control vantage point. -type ControlTLSHandshakeResult struct { - ServerName string `json:"server_name"` - Status bool `json:"status"` - Failure *string `json:"failure"` -} - -// ControlHTTPRequestResult is the result of the HTTP request -// performed by the control vantage point. -type ControlHTTPRequestResult struct { - BodyLength int64 `json:"body_length"` - Failure *string `json:"failure"` - Title string `json:"title"` - Headers map[string]string `json:"headers"` - StatusCode int64 `json:"status_code"` -} - -// TODO(bassosimone): ASNs and FillASNs are private implementation details of v0.4 -// that are actually ~annoying because we are mixing the data model with fields used -// by just the v0.4 client implementation. We should avoid repeating this mistake -// when implementing v0.5 of the client. - -// ControlDNSResult is the result of the DNS lookup -// performed by the control vantage point. -type ControlDNSResult struct { - Failure *string `json:"failure"` - Addrs []string `json:"addrs"` - ASNs []int64 `json:"-"` // not visible from the JSON -} - -// ControlIPInfo contains information about IP addresses resolved either -// by the probe or by the TH and processed by the TH. -type ControlIPInfo struct { - // ASN contains the address' AS number. - ASN int64 `json:"asn"` - - // Flags contains flags describing this address. - Flags int64 `json:"flags"` -} - -const ( - // ControlIPInfoFlagResolvedByProbe indicates that the probe has - // resolved this IP address. - ControlIPInfoFlagResolvedByProbe = 1 << iota - - // ControlIPInfoFlagResolvedByTH indicates that the test helper - // has resolved this IP address. - ControlIPInfoFlagResolvedByTH - - // ControlIPInfoFlagIsBogon indicates that the address is a bogon - ControlIPInfoFlagIsBogon - - // ControlIPInfoFlagValidForDomain indicates that an IP address - // is valid for the domain because it works with TLS - ControlIPInfoFlagValidForDomain +// Redirect to types defined inside the model package +type ( + ControlRequest = model.THRequest + ControlResponse = model.THResponse + ControlDNSResult = model.THDNSResult + ControlHTTPRequestResult = model.THHTTPRequestResult + ControlTCPConnectResult = model.THTCPConnectResult ) -// ControlResponse is the response from the control service. -type ControlResponse struct { - TCPConnect map[string]ControlTCPConnectResult `json:"tcp_connect"` - TLSHandshake map[string]ControlTLSHandshakeResult `json:"tls_handshake"` - HTTPRequest ControlHTTPRequestResult `json:"http_request"` - DNS ControlDNSResult `json:"dns"` - IPInfo map[string]*ControlIPInfo `json:"ip_info"` -} - // Control performs the control request and returns the response. func Control( ctx context.Context, sess model.ExperimentSession, @@ -110,16 +35,16 @@ func Control( err = netxlite.NewTopLevelGenericErrWrapper(err) } sess.Logger().Infof("control for %s... %+v", creq.HTTPRequest, model.ErrorToStringOrOK(err)) - (&out.DNS).FillASNs(sess) + fillASNs(&out.DNS) return } -// FillASNs fills the ASNs array of ControlDNSResult. For each Addr inside +// fillASNs fills the ASNs array of ControlDNSResult. For each Addr inside // 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. -func (dns *ControlDNSResult) FillASNs(sess model.ExperimentSession) { +func fillASNs(dns *ControlDNSResult) { dns.ASNs = []int64{} for _, ip := range dns.Addrs { asn, _, _ := geoipx.LookupASN(ip) diff --git a/internal/engine/experiment/webconnectivity/control_test.go b/internal/engine/experiment/webconnectivity/control_test.go index c166637..0276d3b 100644 --- a/internal/engine/experiment/webconnectivity/control_test.go +++ b/internal/engine/experiment/webconnectivity/control_test.go @@ -1,26 +1,23 @@ -package webconnectivity_test +package webconnectivity import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/ooni/probe-cli/v3/internal/engine/experiment/webconnectivity" - "github.com/ooni/probe-cli/v3/internal/engine/mockable" ) func TestFillASNsEmpty(t *testing.T) { - dns := new(webconnectivity.ControlDNSResult) - dns.FillASNs(new(mockable.Session)) + dns := new(ControlDNSResult) + fillASNs(dns) if diff := cmp.Diff(dns.ASNs, []int64{}); diff != "" { t.Fatal(diff) } } func TestFillASNsSuccess(t *testing.T) { - sess := newsession(t, false) - dns := new(webconnectivity.ControlDNSResult) + dns := new(ControlDNSResult) dns.Addrs = []string{"8.8.8.8", "1.1.1.1"} - dns.FillASNs(sess) + fillASNs(dns) if diff := cmp.Diff(dns.ASNs, []int64{15169, 13335}); diff != "" { t.Fatal(diff) } diff --git a/internal/engine/experiment/webconnectivity/dnsanalysis.go b/internal/engine/experiment/webconnectivity/dnsanalysis.go index f1ee86a..dd8f655 100644 --- a/internal/engine/experiment/webconnectivity/dnsanalysis.go +++ b/internal/engine/experiment/webconnectivity/dnsanalysis.go @@ -4,6 +4,7 @@ import ( "net" "net/url" + "github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/netxlite" ) @@ -14,7 +15,7 @@ type DNSAnalysisResult struct { } // DNSNameError is the error returned by the control on NXDOMAIN -const DNSNameError = "dns_name_error" +const DNSNameError = model.THDNSNameError var ( // DNSConsistent indicates that the measurement and the diff --git a/internal/model/th.go b/internal/model/th.go new file mode 100644 index 0000000..233eaf6 --- /dev/null +++ b/internal/model/th.go @@ -0,0 +1,85 @@ +package model + +// THDNSNameError is the error returned by the control on NXDOMAIN +const THDNSNameError = "dns_name_error" + +// THRequest is the request that we send to the control +type THRequest struct { + HTTPRequest string `json:"http_request"` + HTTPRequestHeaders map[string][]string `json:"http_request_headers"` + TCPConnect []string `json:"tcp_connect"` +} + +// THTCPConnectResult is the result of the TCP connect +// attempt performed by the control vantage point. +type THTCPConnectResult struct { + Status bool `json:"status"` + Failure *string `json:"failure"` +} + +// THTLSHandshakeResult is the result of the TLS handshake +// attempt performed by the control vantage point. +type THTLSHandshakeResult struct { + ServerName string `json:"server_name"` + Status bool `json:"status"` + Failure *string `json:"failure"` +} + +// THHTTPRequestResult is the result of the HTTP request +// performed by the control vantage point. +type THHTTPRequestResult struct { + BodyLength int64 `json:"body_length"` + Failure *string `json:"failure"` + Title string `json:"title"` + Headers map[string]string `json:"headers"` + StatusCode int64 `json:"status_code"` +} + +// TODO(bassosimone): ASNs is a private implementation detail of v0.4 +// that is actually ~annoying because we are mixing the data model with fields used +// by just the v0.4 client implementation. We should avoid repeating this mistake +// when implementing v0.5 of the client and eventually remove ASNs. + +// THDNSResult is the result of the DNS lookup +// performed by the control vantage point. +type THDNSResult struct { + Failure *string `json:"failure"` + Addrs []string `json:"addrs"` + ASNs []int64 `json:"-"` // not visible from the JSON +} + +// THIPInfo contains information about IP addresses resolved either +// by the probe or by the TH and processed by the TH. +type THIPInfo struct { + // ASN contains the address' AS number. + ASN int64 `json:"asn"` + + // Flags contains flags describing this address. + Flags int64 `json:"flags"` +} + +const ( + // THIPInfoFlagResolvedByProbe indicates that the probe has + // resolved this IP address. + THIPInfoFlagResolvedByProbe = 1 << iota + + // THIPInfoFlagResolvedByTH indicates that the test helper + // has resolved this IP address. + THIPInfoFlagResolvedByTH + + // THIPInfoFlagIsBogon indicates that the address is a bogon + THIPInfoFlagIsBogon + + // THIPInfoFlagValidForDomain indicates that an IP address + // is valid for the domain because it works with TLS + THIPInfoFlagValidForDomain +) + +// THResponse is the response from the control service. +type THResponse struct { + TCPConnect map[string]THTCPConnectResult `json:"tcp_connect"` + TLSHandshake map[string]THTLSHandshakeResult `json:"tls_handshake"` + HTTPRequest THHTTPRequestResult `json:"http_request"` + DNS THDNSResult `json:"dns"` + IPInfo map[string]*THIPInfo `json:"ip_info"` +}