package prechecks import ( "time" "github.com/google/uuid" "github.com/cloudflare/cloudflared/connection" "github.com/cloudflare/cloudflared/edgediscovery/allregions" ) // Status represents the outcome of a single connectivity pre-check. type Status int const ( // Pass indicates the check completed successfully. Pass Status = iota // Fail indicates the check did not succeed. Whether this is a hard failure // or a degraded-but-functional state depends on which probe(s) failed — see // Report.hasHardFail and Report.hasWarn. Fail // Skip indicates the check was not executed because a prerequisite // check (typically DNS) failed first. Skip ) // String returns the canonical display name for a Status value. func (s Status) String() string { switch s { case Pass: return "PASS" case Fail: return "FAIL" case Skip: return "SKIP" default: return "UNKNOWN" } } // ProbeType identifies which connectivity probe produced a CheckResult. // It is used by hasHardFail and hasWarn to evaluate severity without // matching against human-readable strings. type ProbeType int const ( ProbeTypeDNS ProbeType = iota // DNS resolution ProbeTypeQUIC // UDP/QUIC transport ProbeTypeHTTP2 // TCP/HTTP2 transport ProbeTypeManagementAPI // Cloudflare management API ) // CheckResult holds the outcome of one individual connectivity probe. type CheckResult struct { // Type identifies which probe produced this result. Used for severity // classification in hasHardFail and hasWarn. Type ProbeType // Component is the human-readable probe category shown in the table header // column Component string // Target is the address or resource that was probed Target string // ProbeStatus is the outcome of the probe. ProbeStatus Status // Details is a short description of the result shown in the table Details string // Action is non-empty when ProbeStatus is Fail and contains a human-readable // remediation instruction Action string } // ResolvedTarget bundles a resolved edge target's addresses with the DNS // CheckResult that describes it. This keeps addr groups and their report rows // together as a single unit, avoiding parallel-slice synchronization. type ResolvedTarget struct { // Addrs holds the resolved edge addresses for this target. May be empty // when DNS resolution succeeded structurally but returned no IPs. Addrs []*allregions.EdgeAddr // DNSResult is the CheckResult representing DNS resolution for this target. // Its Target field is the human-readable label used across all probe rows. DNSResult CheckResult } // Report aggregates all CheckResults produced by a single Run() invocation. // Pre-checks run in parallel with tunnel initialization and are purely // diagnostic: the Report is displayed to the user but never gates startup. type Report struct { // RunID is a unique identifier for this pre-check run. It is included in // every structured log line so that all results from a single invocation // can be correlated across log aggregation systems. RunID uuid.UUID // Results contains one entry per executed probe, in the order they were // collected. Results []CheckResult // SuggestedProtocol is the connection protocol the pre-checks recommend // based on transport probe results. Nil when no valid protocol is available // (e.g., when both transports fail or DNS is unresolvable). SuggestedProtocol *connection.Protocol } // Config controls the behavior of a pre-check Run(). type Config struct { // Region is the optional cloudflared --region flag value. When non-empty // the pre-check probes the regional edge hostnames instead of the global ones. Region string // Timeout is the maximum wall-clock duration allowed for the entire // pre-check suite to complete. Timeout time.Duration // IPVersion controls which address families are probed for transport // checks. It mirrors the --edge-ip-version CLI flag so that the pre-check // exercises the same code paths the tunnel itself will use. IPVersion allregions.ConfigIPVersion // EdgeAddrs, when non-empty, contains the --edge flag values (explicit // edge addresses). When set, DNS probing is skipped entirely — there are // no SRV records to validate — and transport probes target each addr // individually, labeled with the original addr string. EdgeAddrs []string // ProtocolOverride is the raw --protocol flag value (e.g. "quic", // "http2", "h2mux"). When non-empty and not "auto", the pre-checks still // probe both transports for diagnostic completeness, but the reported // SuggestedProtocol honours the override so that the summary message // reflects what cloudflared will actually use — not what the probe // heuristic would recommend on its own. Parsing happens inside the // prechecks package. ProtocolOverride string }