{"record":{"id":"4d3218f8d0232388","repo":"AlexxIT/go2rtc","slug":"s-w-4d3218","errorCode":null,"errorMessage":"%s: %w","messagePattern":"%s: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/xiaomi/miss/cs2/conn.go","lineNumber":122,"sourceCode":"\t}\n\n\treturn conn, nil\n}\n\nfunc (c *Conn) worker() {\n\tdefer func() {\n\t\tc.channels[0].Close()\n\t\tc.channels[2].Close()\n\t}()\n\n\tvar keepaliveTS time.Time // only for TCP\n\n\tbuf := make([]byte, 1200)\n\n\tfor {\n\t\tn, err := c.Conn.Read(buf)\n\t\tif err != nil {\n\t\t\tc.err = fmt.Errorf(\"%s: %w\", \"cs2\", err)\n\t\t\treturn\n\t\t}\n\n\t\t// 0  f1d0  magic\n\t\t// 2  005d  size = total size + 4\n\t\t// 4  d1    magic\n\t\t// 5  00    channel\n\t\t// 6  0000  seq\n\t\tswitch buf[1] {\n\t\tcase msgDrw:\n\t\t\tch := buf[5]\n\t\t\tchannel := c.channels[ch]\n\n\t\t\tif c.isTCP {\n\t\t\t\t// For TCP we should send ping every second to keep connection alive.\n\t\t\t\t// Based on PCAP analysis: official Mi Home app sends PING every ~1s.\n\t\t\t\tif now := time.Now(); now.After(keepaliveTS) {\n\t\t\t\t\t_, _ = c.Conn.Write([]byte{magic, msgPing, 0, 0})","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/xiaomi/miss/cs2/conn.go#L104-L140","documentation":"This error wraps any error returned by the underlying TCP Conn.Read inside the cs2 connection's worker read loop. The library prefixes it with \"cs2\" so the wrapped net.Error (e.g. connection reset, EOF, timeout) remains inspectable via errors.Unwrap. It terminates the worker loop and is stored in c.err, surfacing to any caller reading from the connection afterward.","triggerScenarios":"The remote cs2 endpoint closes the TCP connection (EOF), resets it, times out, or the network drops while the worker goroutine is blocked in c.Conn.Read inside the read loop.","commonSituations":"Device/peer powers off or reboots mid-session; NAT or firewall silently drops an idle connection; keep-alive pings not being answered; server-side connection limit reached; mobile/unstable networks.","solutions":["Inspect the wrapped cause with errors.Unwrap(err) or errors.Is(err, net.ErrClosed) / os.IsTimeout to identify the transport failure","Check network reachability and firewall/NAT rules between client and the cs2 endpoint","Recreate the cs2 connection (the worker has exited; c.err is terminal) and resume, replaying any missed sequence numbers","Enable periodic pings (msgPing/msgPong are supported) to keep NAT mappings alive and detect dead peers early"],"exampleFix":"// before\nn, err := c.Conn.Read(buf)\nif err != nil {\n    c.err = fmt.Errorf(\"%s: %w\", \"cs2\", err)\n    return\n}\n// after\nn, err := c.Conn.Read(buf)\nif err != nil {\n    if errors.Is(err, io.EOF) || errors.Is(err, syscall.ECONNRESET) {\n        err = c.reconnect() // reconnect with backoff instead of surfacing raw error\n    } else {\n        c.err = fmt.Errorf(\"%s: %w\", \"cs2\", err)\n    }\n    return\n}","handlingStrategy":"try-catch","validationCode":"// Go: check connection liveness before read-heavy work\nfunc connAlive(c *net.TCPConn) bool {\n    if c == nil { return false }\n    return c.SetReadDeadline(time.Now().Add(time.Second)) == nil\n}","typeGuard":"func isConnErr(err error) bool {\n    var ne net.Error\n    return errors.As(err, &ne) || errors.Is(err, net.ErrClosed) || errors.Is(err, io.EOF)\n}","tryCatchPattern":"n, err := conn.Read(buf)\nif err != nil {\n    if isConnErr(err) {\n        // reconnect with backoff\n        err = reconnect()\n    }\n    return err\n}","preventionTips":["Set read/write deadlines on the connection to detect dead peers","Send periodic pings to keep NAT mappings alive","Monitor c.err and reconnect proactively","Log the unwrapped cause for diagnosis"],"tags":["network","tcp","connection","xiaomi-cs2"],"backgroundTag":"network-request-failed","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}