Files
onvif/event/stream/doc.go
T. Tradesman 3634cee483 fix(event/stream): require real headroom and type the options error
Two gaps in the previous commit's guard.

Strict inequality was not enough. A client timeout one millisecond
above PullTimeout passed, and the test pinned that as valid — but the
client ceiling also has to cover dial, TLS and the response transfer on
top of the poll it outlasts, which on a cellular bearer is hundreds of
milliseconds. Require minClientHeadroom (5s) above PullTimeout.

The error was a bare fmt.Errorf, so callers could not tell it from the
transient pull/renew/recreate failures they retry. A consumer that
retries this one loops forever on a configuration that can never
succeed. ErrInvalidOptions is a sentinel they can short-circuit on.

Zero stays accepted: it is the SDK's default when a caller passes no
client, so rejecting it would break every default consumer. The comment
no longer claims that is safe — the caller interface documents that ctx
cannot interrupt an in-flight SOAP call, so an unbounded client is the
one case nothing can unwedge.
2026-07-23 14:56:20 +02:00

30 lines
1.2 KiB
Go

// Package stream is a typed, channel-based consumer for ONVIF device
// events. It hides the SOAP/XML, pull-point subscription lifecycle,
// subscription renewal and vendor-specific topic conventions behind a
// single Event stream.
//
// # Usage
//
// dev, _ := onvif.NewDevice(onvif.DeviceParams{Xaddr: "...", Username: "...", Password: "..."})
// s, err := stream.NewStream(ctx, dev, stream.Options{DeviceID: "front-door"})
// if err != nil { /* construction failed: auth, network, or no event support */ }
// defer s.Close()
//
// for ev := range s.Events() {
// switch ev.Kind {
// case stream.KindMotion:
// if ev.State == stream.StateActive { /* start recording */ }
// }
// }
//
// NewStream performs network I/O so auth and reachability failures
// surface synchronously, and rejects a client timeout that cannot
// outlast PullTimeout with ErrInvalidOptions. Events and Errors close when the Stream stops;
// Errors sends are non-blocking so a stalled consumer drops older
// errors rather than blocking the pull loop. After a silent reconnect,
// the next batch's events carry Event.AfterReconnect=true.
//
// See topics.go for the verified topic→Kind mapping across AXIS,
// Hikvision, Avigilon, Hanwha, Bosch and Dahua.
package stream