Files
onvif-go/docs/NETWORK_INTERFACE_IMPLEMENTATION.md
T
ProtoTess dfa113ad6d docs: add network interface implementation summary
Add comprehensive implementation summary document including:
- Problem statement and solution overview
- Implementation details and file changes
- API reference and type definitions
- Usage examples and common scenarios
- Testing results and verification
- Benefits and future enhancements

This documents the complete network interface selection feature
implementation for WS-Discovery multicast discovery.
2025-11-17 17:35:19 +00:00

8.9 KiB

Network Interface Discovery Feature - Implementation Summary

Overview

Successfully implemented network interface selection for ONVIF device discovery via WS-Discovery multicast. This feature allows users to explicitly specify which network interface to use when discovering cameras on their network.

Problem Statement

Users with multiple active network interfaces (Ethernet, WiFi, Virtual Adapters, etc.) often encounter situations where the auto-detected network interface isn't the one connected to their cameras. This results in failed discovery despite cameras being present on another network segment.

Solution

Added optional DiscoverOptions parameter to discovery functions, allowing users to:

  • Specify interface by name (e.g., "eth0", "wlan0")
  • Specify interface by IP address (e.g., "192.168.1.100")
  • Enumerate all available interfaces with metadata
  • Get helpful error messages listing available options

Implementation Details

Files Modified

discovery/discovery.go

  • Added DiscoverOptions struct with NetworkInterface field
  • Added DiscoverWithOptions() function for interface-specific discovery
  • Added ListNetworkInterfaces() public function
  • Added resolveNetworkInterface() helper function
  • Maintained backward compatibility with existing Discover() function

discovery/discovery_test.go

  • Added comprehensive test suite (6 unit tests + 2 benchmarks)
  • Tests cover: listing, resolution by name, resolution by IP, error handling
  • All tests passing (3.009s runtime)

Files Created

discovery/NETWORK_INTERFACE_GUIDE.md

  • Comprehensive usage guide with examples
  • API reference documentation
  • Common scenarios and troubleshooting
  • Best practices and error handling patterns
  • 400+ lines of detailed documentation

QUICKSTART.md (Updated)

  • Added network interface discovery section
  • Included examples for all three usage patterns
  • Cross-reference to detailed guide

API Reference

New Functions

// Discover with custom options
func DiscoverWithOptions(ctx context.Context, timeout time.Duration, 
    opts *DiscoverOptions) ([]*Device, error)

// List all available interfaces
func ListNetworkInterfaces() ([]NetworkInterface, error)

New Types

type DiscoverOptions struct {
    // NetworkInterface specifies which interface to use
    // Examples: "eth0", "192.168.1.100"
    // Empty string = system default
    NetworkInterface string
}

type NetworkInterface struct {
    Name       string     // "eth0", "wlan0", etc.
    Addresses  []string   // IP addresses
    Up         bool       // Is interface up?
    Multicast  bool       // Supports multicast?
}

Backward Compatibility

The existing Discover() function continues to work unchanged:

// Old code still works
devices, err := discovery.Discover(ctx, 5*time.Second)

// New code with options
opts := &discovery.DiscoverOptions{NetworkInterface: "eth0"}
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)

Usage Examples

List Available Interfaces

interfaces, err := discovery.ListNetworkInterfaces()
for _, iface := range interfaces {
    fmt.Printf("%s: up=%v, multicast=%v, ips=%v\n",
        iface.Name, iface.Up, iface.Multicast, iface.Addresses)
}

Discover on Specific Interface

// By interface name
opts := &discovery.DiscoverOptions{NetworkInterface: "eth0"}
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)

// By IP address
opts := &discovery.DiscoverOptions{NetworkInterface: "192.168.1.100"}
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)

Error Handling

opts := &discovery.DiscoverOptions{NetworkInterface: "invalid-interface"}
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)
if err != nil {
    // Error includes list of available interfaces
    fmt.Println(err)
    // Output: network interface "invalid-interface" not found.
    //         Available interfaces: [eth0 [192.168.1.100] wlan0 [192.168.88.50] ...]
}

Testing Results

=== RUN   TestListNetworkInterfaces
    discovery_test.go:279: Found 3 network interface(s)
    discovery_test.go:281:   - lo: up=true, multicast=false, addresses=[127.0.0.1 ::1]
    discovery_test.go:281:   - eth0: up=true, multicast=true, addresses=[10.0.0.27 fe80::...]
    discovery_test.go:281:   - docker0: up=true, multicast=true, addresses=[172.17.0.1]
--- PASS: TestListNetworkInterfaces (0.00s)

=== RUN   TestResolveNetworkInterface
=== RUN   TestResolveNetworkInterface/loopback_by_name
    discovery_test.go:328: Resolved lo to interface: lo
=== RUN   TestResolveNetworkInterface/loopback_by_ip
    discovery_test.go:328: Resolved 127.0.0.1 to interface: lo
=== RUN   TestResolveNetworkInterface/invalid_interface
--- PASS: TestResolveNetworkInterface (0.00s)

=== RUN   TestDiscoverWithOptions_DefaultOptions
--- PASS: TestDiscoverWithOptions_DefaultOptions (1.00s)

=== RUN   TestDiscoverWithOptions_NilOptions
--- PASS: TestDiscoverWithOptions_NilOptions (0.50s)

=== RUN   TestDiscoverWithOptions_LoopbackInterface
--- PASS: TestDiscoverWithOptions_LoopbackInterface (0.50s)

=== RUN   TestDiscoverWithOptions_InvalidInterface
    discovery_test.go:407: Got expected error: failed to resolve network interface:...
--- PASS: TestDiscoverWithOptions_InvalidInterface (0.00s)

=== RUN   TestDiscover_BackwardCompatibility
    discovery_test.go:424: Backward compat: found 0 devices
--- PASS: TestDiscover_BackwardCompatibility (0.50s)

PASS
ok      github.com/0x524a/onvif-go/discovery    3.009s

Common Use Cases

Scenario 1: Multiple Network Adapters

// List all to find the right one
interfaces, _ := discovery.ListNetworkInterfaces()
for _, iface := range interfaces {
    opts := &discovery.DiscoverOptions{NetworkInterface: iface.Name}
    devices, _ := discovery.DiscoverWithOptions(ctx, 2*time.Second, opts)
    if len(devices) > 0 {
        fmt.Printf("Found %d devices on %s\n", len(devices), iface.Name)
    }
}

Scenario 2: Docker Container with Multiple Networks

// Use specific bridge network IP
opts := &discovery.DiscoverOptions{
    NetworkInterface: "172.20.0.10",  // Custom bridge network
}
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)

Scenario 3: CLI Tool with User Selection

// Command: ./app -interface eth0
interfaces, _ := discovery.ListNetworkInterfaces()
opts := &discovery.DiscoverOptions{
    NetworkInterface: userInputFlag,
}
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)

Benefits

Solves Real Problem: Users with multiple interfaces can now find cameras reliably
Backward Compatible: Existing code continues to work unchanged
Flexible: Supports interface names and IP addresses
User-Friendly: Helpful error messages with available options
Well-Documented: Comprehensive guide with examples
Well-Tested: 6 unit tests + 2 benchmarks + backward compatibility test
Production-Ready: No external dependencies, uses standard library only

Documentation

  • Detailed Guide: discovery/NETWORK_INTERFACE_GUIDE.md (400+ lines with examples)
  • Quick Start: QUICKSTART.md - Updated with network interface examples
  • API Docs: Inline code comments with examples
  • Tests: discovery/discovery_test.go - Serve as additional usage examples

Commits

  1. c384dca: feat: add network interface selection to WS-Discovery

    • Core implementation of all new functions
    • Comprehensive test suite
    • NETWORK_INTERFACE_GUIDE.md created
  2. d6e5cbd: docs: add network interface discovery section to QUICKSTART

    • Updated QUICKSTART.md with examples
    • Cross-references to detailed guide

Future Enhancements

Possible future improvements:

  • Support for interface filtering (up/down, multicast capability)
  • Async discovery across multiple interfaces
  • Caching of interface list
  • Event-based interface change detection
  • IPv6-only discovery option
  • Custom multicast group selection
  • Addresses user request: "For the discovery, lets add an option that the user should be able to define the Network Interface on which we can send the Multicast messages"
  • Part of PR #30: Network Interface Selection for Discovery
  • Built on top of PR #29: Complete branding consistency

Verification Checklist

Implementation complete
All tests passing (3.009s)
Backward compatibility verified
No unused variables or imports
Error handling comprehensive
Documentation complete (400+ lines)
Examples provided for all features
Changes committed and pushed
Code follows Go standards
No external dependencies added

Summary

Successfully implemented network interface selection for ONVIF device discovery. The feature is production-ready, well-documented, fully backward compatible, and comprehensively tested. Users can now reliably discover cameras when multiple network interfaces are active on their systems.