// 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
// +build !build_with_native_toolchain

package netstack

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

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/fidlconv"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routes"
	"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/header"
	"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
	"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
	tcpipstack "gvisor.dev/gvisor/pkg/tcpip/stack"
)

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

// addressPatch is a patch to the address data exposed by upstream interface
// data. This type provides a mechanism by which clients of onPropertiesChange
// can extend the data exposed by fuchsia.net.interfaces beyond what is
// available in the upstream interface representation. At the the time of this
// writing, there is only need for an extension to Address data; should more
// general extensions be needed, a properties patch type which composes this
// type may be called for.
type addressPatch struct {
	addr       tcpip.AddressWithPrefix
	validUntil time.Time
}

func makeInterfacesAddress(protocolAddr tcpip.ProtocolAddress, validUntil time.Time) interfaces.Address {
	switch protocolAddr.Protocol {
	case ipv4.ProtocolNumber:
	case ipv6.ProtocolNumber:
	default:
		panic(fmt.Sprintf("makeInterfaceAddress(%+v, %s): unknown protocol", protocolAddr, validUntil))
	}

	var addr interfaces.Address
	addr.SetAddr(net.Subnet{
		Addr:      fidlconv.ToNetIpAddress(protocolAddr.AddressWithPrefix.Address),
		PrefixLen: uint8(protocolAddr.AddressWithPrefix.PrefixLen),
	})
	addr.SetValidUntil(validUntil.MonotonicNano())
	return addr
}

func interfaceProperties(nicInfo tcpipstack.NICInfo, hasDefaultIPv4Route, hasDefaultIPv6Route bool, addressPatches []addressPatch) interfaces.Properties {
	var p interfaces.Properties
	ifs := nicInfo.Context.(*ifState)
	p.SetId(uint64(ifs.nicid))
	p.SetName(nicInfo.Name)
	p.SetHasDefaultIpv4Route(hasDefaultIPv4Route)
	p.SetHasDefaultIpv6Route(hasDefaultIPv6Route)

	if ifs.endpoint.Capabilities()&tcpipstack.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, nicInfo.Name))
	}

	ifs.mu.Lock()
	p.SetOnline(ifs.IsUpLocked())
	ifs.mu.Unlock()

	var addrs []interfaces.Address
	for _, a := range nicInfo.ProtocolAddresses {
		addr := makeInterfacesAddress(a, time.Monotonic(int64(zx.TimensecInfinite)))
		for _, p := range addressPatches {
			if p.addr == a.AddressWithPrefix {
				addr.SetValidUntil(p.validUntil.MonotonicNano())
				break
			}
		}
		addrs = append(addrs, addr)
	}
	sort.Slice(addrs, func(i, j int) bool {
		return cmpSubnet(addrs[i].GetAddr(), addrs[j].GetAddr()) <= 0
	})
	p.SetAddresses(addrs)

	return p
}

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

type interfaceWatcherImpl struct {
	cancelServe context.CancelFunc
	ready       chan struct{}
	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.WarnTf(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:
		}
	}
}

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

func emptyInterfaceProperties(p interfaces.Properties) bool {
	return !(p.HasId() || p.HasAddresses() || p.HasOnline() || p.HasDeviceClass() || p.HasHasDefaultIpv4Route() || p.HasHasDefaultIpv6Route())
}

// Diff two interface properties. The return value will have no fields present
// if there is no difference. The return value may contain references to fields
// in p2.
func diffInterfaceProperties(p1, p2 interfaces.Properties) interfaces.Properties {
	var diff interfaces.Properties
	if p1.GetOnline() != p2.GetOnline() {
		diff.SetOnline(p2.GetOnline())
	}
	if p1.GetHasDefaultIpv4Route() != p2.GetHasDefaultIpv4Route() {
		diff.SetHasDefaultIpv4Route(p2.GetHasDefaultIpv4Route())
	}
	if p1.GetHasDefaultIpv6Route() != p2.GetHasDefaultIpv6Route() {
		diff.SetHasDefaultIpv6Route(p2.GetHasDefaultIpv6Route())
	}
	if func() bool {
		if len(p2.GetAddresses()) != len(p1.GetAddresses()) {
			return true
		}
		for i, addr := range p1.GetAddresses() {
			p2Addr := p2.GetAddresses()[i]
			if cmpSubnet(addr.GetAddr(), p2Addr.GetAddr()) != 0 {
				return true
			}
			if addr.GetValidUntil() != p2Addr.GetValidUntil() {
				return true
			}
		}
		return false
	}() {
		diff.SetAddresses(p2.GetAddresses())
	}
	if !emptyInterfaceProperties(diff) {
		diff.SetId(p2.GetId())
	}
	return diff
}

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 = wi.mu.queue[1:]
			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 interfaceWatcherCollection struct {
	mu struct {
		sync.Mutex
		lastObserved map[tcpip.NICID]interfaces.Properties
		watchers     map[*interfaceWatcherImpl]struct{}
	}
}

func (wc *interfaceWatcherCollection) onPropertiesChangeLocked(nicid tcpip.NICID, nicInfo tcpipstack.NICInfo, addressPatches []addressPatch) {
	if properties, ok := wc.mu.lastObserved[nicid]; ok {
		newProperties := interfaceProperties(nicInfo, properties.GetHasDefaultIpv4Route(), properties.GetHasDefaultIpv6Route(), addressPatches)
		if diff := diffInterfaceProperties(properties, newProperties); !emptyInterfaceProperties(diff) {
			wc.mu.lastObserved[nicid] = newProperties
			for w := range wc.mu.watchers {
				w.onEvent(interfaces.EventWithChanged(diff))
			}
		}
	} else {
		_ = syslog.WarnTf(watcherProtocolName, "onPropertiesChange called regarding unknown interface %d", nicid)
	}
}

// onAddressAdd is called when an address is added.
//
// If performed, DAD must have completed successfully before calling this function, as the
// presence of an address indicates to clients that the address can be used.
func (wc *interfaceWatcherCollection) onAddressAdd(nicid tcpip.NICID, protocolAddr tcpip.ProtocolAddress, validUntil time.Time) {
	wc.mu.Lock()
	defer wc.mu.Unlock()

	properties, ok := wc.mu.lastObserved[nicid]
	if !ok {
		_ = syslog.Warnf("onAddressAdd(%d, %+v, %s): NIC no longer exists", nicid, protocolAddr, validUntil)
		return
	}

	if addrs, changed := func() ([]interfaces.Address, bool) {
		if !properties.HasAddresses() {
			return nil, true
		} else {
			addrs := properties.GetAddresses()
			for _, a := range addrs {
				subnet := a.GetAddr()
				foundAddrWithPrefix := tcpip.AddressWithPrefix{
					Address:   fidlconv.ToTCPIPAddress(subnet.Addr),
					PrefixLen: int(subnet.PrefixLen),
				}
				if foundAddrWithPrefix == protocolAddr.AddressWithPrefix {
					_ = syslog.Warnf("onAddressAdd(%d, %+v, %s): address %+v already exists", nicid, protocolAddr, validUntil, foundAddrWithPrefix)
					return nil, false
				}
			}
			return addrs, true
		}
	}(); changed {
		addrs = append(addrs, makeInterfacesAddress(protocolAddr, validUntil))
		sort.Slice(addrs, func(i, j int) bool {
			return cmpSubnet(addrs[i].GetAddr(), addrs[j].GetAddr()) <= 0
		})
		properties.SetAddresses(addrs)
		wc.mu.lastObserved[nicid] = properties

		var diff interfaces.Properties
		diff.SetId(uint64(nicid))
		diff.SetAddresses(addrs)

		for w := range wc.mu.watchers {
			w.onEvent(interfaces.EventWithChanged(diff))
		}
	}
}

func (wc *interfaceWatcherCollection) onDefaultRouteChangeLocked(routes []routes.ExtendedRoute) {
	v4DefaultRoute := make(map[tcpip.NICID]struct{})
	v6DefaultRoute := make(map[tcpip.NICID]struct{})
	for _, er := range routes {
		if er.Enabled {
			if er.Route.Destination.Equal(header.IPv4EmptySubnet) {
				v4DefaultRoute[er.Route.NIC] = struct{}{}
			} else if er.Route.Destination.Equal(header.IPv6EmptySubnet) {
				v6DefaultRoute[er.Route.NIC] = struct{}{}
			}
		}
	}

	for nicid, properties := range wc.mu.lastObserved {
		var diff interfaces.Properties
		diff.SetId(uint64(nicid))
		if _, ok := v4DefaultRoute[nicid]; ok != properties.GetHasDefaultIpv4Route() {
			properties.SetHasDefaultIpv4Route(ok)
			diff.SetHasDefaultIpv4Route(ok)
		}
		if _, ok := v6DefaultRoute[nicid]; ok != properties.GetHasDefaultIpv6Route() {
			properties.SetHasDefaultIpv6Route(ok)
			diff.SetHasDefaultIpv6Route(ok)
		}
		if diff.HasHasDefaultIpv4Route() || diff.HasHasDefaultIpv6Route() {
			wc.mu.lastObserved[nicid] = properties
			for w := range wc.mu.watchers {
				w.onEvent(interfaces.EventWithChanged(diff))
			}
		}
	}
}

func (wc *interfaceWatcherCollection) onInterfaceAddLocked(nicid tcpip.NICID, nicInfo tcpipstack.NICInfo, routes []routes.ExtendedRoute) {
	if properties, ok := wc.mu.lastObserved[nicid]; ok {
		_ = syslog.WarnTf(watcherProtocolName, "interface added but already known: %+v", properties)
		return
	}

	var hasDefaultIpv4Route, hasDefaultIpv6Route bool
	for _, er := range routes {
		if er.Enabled && er.Route.NIC == nicid {
			hasDefaultIpv4Route = hasDefaultIpv4Route || er.Route.Destination.Equal(header.IPv4EmptySubnet)
			hasDefaultIpv6Route = hasDefaultIpv6Route || er.Route.Destination.Equal(header.IPv6EmptySubnet)
		}
	}

	properties := interfaceProperties(nicInfo, hasDefaultIpv4Route, hasDefaultIpv6Route, nil)
	wc.mu.lastObserved[nicid] = properties
	for w := range wc.mu.watchers {
		w.onEvent(interfaces.EventWithAdded(properties))
	}
}

func (c *interfaceWatcherCollection) onInterfaceRemove(nicid tcpip.NICID) {
	c.mu.Lock()
	defer c.mu.Unlock()

	if _, ok := c.mu.lastObserved[nicid]; !ok {
		_ = syslog.WarnTf(watcherProtocolName, "unknown interface removed")
		return
	}
	delete(c.mu.lastObserved, nicid)
	for w := range c.mu.watchers {
		w.onEvent(interfaces.EventWithRemoved(uint64(nicid)))
	}
}

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

type interfaceStateImpl struct {
	ns *Netstack
}

func (si *interfaceStateImpl) GetWatcher(_ fidl.Context, _ interfaces.WatcherOptions, watcher interfaces.WatcherWithCtxInterfaceRequest) error {
	ctx, cancel := context.WithCancel(context.Background())
	impl := interfaceWatcherImpl{
		ready:       make(chan struct{}, 1),
		cancelServe: cancel,
	}
	impl.mu.queue = make([]interfaces.Event, 0, maxInterfaceWatcherQueueLen)

	si.ns.interfaceWatchers.mu.Lock()

	for _, properties := range si.ns.interfaceWatchers.mu.lastObserved {
		impl.mu.queue = append(impl.mu.queue, interfaces.EventWithExisting(properties))
	}
	impl.mu.queue = append(impl.mu.queue, interfaces.EventWithIdle(interfaces.Empty{}))

	si.ns.interfaceWatchers.mu.watchers[&impl] = struct{}{}
	si.ns.interfaceWatchers.mu.Unlock()

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

		si.ns.interfaceWatchers.mu.Lock()
		delete(si.ns.interfaceWatchers.mu.watchers, &impl)
		si.ns.interfaceWatchers.mu.Unlock()
	}()

	return nil
}
