bb6563f363
This commit moves the TH structs and definitions to model. We don't want oohelperd to depend on web_connectivity@v0.4. Part of https://github.com/ooni/probe/issues/2240
103 lines
2.9 KiB
Go
103 lines
2.9 KiB
Go
package main
|
|
|
|
//
|
|
// Generates IP and endpoint information.
|
|
//
|
|
|
|
import (
|
|
"net"
|
|
"net/url"
|
|
"sort"
|
|
"strings"
|
|
|
|
"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]*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] |= model.THIPInfoFlagResolvedByProbe
|
|
}
|
|
for _, addr := range addrs {
|
|
if net.ParseIP(addr) != nil {
|
|
discoveredby[addr] |= model.THIPInfoFlagResolvedByTH
|
|
}
|
|
}
|
|
ipinfo := make(map[string]*model.THIPInfo)
|
|
for addr, flags := range discoveredby {
|
|
if netxlite.IsBogon(addr) { // note: we already excluded non-IP addrs above
|
|
flags |= model.THIPInfoFlagIsBogon
|
|
}
|
|
asn, _, _ := geoipx.LookupASN(addr) // AS0 on failure
|
|
ipinfo[addr] = &model.THIPInfo{
|
|
ASN: int64(asn),
|
|
Flags: flags,
|
|
}
|
|
}
|
|
return ipinfo
|
|
}
|
|
|
|
// endpointInfo contains info about an endpoint to measure
|
|
type endpointInfo struct {
|
|
// Addr is the address to measure
|
|
Addr string
|
|
|
|
// Epnt is the endpoint to measure
|
|
Epnt string
|
|
|
|
// TLS indicates whether we should try using TLS
|
|
TLS bool
|
|
}
|
|
|
|
// ipInfoToEndpoints takes in input the [ipinfo] returned by newIPInfo
|
|
// and the [URL] provided by the probe to generate the list of endpoints
|
|
// to measure. We choose ports as follows:
|
|
//
|
|
// 1. if the input URL contains a port, we use such a port;
|
|
//
|
|
// 2. if the input URL scheme is "https", we choose port 443;
|
|
//
|
|
// 3. if the input URL scheme is "http", we use both 443 and 80, which
|
|
// allows us to include in the measurement information useful to determine
|
|
// 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]*model.THIPInfo) []endpointInfo {
|
|
var ports []string
|
|
if port := URL.Port(); port != "" {
|
|
ports = []string{port} // as documented
|
|
} else if URL.Scheme == "https" {
|
|
ports = []string{"443"} // as documented
|
|
} else if URL.Scheme == "http" {
|
|
ports = []string{"80", "443"} // as documented
|
|
}
|
|
out := []endpointInfo{}
|
|
for addr, info := range ipinfo {
|
|
if (info.Flags & model.THIPInfoFlagIsBogon) != 0 {
|
|
continue // as documented
|
|
}
|
|
for _, port := range ports {
|
|
epnt := net.JoinHostPort(addr, port)
|
|
out = append(out, endpointInfo{
|
|
Addr: addr,
|
|
Epnt: epnt,
|
|
TLS: port == "443",
|
|
})
|
|
}
|
|
}
|
|
// sort the output to make testing work deterministically since iterating
|
|
// a map in golang isn't guaranteed to return ordered keys
|
|
sort.SliceStable(out, func(i, j int) bool {
|
|
return strings.Compare(out[i].Epnt, out[j].Epnt) < 0
|
|
})
|
|
return out
|
|
}
|