# go-onvif Architecture & Design ## Overview go-onvif is a modern, performant Go library for communicating with ONVIF-compliant IP cameras and devices. It provides a clean, type-safe API with comprehensive support for device management, media streaming, PTZ control, and imaging settings. ## Architecture ### Project Structure The project follows the **Standard Go Project Layout** for libraries: ``` onvif-go/ ├── *.go # Public API (client.go, device.go, media.go, ptz.go, imaging.go) ├── internal/ # Private implementation details │ └── soap/ # SOAP client (not exported) ├── discovery/ # Device discovery (public subpackage) ├── server/ # ONVIF server implementation (public subpackage) ├── cmd/ # Command-line tools ├── examples/ # Usage examples ├── docs/ # Documentation ├── testing/ # Testing helpers └── testdata/ # Test fixtures ``` **Design Rationale:** - **Root-level API**: Main package at root for clean imports (`github.com/0x524a/onvif-go`) - **internal/**: Private packages not intended for external use (SOAP implementation) - **Subpackages**: Additional features like `discovery/` and `server/` - **cmd/**: Executable applications and tools - **examples/**: Demonstrate library usage ### Core Components ``` ┌─────────────────────────────────────────────────────────────┐ │ Client Layer │ │ - onvif.Client: Main entry point │ │ - Context-aware operations │ │ - Connection pooling │ │ - Credential management │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ Service Layer │ │ - Device Service (device.go) │ │ - Media Service (media.go) │ │ - PTZ Service (ptz.go) │ │ - Imaging Service (imaging.go) │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ Transport Layer │ │ - SOAP Client (internal/soap/soap.go) │ │ - WS-Security Authentication │ │ - XML Marshaling/Unmarshaling │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ Network Layer │ │ - HTTP Client with connection pooling │ │ - TLS support │ │ - Timeout management │ └─────────────────────────────────────────────────────────────┘ ``` ### Discovery Component ``` ┌─────────────────────────────────────────────────────────────┐ │ WS-Discovery Service │ │ - Multicast UDP probe │ │ - Device enumeration │ │ - Service endpoint discovery │ └─────────────────────────────────────────────────────────────┘ ``` ## Key Design Decisions ### 1. Context-First Design All network operations accept `context.Context` as the first parameter, enabling: - Request cancellation - Timeout control - Request tracing - Graceful shutdown ```go ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() info, err := client.GetDeviceInformation(ctx) ``` ### 2. Functional Options Pattern Client configuration uses functional options for flexibility: ```go client, err := onvif.NewClient( endpoint, onvif.WithCredentials(username, password), onvif.WithTimeout(30*time.Second), onvif.WithHTTPClient(customClient), ) ``` ### 3. Type Safety Strong typing throughout the API with comprehensive struct definitions: - Clear data structures for all ONVIF types - Type-safe service methods - Compile-time error detection ### 4. Error Handling Multiple error handling strategies: - Sentinel errors for common cases (`ErrServiceNotSupported`, `ErrAuthenticationFailed`) - Typed `ONVIFError` for SOAP faults - Wrapped errors with context ```go if err := client.ContinuousMove(ctx, profileToken, velocity, nil); err != nil { if errors.Is(err, onvif.ErrServiceNotSupported) { // Handle missing PTZ support } else if onvif.IsONVIFError(err) { // Handle SOAP fault } } ``` ### 5. Concurrency Safety Thread-safe operations with proper locking: - Mutex-protected credential management - Safe concurrent API calls - Connection pool management ### 6. Performance Optimization Multiple performance optimizations: - HTTP connection pooling - Reusable HTTP client - Efficient XML marshaling - Minimal allocations in hot paths ## Service Implementations ### Device Service Provides device management functionality: - Device information retrieval - Capability discovery - System operations (reboot, date/time) - Service endpoint enumeration ### Media Service Handles media profiles and streaming: - Profile management - Stream URI generation (RTSP/HTTP) - Snapshot URI retrieval - Encoder configuration ### PTZ Service Controls pan-tilt-zoom operations: - Continuous movement - Absolute positioning - Relative positioning - Preset management - Status monitoring ### Imaging Service Manages image settings: - Brightness, contrast, saturation - Exposure control - Focus management - White balance - Wide dynamic range (WDR) ## Security ### WS-Security Implementation Authentication uses WS-Security UsernameToken with password digest: 1. Generate random nonce (16 bytes) 2. Get current UTC timestamp 3. Calculate digest: `Base64(SHA1(nonce + created + password))` 4. Include in SOAP header ```xml admin digest nonce 2024-01-01T12:00:00Z ``` ### Transport Security - Supports HTTP and HTTPS - Configurable TLS settings via custom HTTP client - Certificate validation control ## Discovery Protocol WS-Discovery implementation: 1. Send multicast probe to `239.255.255.250:3702` 2. Listen for probe matches 3. Parse device information from responses 4. Extract service endpoints (XAddrs) 5. Deduplicate devices by endpoint reference ## SOAP Message Flow ``` Client Request ↓ Build SOAP Envelope ↓ Add WS-Security Header (if authenticated) ↓ Marshal to XML ↓ HTTP POST ↓ Receive Response ↓ Parse SOAP Envelope ↓ Check for Fault ↓ Unmarshal Response Data ↓ Return to Caller ``` ## Testing Strategy ### Unit Tests - Client initialization and configuration - Error handling - Type validation - Option application ### Integration Tests (with mock servers) - SOAP message formatting - Response parsing - Error handling ### Real Device Tests - Full service workflows - PTZ operations - Media streaming - Discovery ## Performance Characteristics ### Benchmarks (typical) - Client creation: ~100 µs - SOAP call: ~10-50 ms (network dependent) - Discovery: ~1-5 seconds - Memory usage: ~1-5 MB per client ### Scalability - Supports hundreds of concurrent clients - Connection pooling reduces overhead - Minimal memory footprint per device ## Future Enhancements ### Planned Features - Event service (event subscription, pull-point) - Analytics service (rule engine, motion detection) - Recording service (recording management) - Replay service (playback control) - Advanced security (X.509 certificates) ### Optimizations - Response caching for static data - Batch operations support - Streaming data handling - WebSocket support for events ## Best Practices ### Client Lifecycle ```go // Create client once client, err := onvif.NewClient(endpoint, options...) if err != nil { return err } // Initialize to discover services if err := client.Initialize(ctx); err != nil { return err } // Reuse client for multiple operations // ... // No explicit cleanup needed (HTTP client manages connections) ``` ### Error Handling ```go info, err := client.GetDeviceInformation(ctx) if err != nil { // Check for specific errors if errors.Is(err, context.DeadlineExceeded) { // Handle timeout } return fmt.Errorf("failed to get device info: %w", err) } ``` ### Resource Management ```go // Use contexts with timeouts ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // Operations automatically respect context cancellation result, err := client.Operation(ctx, ...) ``` ## Dependencies Minimal external dependencies: - `golang.org/x/net`: HTTP/2 support and IDNA - `golang.org/x/text`: Character encoding - Go standard library: Everything else ## Compliance - **ONVIF Core Specification**: ✓ - **ONVIF Profile S** (Streaming): ✓ - **ONVIF Profile T** (Advanced Streaming): Partial - **ONVIF Profile G** (Recording): Planned - **WS-Security**: ✓ (UsernameToken) - **WS-Discovery**: ✓ ## Conclusion go-onvif provides a modern, performant, and easy-to-use Go library for ONVIF camera integration. Its architecture prioritizes: - Developer experience (simple, intuitive API) - Type safety (compile-time error detection) - Performance (connection pooling, efficient operations) - Reliability (comprehensive error handling) - Standards compliance (ONVIF specifications)