package checker import ( "context" sdk "git.happydns.org/checker-sdk-go/checker" ) // c2sReachableRule verifies that at least one client-to-server endpoint // is reachable (TCP + TLS) and that no discovered c2s endpoint is down. type c2sReachableRule struct{} func (r *c2sReachableRule) Name() string { return "xmpp.c2s_reachable" } func (r *c2sReachableRule) Description() string { return "Verifies that at least one client-to-server endpoint accepts TCP and completes TLS." } func (r *c2sReachableRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) []sdk.CheckState { return evaluateReachable(ctx, obs, opts, ModeClient) } // s2sReachableRule is the s2s counterpart. type s2sReachableRule struct{} func (r *s2sReachableRule) Name() string { return "xmpp.s2s_reachable" } func (r *s2sReachableRule) Description() string { return "Verifies that at least one server-to-server endpoint accepts TCP and completes TLS." } func (r *s2sReachableRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) []sdk.CheckState { return evaluateReachable(ctx, obs, opts, ModeServer) } func evaluateReachable(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions, mode XMPPMode) []sdk.CheckState { data, errSt := loadXMPPData(ctx, obs) if errSt != nil { return []sdk.CheckState{*errSt} } wantC2S, wantS2S := wantsFromOpts(opts) if mode == ModeClient && !wantC2S { return []sdk.CheckState{notTestedState("xmpp.c2s_reachable.skipped", "c2s not in scope for the selected mode.")} } if mode == ModeServer && !wantS2S { return []sdk.CheckState{notTestedState("xmpp.s2s_reachable.skipped", "s2s not in scope for the selected mode.")} } // Per-endpoint TCP unreachable states for this mode. var states []sdk.CheckState anyForMode := false for _, ep := range data.Endpoints { if ep.Mode != mode { continue } anyForMode = true if !ep.TCPConnected && ep.Error != "" { states = append(states, sdk.CheckState{ Status: sdk.StatusWarn, Message: "Cannot reach " + ep.Address + ": " + ep.Error + ".", Code: CodeTCPUnreachable, Subject: ep.Address, Meta: map[string]any{"fix": "Verify firewall rules and that the XMPP server is listening on this address."}, }) } } if !anyForMode { return []sdk.CheckState{{ Status: sdk.StatusCrit, Message: "No " + string(mode) + " endpoint discovered to probe.", Code: CodeNoSRV, }} } working := data.Coverage.WorkingC2S if mode == ModeServer { working = data.Coverage.WorkingS2S } if !working { states = append(states, sdk.CheckState{ Status: sdk.StatusCrit, Message: "No working " + string(mode) + " endpoint (TCP + TLS).", Code: CodeAllEndpointsDown, }) } if len(states) == 0 { code := "xmpp.c2s_reachable.ok" if mode == ModeServer { code = "xmpp.s2s_reachable.ok" } return []sdk.CheckState{passState(code, "At least one "+string(mode)+" endpoint is reachable and completes TLS.")} } return states }