// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//go:build !build_with_native_toolchain

package netstack

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"sort"
	"strings"
	"sync/atomic"
	"syscall/zx"
	"syscall/zx/fidl"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/fidlconv"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/sync"
	zxtime "go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/time"
	"go.fuchsia.dev/fuchsia/src/lib/component"
	syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go"

	"fidl/fuchsia/net"
	"fidl/fuchsia/net/interfaces"

	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/stack"
)

const watcherProtocolName = "fuchsia.net.interfaces/Watcher"

func initialProperties(ifs *ifState, name string) interfaces.Properties {
	var p interfaces.Properties

	p.SetId(uint64(ifs.nicid))
	p.SetName(name)
	if ifs.endpoint.Capabilities()&stack.CapabilityLoopback != 0 {
		p.SetDeviceClass(interfaces.DeviceClassWithLoopback(interfaces.Empty{}))
	} else if ifs.controller != nil {
		p.SetDeviceClass(interfaces.DeviceClassWithDevice(ifs.controller.DeviceClass()))
	} else {
		panic(fmt.Sprintf("can't extract DeviceClass from non-loopback NIC %d(%s) with nil controller", ifs.nicid, name))
	}

	p.SetOnline(false)
	p.SetHasDefaultIpv4Route(false)
	p.SetHasDefaultIpv6Route(false)
	p.SetAddresses([]interfaces.Address{})

	return p
}

func hasAllSecondaryProperties(addr interfaces.Address) bool {
	return addr.HasValidUntil() && addr.HasPreferredLifetimeInfo()
}

var _ interfaces.WatcherWithCtx = (*interfaceWatcherImpl)(nil)

type interfaceWatcherImpl struct {
	cancelServe                 context.CancelFunc
	ready                       chan struct{}
	addrInterest                interfaces.AddressPropertiesInterest
	includeNonAssignedAddresses bool
	mu                          struct {
		sync.Mutex
		isHanging bool
		queue     []interfaces.Event
	}
}

const maxInterfaceWatcherQueueLen = 128

func (wi *interfaceWatcherImpl) onEvent(e interfaces.Event) {
	wi.mu.Lock()
	if len(wi.mu.queue) >= maxInterfaceWatcherQueueLen {
		_ = syslog.ErrorTf(watcherProtocolName, "too many unconsumed events (client may not be calling Watch as frequently as possible): %d, max: %d", len(wi.mu.queue), maxInterfaceWatcherQueueLen)
		wi.cancelServe()
	} else {
		wi.mu.queue = append(wi.mu.queue, e)
	}
	queueLen := len(wi.mu.queue)
	isHanging := wi.mu.isHanging
	wi.mu.Unlock()

	if queueLen > 0 && isHanging {
		select {
		case wi.ready <- struct{}{}:
		default:
		}
	}
}

// filterAddressesAndProperties returns a list of addresses with disinterested
// addresses and properties cleared.
//
// Does not modify addresses and returns a new slice.
func (wi *interfaceWatcherImpl) filterAddressesAndProperties(addresses []interfaces.Address) []interfaces.Address {
	rtn := make([]interfaces.Address, 0, len(addresses))
	clearValidUntil := !wi.addrInterest.HasBits(interfaces.AddressPropertiesInterestValidUntil)
	clearPreferredLifetimeInfo := !wi.addrInterest.HasBits(interfaces.AddressPropertiesInterestPreferredLifetimeInfo)
	for _, addr := range addresses {
		if !wi.includeNonAssignedAddresses {
			switch state := addr.GetAssignmentState(); state {
			case interfaces.AddressAssignmentStateAssigned:
			case interfaces.AddressAssignmentStateTentative, interfaces.AddressAssignmentStateUnavailable:
				// If the address is not assigned and the watcher does not want us to
				// include non-assigned addresses, skip the address.
				continue
			default:
				panic(fmt.Sprintf("unexpected assignment state = %d", state))
			}
		}

		if clearValidUntil {
			addr.ClearValidUntil()
		}
		if clearPreferredLifetimeInfo {
			addr.ClearPreferredLifetimeInfo()
		}
		rtn = append(rtn, addr)
	}
	return rtn
}

type assignmentStateChange int

const (
	_ assignmentStateChange = iota
	assignmentStateChangeInvolvingAssigned
	assignmentStateChangeNotInvolvingAssigned
	assignmentStateUnchangedAtAssigned
	assignmentStateUnchangedAtNonassigned
)

type changedAddressProperties struct {
	// When the address is added/removed, the interested properties field is
	// always zero since the only interesting event during such events in the
	// assignment state change.
	//
	// Note that we repurpose interfaces.AddressPropertiesInterest to hold the
	// fields that has changed instead of any specific watcher's interest in
	// address properties. This is so that we can easily check if the set of
	// changed properties intersects with a watcher's set of interested
	// properties.
	properties      interfaces.AddressPropertiesInterest
	assignmentState assignmentStateChange
}

func (c *changedAddressProperties) anyOfInterest(includeAllAddresses bool, includeProperties interfaces.AddressPropertiesInterest) bool {
	switch c.assignmentState {
	case assignmentStateChangeInvolvingAssigned:
		// All watchers receive updates if the state transitioned from/to assigned.
		return true
	case assignmentStateChangeNotInvolvingAssigned:
		// This is change where the previous and new state are both not assigned.
		// This change is only of interest to the watcher if they are interested
		// in all addresses. Note that the other address properties don't matter
		// here since if the address is not of interest to watchers, then property
		// changes aren't either for such addresses.
		return includeAllAddresses
	case assignmentStateUnchangedAtNonassigned:
		// If the addresses remained at an unassigned state and the watcher is not
		// interested in those addresses, then the properties are not of interest
		// either.
		if !includeAllAddresses {
			return false
		}
		fallthrough
	case assignmentStateUnchangedAtAssigned:
		// All watchers are interested in changes to assigned addresses so if the
		// properties changed, then it is of interest to the watcher.
		return c.properties&includeProperties != 0
	default:
		panic(fmt.Sprintf("unexpected assignment state change = %d", c.assignmentState))
	}
}

// onAddressesChanged handles an address for this watcher client.
//
// Does not modify addresses.
func (wi *interfaceWatcherImpl) onAddressesChanged(nicid tcpip.NICID, addresses []interfaces.Address, changes changedAddressProperties) {
	if !changes.anyOfInterest(wi.includeNonAssignedAddresses, wi.addrInterest) {
		// No changes of interest happened to the address.
		return
	}
	var changed interfaces.Properties
	changed.SetId(uint64(nicid))
	changed.SetAddresses(wi.filterAddressesAndProperties(addresses))
	wi.onEvent(interfaces.EventWithChanged(changed))
}

func cmpSubnet(ifAddr1 net.Subnet, ifAddr2 net.Subnet) int {
	switch ifAddr1.Addr.Which() {
	case net.IpAddressIpv4:
		if ifAddr2.Addr.Which() == net.IpAddressIpv6 {
			return -1
		}
		if diff := bytes.Compare(ifAddr1.Addr.Ipv4.Addr[:], ifAddr2.Addr.Ipv4.Addr[:]); diff != 0 {
			return diff
		}
	case net.IpAddressIpv6:
		if ifAddr2.Addr.Which() == net.IpAddressIpv4 {
			return 1
		}
		if diff := bytes.Compare(ifAddr1.Addr.Ipv6.Addr[:], ifAddr2.Addr.Ipv6.Addr[:]); diff != 0 {
			return diff
		}
	}
	if ifAddr1.PrefixLen < ifAddr2.PrefixLen {
		return -1
	} else if ifAddr1.PrefixLen > ifAddr2.PrefixLen {
		return 1
	}
	return 0
}

func (wi *interfaceWatcherImpl) Watch(ctx fidl.Context) (interfaces.Event, error) {
	wi.mu.Lock()
	defer wi.mu.Unlock()

	if wi.mu.isHanging {
		wi.cancelServe()
		return interfaces.Event{}, errors.New("not allowed to call Watcher.Watch when a call is already pending")
	}

	for {
		if len(wi.mu.queue) > 0 {
			event := wi.mu.queue[0]
			wi.mu.queue[0] = interfaces.Event{}
			wi.mu.queue = wi.mu.queue[1:]
			if len(wi.mu.queue) == 0 {
				// Drop the whole slice so that the backing array can be garbage
				// collected. Otherwise, the now-inaccessible front of wi.mu.queue could
				// be retained in memory forever.
				wi.mu.queue = nil
			}
			return event, nil
		}

		wi.mu.isHanging = true
		wi.mu.Unlock()

		var err error
		select {
		case <-wi.ready:
		case <-ctx.Done():
			err = fmt.Errorf("cancelled: %w", ctx.Err())
		}

		wi.mu.Lock()
		wi.mu.isHanging = false
		if err != nil {
			return interfaces.Event{}, err
		}
	}
}

type interfaceWatcherRequest struct {
	req     interfaces.WatcherWithCtxInterfaceRequest
	options interfaces.WatcherOptions
}

var _ interfaces.StateWithCtx = (*interfaceStateImpl)(nil)

type interfaceStateImpl struct {
	watcherChan chan<- interfaceWatcherRequest
}

func (si *interfaceStateImpl) GetWatcher(_ fidl.Context, options interfaces.WatcherOptions, watcher interfaces.WatcherWithCtxInterfaceRequest) error {
	si.watcherChan <- interfaceWatcherRequest{
		req:     watcher,
		options: options,
	}
	return nil
}

func fidlSubnetToString(s net.Subnet) string {
	return fidlconv.ToTCPIPAddressWithPrefix(s).String()
}

func preferredLifetimeInfoToString(p interfaces.PreferredLifetimeInfo) string {
	switch tag := p.Which(); tag {
	case interfaces.PreferredLifetimeInfoDeprecated:
		return "deprecated"
	case interfaces.PreferredLifetimeInfoPreferredUntil:
		return fmt.Sprintf("boot+%s", zxtime.Duration(p.PreferredUntil))
	default:
		panic(fmt.Sprintf("fuchsia.net.interfaces/PreferredLifetimeInfo with unknown tag: %d", tag))
	}
}

func addressToString(a interfaces.Address) string {
	var b strings.Builder

	if !a.HasAddr() {
		// Note that due to the lack of addr, this will not accidentally print an
		// address in bytes that prevents anonymization.
		panic(fmt.Sprintf("fuchsia.net.interfaces/Address must contain addr field: %#v", a))
	}
	b.WriteString(fmt.Sprintf("{Addr:%s", fidlSubnetToString(a.GetAddr())))
	if a.HasValidUntil() {
		b.WriteString(fmt.Sprintf(", ValidUntil:boot+%s", zxtime.Duration(a.GetValidUntil())))
	}
	if a.HasPreferredLifetimeInfo() {
		b.WriteString(fmt.Sprintf(", PreferredLifetimeInfo:%s", preferredLifetimeInfoToString(a.GetPreferredLifetimeInfo())))
	}
	b.WriteString("}")

	return b.String()
}

type interfaceEvent interface {
	isInterfaceEvent()
}

type interfaceAdded interfaces.Properties

var _ interfaceEvent = (*interfaceAdded)(nil)

func (*interfaceAdded) isInterfaceEvent() {}

func deviceClassToString(d interfaces.DeviceClass) string {
	switch tag := d.Which(); tag {
	case interfaces.DeviceClassLoopback:
		return "loopback"
	case interfaces.DeviceClassDevice:
		return d.Device.String()
	default:
		panic(fmt.Sprintf("fuchsia.net.interfaces/DeviceClass with unknown tag: %d", tag))
	}
}

func (a interfaceAdded) String() string {
	p := interfaces.Properties(a)
	var b strings.Builder

	if !p.HasId() {
		panic("fuchsia.net.interfaces/Properties missing id field")
	}

	b.WriteString(fmt.Sprintf("{Id:%d", p.GetId()))
	if p.HasName() {
		b.WriteString(fmt.Sprintf(", Name:%s", p.GetName()))
	}
	if p.HasDeviceClass() {
		b.WriteString(fmt.Sprintf(", DeviceClass:%s", deviceClassToString(p.GetDeviceClass())))
	}
	if p.HasOnline() {
		b.WriteString(fmt.Sprintf(", Online:%t", p.GetOnline()))
	}
	if p.HasHasDefaultIpv4Route() {
		b.WriteString(fmt.Sprintf(", HasDefaultIpv4Route:%t", p.GetHasDefaultIpv4Route()))
	}
	if p.HasHasDefaultIpv6Route() {
		b.WriteString(fmt.Sprintf(", HasDefaultIpv6Route:%t", p.GetHasDefaultIpv6Route()))
	}
	if p.HasAddresses() && len(p.GetAddresses()) > 0 {
		b.WriteString(", Addresses:[")
		for i, addr := range p.GetAddresses() {
			if i > 0 {
				b.WriteString(", ")
			}
			b.WriteString(addressToString(addr))
		}
		b.WriteString("]")
	}
	b.WriteString("}")

	return b.String()
}

type interfaceRemoved tcpip.NICID

var _ interfaceEvent = (*interfaceRemoved)(nil)

func (*interfaceRemoved) isInterfaceEvent() {}

type onlineChanged struct {
	nicid  tcpip.NICID
	online bool
}

var _ interfaceEvent = (*onlineChanged)(nil)

func (*onlineChanged) isInterfaceEvent() {}

type defaultRouteChanged struct {
	nicid               tcpip.NICID
	hasDefaultIPv4Route *bool
	hasDefaultIPv6Route *bool
}

var _ interfaceEvent = (*defaultRouteChanged)(nil)

func (*defaultRouteChanged) isInterfaceEvent() {}

func (c defaultRouteChanged) String() string {
	var b strings.Builder

	b.WriteString(fmt.Sprintf("{nicid:%d", c.nicid))
	if c.hasDefaultIPv4Route != nil {
		b.WriteString(fmt.Sprintf(", hasDefaultIPv4Route:%t", *c.hasDefaultIPv4Route))
	}
	if c.hasDefaultIPv6Route != nil {
		b.WriteString(fmt.Sprintf(", hasDefaultIPv6Route:%t", *c.hasDefaultIPv6Route))
	}
	b.WriteString("}")

	return b.String()
}

type addressProperties struct {
	lifetimes stack.AddressLifetimes
	state     stack.AddressAssignmentState
}

// isAddressAssigned returns whether an address is considered assigned.
func isAddressAssigned(state stack.AddressAssignmentState) bool {
	switch state {
	case stack.AddressAssigned:
		return true
	case stack.AddressDisabled, stack.AddressTentative:
		return false
	default:
		panic(fmt.Sprintf("unknown address assignment state: %d", state))
	}
}

type interfaceProperties struct {
	interfaces.Properties
	// addresses stores address properties that come from the gVisor stack.
	//
	// It is necessary to track these properties separately because IPv6
	// addresses in disabled or tentative state are hidden from clients
	// so such addresses are not present in the embedded Properties and
	// need to have their properties stored here.
	addresses map[tcpip.ProtocolAddress]addressProperties
}

func addressMapToSlice(addressMap map[tcpip.ProtocolAddress]addressProperties) []interfaces.Address {
	var addressSlice []interfaces.Address
	for protocolAddr, properties := range addressMap {
		var addr interfaces.Address
		addr.SetAddr(fidlconv.ToNetSubnet(protocolAddr.AddressWithPrefix))
		addr.SetValidUntil(int64(toZxTimeInfiniteIfZero(properties.lifetimes.ValidUntil)))
		info := func() interfaces.PreferredLifetimeInfo {
			if properties.lifetimes.Deprecated {
				return interfaces.PreferredLifetimeInfoWithDeprecated(interfaces.Empty{})
			} else {
				return interfaces.PreferredLifetimeInfoWithPreferredUntil(int64(toZxTimeInfiniteIfZero(properties.lifetimes.PreferredUntil)))
			}
		}()
		addr.SetPreferredLifetimeInfo(info)
		addr.SetAssignmentState(fidlconv.ToAddressAssignmentState(properties.state))
		addressSlice = append(addressSlice, addr)
	}

	sort.Slice(addressSlice, func(i, j int) bool {
		return cmpSubnet(addressSlice[i].GetAddr(), addressSlice[j].GetAddr()) <= 0
	})
	return addressSlice
}

func toZxTimeInfiniteIfZero(t tcpip.MonotonicTime) zx.Time {
	if t == (tcpip.MonotonicTime{}) {
		return zx.TimensecInfinite
	}
	return fidlconv.ToZxTime(t)
}

type fidlInterfaceWatcherStats struct {
	count atomic.Int64
}

func addedRemovedAddressChangeType(properties addressProperties) changedAddressProperties {
	var assignmentState assignmentStateChange
	if isAddressAssigned(properties.state) {
		assignmentState = assignmentStateChangeInvolvingAssigned
	} else {
		assignmentState = assignmentStateChangeNotInvolvingAssigned
	}
	return changedAddressProperties{assignmentState: assignmentState}
}

func addressesChangeType(previouslyKnown bool, prevProperties, nextProperties addressProperties) changedAddressProperties {
	if !previouslyKnown {
		// If the address was previously unknown, treat the "previous" assignment
		// state like it was some imaginary state indicating "not added".
		return addedRemovedAddressChangeType(nextProperties)
	}

	var properties interfaces.AddressPropertiesInterest
	if prevProperties.lifetimes.ValidUntil != nextProperties.lifetimes.ValidUntil {
		properties |= interfaces.AddressPropertiesInterestValidUntil
	}
	if prevProperties.lifetimes.Deprecated != nextProperties.lifetimes.Deprecated ||
		prevProperties.lifetimes.PreferredUntil != nextProperties.lifetimes.PreferredUntil {
		properties |= interfaces.AddressPropertiesInterestPreferredLifetimeInfo
	}

	assignmentState := func() assignmentStateChange {
		if prevProperties.state == nextProperties.state {
			if isAddressAssigned(nextProperties.state) {
				return assignmentStateUnchangedAtAssigned
			}
			return assignmentStateUnchangedAtNonassigned
		}

		if isAddressAssigned(prevProperties.state) || isAddressAssigned(nextProperties.state) {
			return assignmentStateChangeInvolvingAssigned
		}

		return assignmentStateChangeNotInvolvingAssigned
	}()

	return changedAddressProperties{
		properties:      properties,
		assignmentState: assignmentState,
	}
}

func interfaceWatcherEventLoop(
	ctx context.Context,
	eventChan <-chan interfaceEvent,
	watcherChan <-chan interfaceWatcherRequest,
	fidlInterfaceWatcherStats *fidlInterfaceWatcherStats,
) {
	if eventChan == nil {
		panic("cannot start interface watcher event loop with nil interface event channel")
	}
	if watcherChan == nil {
		panic("cannot start interface watcher event loop with nil watcher channel")
	}

	watchers := make(map[*interfaceWatcherImpl]struct{})
	propertiesMap := make(map[tcpip.NICID]interfaceProperties)
	watcherClosedChan := make(chan *interfaceWatcherImpl)
	watcherClosedFn := func(closedWatcher *interfaceWatcherImpl) {
		delete(watchers, closedWatcher)
		fidlInterfaceWatcherStats.count.Add(-1)
	}

	for {
		select {
		case <-ctx.Done():
			_ = syslog.InfoTf(watcherProtocolName, "stopping interface watcher event loop")

			// Wait for all watchers to close so that it is guaranteed that no
			// goroutines serving the interface watcher API are still running once
			// this function returns.
			for len(watchers) > 0 {
				watcherClosedFn(<-watcherClosedChan)
			}
			return
		case e := <-eventChan:
			switch event := e.(type) {
			case *interfaceAdded:
				added := interfaces.Properties(*event)
				if !added.HasId() {
					panic(fmt.Sprintf("interface added event with no ID: %s", event))
				}
				if len(added.GetAddresses()) > 0 {
					// This panic enforces that interfaces are never added
					// with addresses present, which enables the event loop to
					// not have to worry about address properties/assignment
					// state when handling interface-added events.
					panic(fmt.Sprintf("interface added event contains addresses: %s", event))
				}
				nicid := tcpip.NICID(added.GetId())
				if _, ok := propertiesMap[nicid]; ok {
					panic(fmt.Sprintf("interface already exists but duplicate added event received: %s", event))
				}
				propertiesMap[nicid] = interfaceProperties{
					Properties: added,
					addresses:  make(map[tcpip.ProtocolAddress]addressProperties),
				}
				for w := range watchers {
					properties := added
					// Since added interfaces must not have any addresses, explicitly set
					// the addresses field to nil instead of potentially copying a slice
					// of length 0.
					properties.SetAddresses(nil)
					w.onEvent(interfaces.EventWithAdded(properties))
				}
			case *interfaceRemoved:
				removed := tcpip.NICID(*event)
				syslog.InfoTf(watcherProtocolName, "interface removed event: %d", removed)
				if _, ok := propertiesMap[removed]; !ok {
					panic(fmt.Sprintf("unknown interface NIC=%d removed", removed))
					continue
				}
				delete(propertiesMap, removed)
				for w := range watchers {
					w.onEvent(interfaces.EventWithRemoved(uint64(removed)))
				}
			case *defaultRouteChanged:
				syslog.InfoTf(watcherProtocolName, "default route changed event: %s", event)

				properties, ok := propertiesMap[event.nicid]
				// TODO(https://fxbug.dev/42177477): Change to panic once interface properties
				// are guaranteed to not change after an interface is removed.
				if !ok {
					_ = syslog.WarnTf(watcherProtocolName, "default route changed event for unknown interface: %#v", event)
					break
				}
				// TODO(https://fxbug.dev/42177595): Once these events are only emitted when
				// the presence of a default route has actually changed, panic if the event
				// disagrees with our view of the world.
				var changes interfaces.Properties
				if event.hasDefaultIPv4Route != nil && properties.GetHasDefaultIpv4Route() != *event.hasDefaultIPv4Route {
					properties.SetHasDefaultIpv4Route(*event.hasDefaultIPv4Route)
					changes.SetHasDefaultIpv4Route(*event.hasDefaultIPv4Route)
				}
				if event.hasDefaultIPv6Route != nil && properties.GetHasDefaultIpv6Route() != *event.hasDefaultIPv6Route {
					properties.SetHasDefaultIpv6Route(*event.hasDefaultIPv6Route)
					changes.SetHasDefaultIpv6Route(*event.hasDefaultIPv6Route)
				}
				if changes.HasHasDefaultIpv4Route() || changes.HasHasDefaultIpv6Route() {
					propertiesMap[event.nicid] = properties
					changes.SetId(uint64(event.nicid))

					for w := range watchers {
						w.onEvent(interfaces.EventWithChanged(changes))
					}
				}
			case *onlineChanged:
				syslog.InfoTf(watcherProtocolName, "online changed event: %#v", event)

				properties, ok := propertiesMap[event.nicid]
				// TODO(https://fxbug.dev/42177477): Change to panic once interface properties
				// are guaranteed to not change after an interface is removed.
				if !ok {
					_ = syslog.WarnTf(watcherProtocolName, "online changed event for unknown interface: %#v", event)
					break
				}
				if event.online == properties.GetOnline() {
					// This assertion is possible because the event is always emitted under a
					// lock (so cannot race against itself), and the event is only emitted when
					// there is an actual change to the boolean value.
					panic(fmt.Sprintf("online changed event for interface with properties %#v with no actual change", properties))
				}

				properties.SetOnline(event.online)
				propertiesMap[event.nicid] = properties

				var changes interfaces.Properties
				changes.SetId(uint64(event.nicid))
				changes.SetOnline(event.online)
				for w := range watchers {
					w.onEvent(interfaces.EventWithChanged(changes))
				}
			case *addressChanged:
				properties, ok := propertiesMap[event.nicid]
				if !ok {
					panic(fmt.Sprintf("address changed event for unknown interface: %s", event))
				}
				nextProperties := addressProperties{state: event.state, lifetimes: event.lifetimes}
				prevProperties, found := properties.addresses[event.protocolAddr]
				properties.addresses[event.protocolAddr] = nextProperties
				addresses := addressMapToSlice(properties.addresses)
				properties.SetAddresses(addresses)
				propertiesMap[event.nicid] = properties

				// Due to the frequency of lifetime changes in certain environments, don't
				// log when the only difference is in address lifetimes in assigned state.
				if !found || nextProperties.state != prevProperties.state {
					syslog.InfoTf(watcherProtocolName, "address changed event: %s", event)
				}

				changes := addressesChangeType(found, prevProperties, nextProperties)
				if !changes.anyOfInterest(true, interfaces.AddressPropertiesInterest_Mask) {
					break
				}
				for w := range watchers {
					w.onAddressesChanged(event.nicid, addresses, changes)
				}
			case *addressRemoved:
				syslog.InfoTf(watcherProtocolName, "address removed event: %s", event)

				properties, ok := propertiesMap[event.nicid]
				if !ok {
					panic(fmt.Sprintf("address removed event for unknown interface: %s", event))
				}
				addrProperties, ok := properties.addresses[event.protocolAddr]
				if !ok {
					panic(fmt.Sprintf("address removed event for unknown address: %s", event))
				}
				delete(properties.addresses, event.protocolAddr)
				addresses := addressMapToSlice(properties.addresses)
				properties.SetAddresses(addresses)
				propertiesMap[event.nicid] = properties

				// Treat the new assignment state as if it was some imaginary state
				// indicating "not added".
				changes := addedRemovedAddressChangeType(addrProperties)
				for w := range watchers {
					w.onAddressesChanged(event.nicid, addresses, changes)
				}
			}
		case watcher := <-watcherChan:
			watcherCtx, cancel := context.WithCancel(ctx)
			impl := interfaceWatcherImpl{
				ready:                       make(chan struct{}, 1),
				cancelServe:                 cancel,
				addrInterest:                watcher.options.GetAddressPropertiesInterestWithDefault(0),
				includeNonAssignedAddresses: watcher.options.GetIncludeNonAssignedAddressesWithDefault(false),
			}
			impl.mu.queue = make([]interfaces.Event, 0, maxInterfaceWatcherQueueLen)

			for _, properties := range propertiesMap {
				// Filtering address properties returns a deep copy of the
				// addresses so that updates to the current interface state
				// don't accidentally change enqueued events.
				properties := properties.Properties
				properties.SetAddresses(impl.filterAddressesAndProperties(properties.GetAddresses()))
				impl.onEvent(interfaces.EventWithExisting(properties))
			}
			impl.mu.queue = append(impl.mu.queue, interfaces.EventWithIdle(interfaces.Empty{}))

			watchers[&impl] = struct{}{}
			fidlInterfaceWatcherStats.count.Add(1)

			go func() {
				defer cancel()
				component.Serve(watcherCtx, &interfaces.WatcherWithCtxStub{Impl: &impl}, watcher.req.Channel, component.ServeOptions{
					Concurrent: true,
					OnError: func(err error) {
						_ = syslog.WarnTf(watcherProtocolName, "%s", err)
					},
				})

				watcherClosedChan <- &impl
			}()
		case watcherClosed := <-watcherClosedChan:
			watcherClosedFn(watcherClosed)
		}
	}
}
