# 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
<Security>
  <UsernameToken>
    <Username>admin</Username>
    <Password Type="...#PasswordDigest">digest</Password>
    <Nonce EncodingType="...#Base64Binary">nonce</Nonce>
    <Created>2024-01-01T12:00:00Z</Created>
  </UsernameToken>
</Security>
```

### 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)
