// Copyright 2017 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.

package netstack

import (
	"fmt"
	"sort"
	"strings"
	"syscall/zx"
	"syscall/zx/fidl"
	"syscall/zx/zxwait"

	"syslog"

	"netstack/fidlconv"
	"netstack/link"
	"netstack/routes"

	"fidl/fuchsia/hardware/ethernet"
	"fidl/fuchsia/io"
	"fidl/fuchsia/net"
	"fidl/fuchsia/netstack"

	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/network/ipv4"
	"github.com/google/netstack/tcpip/network/ipv6"
	"github.com/google/netstack/tcpip/transport/tcp"
	"github.com/google/netstack/tcpip/transport/udp"
)

type netstackImpl struct {
	ns    *Netstack
	getIO func() io.Directory
}

// interfaces2ListToInterfacesList converts a NetInterface2 list into a
// NetInterface one.
func interfaces2ListToInterfacesList(ifs2 []netstack.NetInterface2) []netstack.NetInterface {
	ifs := make([]netstack.NetInterface, 0, len(ifs2))
	for _, e2 := range ifs2 {
		ifs = append(ifs, netstack.NetInterface{
			Id:        e2.Id,
			Flags:     e2.Flags,
			Features:  e2.Features,
			Name:      e2.Name,
			Addr:      e2.Addr,
			Netmask:   e2.Netmask,
			Broadaddr: e2.Broadaddr,
			Hwaddr:    e2.Hwaddr,
			Ipv6addrs: e2.Ipv6addrs,
		})
	}
	return ifs
}

func (ns *Netstack) getNetInterfaces2Locked() []netstack.NetInterface2 {
	ifStates := ns.mu.ifStates
	interfaces := make([]netstack.NetInterface2, 0, len(ifStates))
	for _, ifs := range ifStates {
		ifs.mu.Lock()
		netinterface, err := ifs.toNetInterface2Locked()
		ifs.mu.Unlock()
		if err != nil {
			syslog.Warnf("failed to call ifs.toNetInterfaceLocked: %v", err)
		}
		interfaces = append(interfaces, netinterface)
	}
	return interfaces
}

func (ifs *ifState) toNetInterface2Locked() (netstack.NetInterface2, error) {
	addr, subnet, err := ifs.ns.mu.stack.GetMainNICAddress(ifs.nicid, ipv4.ProtocolNumber)
	mask := subnet.Mask()
	// Upstream reuses ErrNoLinkAddress to indicate no address can be found for the requested NIC and
	// network protocol.
	if err == tcpip.ErrNoLinkAddress {
		addr = zeroIpAddr
	} else if err == tcpip.ErrUnknownNICID {
		panic(fmt.Sprintf("stack.GetMainNICAddress(_): NIC %d not found", ifs.nicid))
	} else if err != nil {
		return netstack.NetInterface2{}, fmt.Errorf("stack.GetMainNICAddress(_): %s", err)
	}

	if len(mask) == 0 {
		mask = zeroIpMask
	}

	broadaddr := []byte(addr)
	for i := range broadaddr {
		broadaddr[i] |= ^mask[i]
	}

	addresses, subnets := ifs.ns.getAddressesLocked(ifs.nicid)
	ipv6addrs := make([]net.Subnet, 0, len(subnets))

	// TODO(stijlist): remove N^2 loop by refactoring upstream to a
	// map[tcpip.Address][]tcpip.Subnet
	for _, subnet := range subnets {
		for _, address := range addresses {
			if address.Protocol == ipv6.ProtocolNumber && subnet.Contains(address.Address) {
				ipv6addrs = append(ipv6addrs, net.Subnet{
					Addr:      fidlconv.ToNetIpAddress(address.Address),
					PrefixLen: uint8(subnet.Prefix()),
				})
			}
		}
	}

	var flags uint32
	if ifs.mu.state == link.StateStarted {
		flags |= netstack.NetInterfaceFlagUp
	}
	if ifs.mu.dhcp.enabled {
		flags |= netstack.NetInterfaceFlagDhcp
	}

	return netstack.NetInterface2{
		Id:        uint32(ifs.nicid),
		Flags:     flags,
		Features:  ifs.features,
		Metric:    uint32(ifs.mu.metric),
		Name:      ifs.mu.name,
		Addr:      fidlconv.ToNetIpAddress(addr),
		Netmask:   fidlconv.ToNetIpAddress(tcpip.Address(mask)),
		Broadaddr: fidlconv.ToNetIpAddress(tcpip.Address(broadaddr)),
		Hwaddr:    []uint8(ifs.endpoint.LinkAddress()[:]),
		Ipv6addrs: ipv6addrs,
	}, nil
}

func (ns *Netstack) getInterfaces2Locked() []netstack.NetInterface2 {
	out := ns.getNetInterfaces2Locked()

	sort.Slice(out, func(i, j int) bool {
		return out[i].Id < out[j].Id
	})

	return out
}

func (ni *netstackImpl) GetPortForService(service string, protocol netstack.Protocol) (port uint16, err error) {
	switch protocol {
	case netstack.ProtocolUdp:
		port, err = serviceLookup(service, udp.ProtocolNumber)
	case netstack.ProtocolTcp:
		port, err = serviceLookup(service, tcp.ProtocolNumber)
	default:
		port, err = serviceLookup(service, tcp.ProtocolNumber)
		if err != nil {
			port, err = serviceLookup(service, udp.ProtocolNumber)
		}
	}
	return port, err
}

func (ni *netstackImpl) GetAddress(name string, port uint16) ([]netstack.SocketAddress, netstack.NetErr, error) {
	// TODO: This should handle IP address strings, empty strings, "localhost", etc. Pull the logic from
	// fdio's getaddrinfo into here.
	addrs, err := ni.ns.dnsClient.LookupIP(name)
	if err != nil {
		return nil, netstack.NetErr{Status: netstack.StatusDnsError, Message: err.Error()}, nil
	}
	out := make([]netstack.SocketAddress, 0, len(addrs))
	for _, addr := range addrs {
		out = append(out, netstack.SocketAddress{
			Addr: fidlconv.ToNetIpAddress(addr),
			Port: port,
		})
	}
	return out, netstack.NetErr{Status: netstack.StatusOk}, nil
}

// GetInterfaces2 returns a list of interfaces.
// TODO(NET-2078): Move this to GetInterfaces once Chromium stops using
// netstack.fidl.
func (ni *netstackImpl) GetInterfaces2() ([]netstack.NetInterface2, error) {
	ni.ns.mu.Lock()
	defer ni.ns.mu.Unlock()
	return ni.ns.getInterfaces2Locked(), nil
}

// GetInterfaces is a deprecated version that returns a list of interfaces in a
// format that Chromium supports. The new version is GetInterfaces2 which
// eventually will be renamed once Chromium is not using netstack.fidl anymore
// and this deprecated version can be removed.
func (ni *netstackImpl) GetInterfaces() ([]netstack.NetInterface, error) {
	ni.ns.mu.Lock()
	defer ni.ns.mu.Unlock()
	// Get the new interface list and convert to the old one.
	return interfaces2ListToInterfacesList(ni.ns.getInterfaces2Locked()), nil
}

// TODO(NET-2078): Move this to GetRouteTable once Chromium stops using
// netstack.fidl.
func (ni *netstackImpl) GetRouteTable2() ([]netstack.RouteTableEntry2, error) {
	return nsToRouteTable2(ni.ns.GetExtendedRouteTable()), nil
}

// GetRouteTable is a deprecated version that returns the route table in a
// format that Chromium supports. The new version is GetRouteTable2 which will
// eventually be renamed once Chromium is not using netstack.fidl anymore and
// this deprecated version can be removed.
func (ni *netstackImpl) GetRouteTable() ([]netstack.RouteTableEntry, error) {
	rt2 := nsToRouteTable2(ni.ns.GetExtendedRouteTable())
	rt := make([]netstack.RouteTableEntry, 0, len(rt2))
	for _, r2 := range rt2 {
		var gateway net.IpAddress
		if r2.Gateway != nil {
			gateway = *r2.Gateway
		} else {
			gateway = fidlconv.ToNetIpAddress(zeroIpAddr)
		}
		rt = append(rt, netstack.RouteTableEntry{
			Destination: r2.Destination,
			Netmask:     r2.Netmask,
			Gateway:     gateway,
			Nicid:       r2.Nicid,
		})
	}
	return rt, nil
}

func nsToRouteTable2(table []routes.ExtendedRoute) (out []netstack.RouteTableEntry2) {
	for _, e := range table {
		// Ensure that if any of the returned addresses are "empty",
		// they still have the appropriate length.
		l := 0
		if len(e.Route.Destination) > 0 {
			l = len(e.Route.Destination)
		} else if len(e.Route.Mask) > 0 {
			l = len(e.Route.Destination)
		}
		dest := e.Route.Destination
		mask := e.Route.Mask
		if len(dest) == 0 {
			dest = tcpip.Address(strings.Repeat("\x00", l))
		}
		if len(mask) == 0 {
			mask = tcpip.AddressMask(strings.Repeat("\x00", l))
		}

		var gatewayPtr *net.IpAddress
		if len(e.Route.Gateway) != 0 {
			gateway := fidlconv.ToNetIpAddress(e.Route.Gateway)
			gatewayPtr = &gateway
		}
		out = append(out, netstack.RouteTableEntry2{
			Destination: fidlconv.ToNetIpAddress(dest),
			Netmask:     fidlconv.ToNetIpAddress(tcpip.Address(mask)),
			Gateway:     gatewayPtr,
			Nicid:       uint32(e.Route.NIC),
			Metric:      uint32(e.Metric),
		})
	}
	return out
}

func routeToNs(r netstack.RouteTableEntry2) tcpip.Route {
	var gateway tcpip.Address
	if r.Gateway != nil {
		gateway = fidlconv.ToTCPIPAddress(*r.Gateway)
	}
	return tcpip.Route{
		Destination: fidlconv.ToTCPIPAddress(r.Destination),
		Mask:        tcpip.AddressMask(fidlconv.ToTCPIPAddress(r.Netmask)),
		Gateway:     gateway,
		NIC:         tcpip.NICID(r.Nicid),
	}
}

type routeTableTransactionImpl struct {
	ni *netstackImpl
}

func (i *routeTableTransactionImpl) AddRoute(r netstack.RouteTableEntry2) (int32, error) {
	err := i.ni.ns.AddRoute(routeToNs(r), routes.Metric(r.Metric), false /* not dynamic */)
	if err != nil {
		return int32(zx.ErrInvalidArgs), err
	}
	return int32(zx.ErrOk), nil
}

func (i *routeTableTransactionImpl) DelRoute(r netstack.RouteTableEntry2) (int32, error) {
	err := i.ni.ns.DelRoute(routeToNs(r))
	if err != nil {
		return int32(zx.ErrInvalidArgs), err
	}
	return int32(zx.ErrOk), nil
}

func (ni *netstackImpl) StartRouteTableTransaction(req netstack.RouteTableTransactionInterfaceRequest) (int32, error) {
	{
		ni.ns.mu.Lock()
		defer ni.ns.mu.Unlock()

		if ni.ns.mu.transactionRequest != nil {
			oldChannel := ni.ns.mu.transactionRequest.ToChannel()
			observed, _ := zxwait.Wait(zx.Handle(oldChannel), 0, 0)
			// If the channel is neither readable nor writable, there is no
			// data left to be processed (not readable) and we can't return
			// any more results (not writable).  It's not enough to only
			// look at peerclosed because the peer can close the channel
			// while it still has data in its buffers.
			if observed&(zx.SignalChannelReadable|zx.SignalChannelWritable) == 0 {
				ni.ns.mu.transactionRequest = nil
			}
		}
		if ni.ns.mu.transactionRequest != nil {
			return int32(zx.ErrShouldWait), nil
		}
		ni.ns.mu.transactionRequest = &req
	}
	var routeTableService netstack.RouteTableTransactionService
	transaction := routeTableTransactionImpl{ni: ni}
	// We don't use the error handler to free the channel because it's
	// possible that the peer closes the channel before our service has
	// finished processing.
	c := req.ToChannel()
	_, err := routeTableService.Add(&transaction, c, nil)
	if err != nil {
		return int32(zx.ErrShouldWait), err
	}
	return int32(zx.ErrOk), err
}

// Add address to the given network interface.
func (ni *netstackImpl) SetInterfaceAddress(nicid uint32, address net.IpAddress, prefixLen uint8) (netstack.NetErr, error) {
	syslog.Infof("net address %+v", address)

	nic := tcpip.NICID(nicid)
	protocol, addr, neterr := ni.ns.validateInterfaceAddress(address, prefixLen)
	if neterr.Status != netstack.StatusOk {
		return neterr, nil
	}

	if err := ni.ns.addInterfaceAddress(nic, protocol, addr, prefixLen); err != nil {
		return netstack.NetErr{Status: netstack.StatusUnknownError, Message: err.Error()}, nil
	}
	return netstack.NetErr{Status: netstack.StatusOk, Message: ""}, nil
}

func (ni *netstackImpl) RemoveInterfaceAddress(nicid uint32, address net.IpAddress, prefixLen uint8) (netstack.NetErr, error) {
	nic := tcpip.NICID(nicid)
	protocol, addr, neterr := ni.ns.validateInterfaceAddress(address, prefixLen)

	if neterr.Status != netstack.StatusOk {
		return neterr, nil
	}

	if err := ni.ns.removeInterfaceAddress(nic, protocol, addr, prefixLen); err != nil {
		return netstack.NetErr{Status: netstack.StatusUnknownError, Message: err.Error()}, nil
	}

	return netstack.NetErr{Status: netstack.StatusOk, Message: ""}, nil
}

// SetInterfaceMetric updates the metric of an interface.
func (ni *netstackImpl) SetInterfaceMetric(nicid uint32, metric uint32) (result netstack.NetErr, err error) {
	if err := ni.ns.UpdateInterfaceMetric(tcpip.NICID(nicid), routes.Metric(metric)); err != nil {
		return netstack.NetErr{Status: netstack.StatusUnknownInterface, Message: err.Error()}, nil
	}
	return netstack.NetErr{Status: netstack.StatusOk}, nil
}

func (ni *netstackImpl) BridgeInterfaces(nicids []uint32) (netstack.NetErr, uint32, error) {
	nics := make([]tcpip.NICID, len(nicids))
	for i, n := range nicids {
		nics[i] = tcpip.NICID(n)
	}
	ifs, err := ni.ns.Bridge(nics)
	if err != nil {
		return netstack.NetErr{Status: netstack.StatusUnknownError, Message: err.Error()}, 0, nil
	}
	return netstack.NetErr{Status: netstack.StatusOk}, uint32(ifs.nicid), nil
}

func (ni *netstackImpl) GetAggregateStats(request io.NodeInterfaceRequest) error {
	b := fidl.Binding{
		Stub:    &io.DirectoryStub{Impl: ni.getIO()},
		Channel: request.Channel,
	}
	return b.Init(func(error) {
		if err := b.Close(); err != nil {
			panic(err)
		}
	})
}

func (ni *netstackImpl) GetStats(nicid uint32) (stats netstack.NetInterfaceStats, err error) {
	ni.ns.mu.Lock()
	nicinfo := ni.ns.mu.stack.NICInfo()
	ni.ns.mu.Unlock()

	if info, ok := nicinfo[tcpip.NICID(nicid)]; ok {
		return netstack.NetInterfaceStats{
			Tx: netstack.NetTrafficStats{
				PktsTotal:  info.Stats.Tx.Packets.Value(),
				BytesTotal: info.Stats.Tx.Bytes.Value(),
			},
			Rx: netstack.NetTrafficStats{
				PktsTotal:  info.Stats.Rx.Packets.Value(),
				BytesTotal: info.Stats.Rx.Bytes.Value(),
			},
		}, nil
	}

	// TODO(stijlist): refactor to return NetErr and use StatusUnknownInterface
	return netstack.NetInterfaceStats{}, fmt.Errorf("no such interface id: %d", nicid)
}

func (ni *netstackImpl) SetInterfaceStatus(nicid uint32, enabled bool) error {
	ni.ns.mu.Lock()
	ifState, ok := ni.ns.mu.ifStates[tcpip.NICID(nicid)]
	ni.ns.mu.Unlock()

	if !ok {
		// TODO(stijlist): refactor to return NetErr and use StatusUnknownInterface
		return fmt.Errorf("no such interface id: %d", nicid)
	}

	if enabled {
		return ifState.eth.Up()
	}
	return ifState.eth.Down()
}

func (ni *netstackImpl) SetDhcpClientStatus(nicid uint32, enabled bool) (netstack.NetErr, error) {
	ni.ns.mu.Lock()
	ifState, ok := ni.ns.mu.ifStates[tcpip.NICID(nicid)]
	ni.ns.mu.Unlock()

	if !ok {
		return netstack.NetErr{Status: netstack.StatusUnknownInterface, Message: "unknown interface"}, nil
	}

	ifState.mu.Lock()
	ifState.setDHCPStatusLocked(enabled)
	ifState.mu.Unlock()
	return netstack.NetErr{Status: netstack.StatusOk, Message: ""}, nil
}

func (ns *netstackImpl) AddEthernetDevice(topological_path string, interfaceConfig netstack.InterfaceConfig, device ethernet.DeviceInterface) (uint32, error) {
	ifs, err := ns.ns.addEth(topological_path, interfaceConfig, &device)
	if err != nil {
		return 0, err
	}
	return uint32(ifs.nicid), err
}

type dnsImpl struct {
	ns *Netstack
}

func (dns *dnsImpl) SetNameServers(servers []net.IpAddress) error {
	ss := make([]tcpip.Address, len(servers))

	for i, s := range servers {
		ss[i] = fidlconv.ToTCPIPAddress(s)
	}

	dns.ns.dnsClient.SetDefaultServers(ss)
	return nil
}
