// Copyright 2019 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 (
	"context"
	"fmt"
	"net"
	"reflect"
	"sort"
	"strconv"
	"syscall/zx"
	"syscall/zx/fidl"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/dhcp"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link/eth"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link/fifo"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link/netdevice"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routes"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/util"
	"go.fuchsia.dev/fuchsia/src/lib/component"
	syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go"

	inspect "fidl/fuchsia/inspect/deprecated"

	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/header"
	"gvisor.dev/gvisor/pkg/tcpip/stack"
	"gvisor.dev/gvisor/pkg/tcpip/transport"
	"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
)

// An infallible version of fuchsia.inspect.Inspect with FIDL details omitted.
type inspectInner interface {
	ReadData() inspect.Object
	ListChildren() []string
	GetChild(string) inspectInner
}

const (
	statsLabel                  = "Stats"
	networkEndpointStatsLabel   = "Network Endpoint Stats"
	socketInfo                  = "Socket Info"
	dhcpInfo                    = "DHCP Info"
	dhcpStateRecentHistoryLabel = "DHCP State Recent History"
	neighborsLabel              = "Neighbors"
	ethInfo                     = "Ethernet Info"
	netdeviceInfo               = "Network Device Info"
	rxReads                     = "RxReads"
	rxWrites                    = "RxWrites"
	txReads                     = "TxReads"
	txWrites                    = "TxWrites"
)

// An adapter that implements fuchsia.inspect.InspectWithCtx using the above.

var _ inspect.InspectWithCtx = (*inspectImpl)(nil)

type inspectImpl struct {
	inner inspectInner
}

func (impl *inspectImpl) ReadData(fidl.Context) (inspect.Object, error) {
	return impl.inner.ReadData(), nil
}

func (impl *inspectImpl) ListChildren(fidl.Context) ([]string, error) {
	return impl.inner.ListChildren(), nil
}

func (impl *inspectImpl) OpenChild(ctx fidl.Context, childName string, childChannel inspect.InspectWithCtxInterfaceRequest) (bool, error) {
	if child := impl.inner.GetChild(childName); child != nil {
		svc := (&inspectImpl{
			inner: child,
		}).asService()
		// The child's lifetime is not tied to the parent's.
		ctx := context.Background()
		return true, svc.AddFn(ctx, childChannel.Channel)
	}
	_ = childChannel.Close()
	return false, nil
}

func (impl *inspectImpl) asService() *component.Service {
	stub := inspect.InspectWithCtxStub{Impl: impl}
	return &component.Service{
		AddFn: func(ctx context.Context, c zx.Channel) error {
			go component.Serve(ctx, &stub, c, component.ServeOptions{
				OnError: func(err error) {
					_ = syslog.WarnTf(inspect.InspectName, "%s", err)
				},
			})
			return nil
		},
	}
}

// Inspect implementations are exposed as directories containing a node called "inspect".

var _ component.Directory = (*inspectDirectory)(nil)

type inspectDirectory struct {
	asService func() *component.Service
}

func (dir *inspectDirectory) Get(name string) (component.Node, bool) {
	if name == inspect.InspectName {
		return dir.asService(), true
	}
	return nil, false
}

func (dir *inspectDirectory) ForEach(fn func(string, component.Node)) {
	fn(inspect.InspectName, dir.asService())
}

// statCounter enables *tcpip.StatCounters and other types in this
// package to be accessed via the same interface.
type statCounter interface {
	Value(...string) uint64
}

var _ statCounter = (*tcpip.StatCounter)(nil)
var statCounterType = reflect.TypeOf((*statCounter)(nil)).Elem()

// Recursive reflection-based implementation for structs containing other
// structs, stat counters, or maps of stat counters.

var _ inspectInner = (*statCounterInspectImpl)(nil)

type statCounterInspectImpl struct {
	name  string
	value reflect.Value
}

func (impl *statCounterInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name:    impl.name,
		Metrics: impl.asMetrics(),
	}
}

func (impl *statCounterInspectImpl) asMetrics() []inspect.Metric {
	var metrics []inspect.Metric
	typ := impl.value.Type()
	for i := 0; i < impl.value.NumField(); i++ {
		// PkgPath is empty for exported field names.
		if field := typ.Field(i); len(field.PkgPath) == 0 {
			v := impl.value.Field(i)
			counter, ok := v.Interface().(statCounter)
			if !ok && v.CanAddr() {
				counter, ok = v.Addr().Interface().(statCounter)
			}
			if ok {
				metrics = append(metrics, inspect.Metric{
					Key:   field.Name,
					Value: inspect.MetricValueWithUintValue(counter.Value()),
				})
			} else if field.Anonymous && v.Kind() == reflect.Struct {
				metrics = append(metrics, (&statCounterInspectImpl{value: v}).asMetrics()...)
			}
		}
	}
	return metrics
}

func (impl *statCounterInspectImpl) ListChildren() []string {
	var children []string
	typ := impl.value.Type()
	for i := 0; i < impl.value.NumField(); i++ {
		field := typ.Field(i)
		// PkgPath is empty for exported field names.
		if len(field.PkgPath) != 0 {
			continue
		}

		if _, ok := extractIntegralStatCounterMap(impl.value.Field(i)); ok {
			children = append(children, field.Name)
		} else if field.Type.Kind() == reflect.Struct && !field.Type.Implements(statCounterType) && !reflect.PtrTo(field.Type).Implements(statCounterType) {
			if field.Anonymous {
				children = append(children, (&statCounterInspectImpl{value: impl.value.Field(i)}).ListChildren()...)
			} else {
				children = append(children, field.Name)
			}
		}
	}
	return children
}

func (impl *statCounterInspectImpl) GetChild(childName string) inspectInner {
	if typ, ok := impl.value.Type().FieldByName(childName); ok {
		// PkgPath is empty for exported field names.
		if len(typ.PkgPath) != 0 {
			return nil
		}
		if child := impl.value.FieldByName(childName); child.IsValid() {
			if counterMap, ok := extractIntegralStatCounterMap(child); ok {
				return &integralStatCounterMapInspectImpl{
					name:  childName,
					value: counterMap,
				}
			}
			if typ.Type.Kind() == reflect.Struct {
				return &statCounterInspectImpl{
					name:  childName,
					value: child,
				}
			}
		}
	}
	return nil
}

func extractIntegralStatCounterMap(value reflect.Value) (*tcpip.IntegralStatCounterMap, bool) {
	switch t := value.Interface().(type) {
	case *tcpip.IntegralStatCounterMap:
		return t, true
	case tcpip.IntegralStatCounterMap:
		return &t, true
	default:
		return nil, false
	}
}

var _ inspectInner = (*logEntryInspectImpl)(nil)

type logEntryInspectImpl struct {
	index string
	entry util.LogEntry
}

func (impl *logEntryInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.index,
		Properties: []inspect.Property{
			{Key: "@time", Value: inspect.PropertyValueWithStr(strconv.FormatInt(int64(impl.entry.Timestamp), 10))},
			{Key: "value", Value: inspect.PropertyValueWithStr(impl.entry.Content)},
		},
	}
}

func (impl *logEntryInspectImpl) ListChildren() []string {
	return nil
}

func (impl *logEntryInspectImpl) GetChild(childName string) inspectInner {
	return nil
}

var _ inspectInner = (*circularLogsInspectImpl)(nil)

type circularLogsInspectImpl struct {
	name  string
	value []util.LogEntry
}

func (impl *circularLogsInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
	}
}

func (impl *circularLogsInspectImpl) ListChildren() []string {
	children := make([]string, 0, len(impl.value))
	for i := range impl.value {
		children = append(children, strconv.FormatUint(uint64(i), 10))
	}
	return children
}

func (impl *circularLogsInspectImpl) GetChild(childName string) inspectInner {
	index, err := strconv.ParseUint(childName, 10, 64)
	if err != nil {
		_ = syslog.VLogTf(syslog.DebugVerbosity, inspect.InspectName, "GetChild(): %s", err)
		return nil
	}
	if index >= uint64(len(impl.value)) {
		_ = syslog.VLogTf(
			syslog.DebugVerbosity,
			inspect.InspectName,
			"GetChild(%s): index %d out of bounds, there are %d entries in the circular logs",
			childName,
			index,
			len(impl.value),
		)
		return nil
	}
	return &logEntryInspectImpl{
		index: childName,
		entry: impl.value[index],
	}
}

var _ inspectInner = (*integralStatCounterMapInspectImpl)(nil)

type integralStatCounterMapInspectImpl struct {
	name  string
	value *tcpip.IntegralStatCounterMap
}

const integralStatMapTotalFieldName = "Total"

func (impl *integralStatCounterMapInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
	}
}

func (impl *integralStatCounterMapInspectImpl) ListChildren() []string {
	var children []string
	children = append(children, integralStatMapTotalFieldName)
	for _, key := range impl.value.Keys() {
		children = append(children, strconv.FormatUint(key, 10))
	}
	return children
}

func (impl *integralStatCounterMapInspectImpl) GetChild(childName string) inspectInner {
	if childName == integralStatMapTotalFieldName {
		var total uint64
		for _, key := range impl.value.Keys() {
			if counter, ok := impl.value.Get(key); ok {
				total += counter.Value()
			}
		}
		return &singleStatCounterInspectImpl{
			name:  childName,
			value: total,
		}
	} else {
		if key, err := strconv.ParseUint(childName, 10, 64); err == nil {
			if counter, ok := impl.value.Get(key); ok {
				return &singleStatCounterInspectImpl{
					name:  childName,
					value: counter.Value(),
				}
			}
		}
		return nil
	}
}

var _ inspectInner = (*singleStatCounterInspectImpl)(nil)

type singleStatCounterInspectImpl struct {
	name  string
	value uint64
}

func (impl *singleStatCounterInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
		Properties: []inspect.Property{
			{Key: "Count", Value: inspect.PropertyValueWithStr(strconv.FormatUint(impl.value, 10))},
		},
	}
}

func (*singleStatCounterInspectImpl) ListChildren() []string {
	return nil
}

func (*singleStatCounterInspectImpl) GetChild(childName string) inspectInner {
	return nil
}

var _ inspectInner = (*nicInfoMapInspectImpl)(nil)

// Picking info to inspect from ifState in netstack.
type ifStateInfo struct {
	stack.NICInfo
	nicid                  tcpip.NICID
	adminUp, linkOnline    bool
	dnsServers             []tcpip.Address
	dhcpEnabled            bool
	dhcpInfo               dhcp.Info
	dhcpStateRecentHistory []util.LogEntry
	dhcpStats              *dhcp.Stats
	controller             link.Controller
	neighbors              map[string]stack.NeighborEntry
	networkEndpointStats   map[string]stack.NetworkEndpointStats
}

type nicInfoMapInspectImpl struct {
	value map[tcpip.NICID]ifStateInfo
}

func (*nicInfoMapInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: "NICs",
	}
}

func (impl *nicInfoMapInspectImpl) ListChildren() []string {
	var children []string
	for nicID := range impl.value {
		children = append(children, strconv.FormatUint(uint64(nicID), 10))
	}
	sort.Strings(children)
	return children
}

func (impl *nicInfoMapInspectImpl) GetChild(childName string) inspectInner {
	id, err := strconv.ParseInt(childName, 10, 32)
	if err != nil {
		_ = syslog.VLogTf(syslog.DebugVerbosity, inspect.InspectName, "GetChild(): %s", err)
		return nil
	}
	if child, ok := impl.value[tcpip.NICID(id)]; ok {
		return &nicInfoInspectImpl{
			name:  childName,
			value: child,
		}
	}
	return nil
}

var _ inspectInner = (*nicInfoInspectImpl)(nil)

type nicInfoInspectImpl struct {
	name  string
	value ifStateInfo
}

func (impl *nicInfoInspectImpl) ReadData() inspect.Object {
	object := inspect.Object{
		Name: impl.name,
		Properties: []inspect.Property{
			{Key: "Name", Value: inspect.PropertyValueWithStr(impl.value.Name)},
			{Key: "NICID", Value: inspect.PropertyValueWithStr(strconv.FormatUint(uint64(impl.value.nicid), 10))},
			{Key: "AdminUp", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.adminUp))},
			{Key: "LinkOnline", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.linkOnline))},
			{Key: "Up", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.Flags.Up))},
			{Key: "Running", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.Flags.Running))},
			{Key: "Loopback", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.Flags.Loopback))},
			{Key: "Promiscuous", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.Flags.Promiscuous))},
		},
		Metrics: []inspect.Metric{
			{Key: "MTU", Value: inspect.MetricValueWithUintValue(uint64(impl.value.MTU))},
		},
	}
	if linkAddress := impl.value.LinkAddress; len(linkAddress) != 0 {
		object.Properties = append(object.Properties, inspect.Property{
			Key:   "LinkAddress",
			Value: inspect.PropertyValueWithStr(linkAddress.String()),
		})
	}
	for i, protocolAddress := range impl.value.ProtocolAddresses {
		protocol := "unknown"
		switch protocolAddress.Protocol {
		case header.IPv4ProtocolNumber:
			protocol = "ipv4"
		case header.IPv6ProtocolNumber:
			protocol = "ipv6"
		case header.ARPProtocolNumber:
			protocol = "arp"
		}
		object.Properties = append(object.Properties, inspect.Property{
			Key:   fmt.Sprintf("ProtocolAddress%d", i),
			Value: inspect.PropertyValueWithStr(fmt.Sprintf("[%s] %s", protocol, protocolAddress.AddressWithPrefix)),
		})
	}

	for i, addr := range impl.value.dnsServers {
		object.Properties = append(object.Properties, inspect.Property{
			Key: fmt.Sprintf("DNS server%d", i), Value: inspect.PropertyValueWithStr(addr.String())})
	}
	object.Properties = append(object.Properties, inspect.Property{
		Key:   "DHCP enabled",
		Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.dhcpEnabled)),
	})
	return object
}

func (impl *nicInfoInspectImpl) ListChildren() []string {
	children := []string{
		statsLabel,
	}
	if len(impl.value.NetworkStats) != 0 {
		children = append(children, networkEndpointStatsLabel)
	}
	if impl.value.dhcpEnabled {
		children = append(children, dhcpInfo)
	}
	if impl.value.neighbors != nil {
		children = append(children, neighborsLabel)
	}

	switch impl.value.controller.(type) {
	case *eth.Client:
		children = append(children, ethInfo)
	case *netdevice.Port:
		children = append(children, netdeviceInfo)
	}

	return children
}

func (impl *nicInfoInspectImpl) GetChild(childName string) inspectInner {
	switch childName {
	case statsLabel:
		return &statCounterInspectImpl{
			name:  childName,
			value: reflect.ValueOf(impl.value.Stats),
		}
	case networkEndpointStatsLabel:
		return &networkEndpointStatsInspectImpl{
			name:  childName,
			value: impl.value.networkEndpointStats,
		}
	case dhcpInfo:
		return &dhcpInfoInspectImpl{
			name:               childName,
			info:               impl.value.dhcpInfo,
			stateRecentHistory: impl.value.dhcpStateRecentHistory,
			stats:              impl.value.dhcpStats,
		}
	case neighborsLabel:
		return &neighborTableInspectImpl{
			name:  childName,
			value: impl.value.neighbors,
		}
	case ethInfo:
		return &ethInfoInspectImpl{
			name:  childName,
			value: impl.value.controller.(*eth.Client),
		}
	case netdeviceInfo:
		return &netdevInspectImpl{
			name:  childName,
			value: impl.value.controller.(*netdevice.Port),
		}
	default:
		return nil
	}
}

var _ inspectInner = (*networkEndpointStatsInspectImpl)(nil)

type networkEndpointStatsInspectImpl struct {
	name  string
	value map[string]stack.NetworkEndpointStats
}

func (impl *networkEndpointStatsInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
	}
}

func (impl *networkEndpointStatsInspectImpl) ListChildren() []string {
	children := make([]string, 0, len(impl.value))
	for k := range impl.value {
		children = append(children, k)
	}
	return children
}

func (impl *networkEndpointStatsInspectImpl) GetChild(childName string) inspectInner {
	entry, ok := impl.value[childName]
	if !ok {
		_ = syslog.VLogTf(syslog.DebugVerbosity, inspect.InspectName,
			"GetChild(%s): no stats found",
			childName,
		)
		return nil
	}

	return &statCounterInspectImpl{
		name:  childName,
		value: reflect.Indirect(reflect.ValueOf(entry)),
	}
}

var _ inspectInner = (*dhcpInfoInspectImpl)(nil)

type dhcpInfoInspectImpl struct {
	name               string
	info               dhcp.Info
	stateRecentHistory []util.LogEntry
	stats              *dhcp.Stats
}

func (impl *dhcpInfoInspectImpl) ReadData() inspect.Object {
	addrString := func(addr tcpip.Address) string {
		if addr == "" {
			return "[none]"
		}
		return addr.String()
	}
	addrPrefixString := func(addr tcpip.AddressWithPrefix) string {
		if addr == (tcpip.AddressWithPrefix{}) {
			return "[none]"
		}
		return addr.String()
	}
	maskString := func(mask tcpip.AddressMask) string {
		if mask.String() == "" {
			return "[none]"
		}
		return mask.String()
	}
	properties := []inspect.Property{
		{Key: "State", Value: inspect.PropertyValueWithStr(impl.info.State.String())},
		{Key: "AcquiredAddress", Value: inspect.PropertyValueWithStr(addrPrefixString(impl.info.Acquired))},
		{Key: "AssignedAddress", Value: inspect.PropertyValueWithStr(addrPrefixString(impl.info.Assigned))},
		{Key: "Acquisition", Value: inspect.PropertyValueWithStr(impl.info.Acquisition.String())},
		{Key: "Backoff", Value: inspect.PropertyValueWithStr(impl.info.Backoff.String())},
		{Key: "Retransmission", Value: inspect.PropertyValueWithStr(impl.info.Retransmission.String())},
		{Key: "LeaseExpiration", Value: inspect.PropertyValueWithStr(impl.info.LeaseExpiration.String())},
		{Key: "RenewTime", Value: inspect.PropertyValueWithStr(impl.info.RenewTime.String())},
		{Key: "RebindTime", Value: inspect.PropertyValueWithStr(impl.info.RebindTime.String())},
		{Key: "Config.ServerAddress", Value: inspect.PropertyValueWithStr(addrString(impl.info.Config.ServerAddress))},
		{Key: "Config.SubnetMask", Value: inspect.PropertyValueWithStr(maskString(impl.info.Config.SubnetMask))},
	}
	for i, router := range impl.info.Config.Router {
		properties = append(properties, inspect.Property{
			Key:   fmt.Sprintf("Config.Router%d", i),
			Value: inspect.PropertyValueWithStr(addrString(router)),
		})
	}
	for i, dns := range impl.info.Config.DNS {
		properties = append(properties, inspect.Property{
			Key:   fmt.Sprintf("Config.DNS%d", i),
			Value: inspect.PropertyValueWithStr(addrString(dns)),
		})
	}
	properties = append(properties, []inspect.Property{
		{Key: "Config.LeaseLength", Value: inspect.PropertyValueWithStr(impl.info.Config.LeaseLength.String())},
		{Key: "Config.RenewTime", Value: inspect.PropertyValueWithStr(impl.info.Config.RenewTime.String())},
		{Key: "Config.RebindTime", Value: inspect.PropertyValueWithStr(impl.info.Config.RebindTime.String())},
		{Key: "Config.Declined", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.info.Config.Declined))},
	}...)
	return inspect.Object{
		Name:       impl.name,
		Properties: properties,
	}
}

func (*dhcpInfoInspectImpl) ListChildren() []string {
	return []string{
		statsLabel,
		dhcpStateRecentHistoryLabel,
	}
}

func (impl *dhcpInfoInspectImpl) GetChild(childName string) inspectInner {
	switch childName {
	case statsLabel:
		return &statCounterInspectImpl{
			name:  childName,
			value: reflect.ValueOf(impl.stats).Elem(),
		}
	case dhcpStateRecentHistoryLabel:
		return &circularLogsInspectImpl{
			name:  childName,
			value: impl.stateRecentHistory,
		}
	default:
		return nil
	}
}

var _ inspectInner = (*ethInfoInspectImpl)(nil)

type ethInfoInspectImpl struct {
	name  string
	value *eth.Client
}

func (impl *ethInfoInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
		Metrics: []inspect.Metric{
			{Key: "TxDrops", Value: inspect.MetricValueWithUintValue(impl.value.TxStats().Drops.Value())},
		},
		Properties: []inspect.Property{
			{Key: "Topopath", Value: inspect.PropertyValueWithStr(impl.value.Topopath())},
			{Key: "Filepath", Value: inspect.PropertyValueWithStr(impl.value.Filepath())},
			{Key: "Features", Value: inspect.PropertyValueWithStr(impl.value.Info.Features.String())},
		},
	}
}

func getFifoStatsChildren() []string {
	return []string{
		rxReads,
		rxWrites,
		txReads,
		txWrites,
	}
}

func getFifoStatsImpl(childName string, rx *fifo.RxStats, tx *fifo.TxStats) inspectInner {
	switch childName {
	case rxReads:
		return &fifoStatsInspectImpl{
			name:  childName,
			value: rx.Reads,
			size:  rx.Size(),
		}
	case rxWrites:
		return &fifoStatsInspectImpl{
			name:  childName,
			value: rx.Writes,
			size:  rx.Size(),
		}
	case txReads:
		return &fifoStatsInspectImpl{
			name:  childName,
			value: tx.Reads,
			size:  tx.Size(),
		}
	case txWrites:
		return &fifoStatsInspectImpl{
			name:  childName,
			value: tx.Writes,
			size:  tx.Size(),
		}
	default:
		return nil
	}
}

func (*ethInfoInspectImpl) ListChildren() []string {
	return getFifoStatsChildren()
}

func (impl *ethInfoInspectImpl) GetChild(childName string) inspectInner {
	return getFifoStatsImpl(childName, impl.value.RxStats(), impl.value.TxStats())
}

var _ inspectInner = (*netdevInspectImpl)(nil)

type netdevInspectImpl struct {
	name  string
	value *netdevice.Port
}

func (impl *netdevInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
		Metrics: []inspect.Metric{
			{Key: "TxDrops", Value: inspect.MetricValueWithUintValue(impl.value.TxStats().Drops.Value())},
		},
		Properties: []inspect.Property{
			{Key: "Class", Value: inspect.PropertyValueWithStr(impl.value.Class().String())},
		},
	}
}

func (*netdevInspectImpl) ListChildren() []string {
	return getFifoStatsChildren()
}

func (impl *netdevInspectImpl) GetChild(childName string) inspectInner {
	return getFifoStatsImpl(childName, impl.value.RxStats(), impl.value.TxStats())
}

var _ inspectInner = (*fifoStatsInspectImpl)(nil)

type fifoStatsInspectImpl struct {
	name  string
	value func(uint32) *tcpip.StatCounter
	size  uint32
}

// We cap the number of Metrics in a response so that the FIDL
// response would fit in a single channel message.
const maxMetricsForFifoStats = 1024

func (impl *fifoStatsInspectImpl) ReadData() inspect.Object {
	var metrics []inspect.Metric
	batchesPerMetrics := ((impl.size - 1) / maxMetricsForFifoStats) + 1
	batch := uint32(1)
	for batch <= impl.size {
		startBatch := batch
		v := uint64(0)
		for i := uint32(0); i < batchesPerMetrics; i++ {
			v += impl.value(batch).Value()
			batch++
			if batch > impl.size {
				break
			}
		}
		endBatch := batch - 1
		if v != 0 {
			var key string
			if startBatch == endBatch {
				key = fmt.Sprintf("%d", startBatch)
			} else {
				key = fmt.Sprintf("%d-%d", startBatch, endBatch)
			}
			metrics = append(metrics, inspect.Metric{
				Key:   key,
				Value: inspect.MetricValueWithUintValue(v),
			})
		}
	}
	return inspect.Object{
		Name:    impl.name,
		Metrics: metrics,
	}
}

func (*fifoStatsInspectImpl) ListChildren() []string {
	return nil
}

func (*fifoStatsInspectImpl) GetChild(string) inspectInner {
	return nil
}

var _ inspectInner = (*socketInfoMapInspectImpl)(nil)

type socketInfoMapInspectImpl struct {
	value *endpointsMap
}

func (*socketInfoMapInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: socketInfo,
	}
}

func (impl *socketInfoMapInspectImpl) ListChildren() []string {
	var children []string
	impl.value.Range(func(key uint64, _ tcpip.Endpoint) bool {
		children = append(children, strconv.FormatUint(uint64(key), 10))
		return true
	})
	return children
}

func (impl *socketInfoMapInspectImpl) GetChild(childName string) inspectInner {
	id, err := strconv.ParseUint(childName, 10, 64)
	if err != nil {
		_ = syslog.VLogTf(syslog.DebugVerbosity, inspect.InspectName, "GetChild(): %s", err)
		return nil
	}
	if ep, ok := impl.value.Load(uint64(id)); ok {
		return &socketInfoInspectImpl{
			name:  childName,
			info:  ep.Info(),
			state: ep.State(),
			stats: ep.Stats(),
		}
	}
	return nil
}

var _ inspectInner = (*socketInfoInspectImpl)(nil)

type socketInfoInspectImpl struct {
	name  string
	info  tcpip.EndpointInfo
	state uint32
	stats tcpip.EndpointStats
}

func (impl *socketInfoInspectImpl) ReadData() inspect.Object {
	var common stack.TransportEndpointInfo
	switch t := impl.info.(type) {
	case *stack.TransportEndpointInfo:
		common = *t
	default:
		return inspect.Object{
			Name: impl.name,
		}
	}

	var netString string
	var zeroAddress net.IP
	switch common.NetProto {
	case header.IPv4ProtocolNumber:
		netString = "IPv4"
		zeroAddress = net.IPv4zero
	case header.IPv6ProtocolNumber:
		netString = "IPv6"
		zeroAddress = net.IPv6zero
	default:
		netString = "UNKNOWN"
	}

	var transString string
	var state string
	switch common.TransProto {
	case header.TCPProtocolNumber:
		transString = "TCP"
		state = tcp.EndpointState(impl.state).String()
	case header.UDPProtocolNumber:
		transString = "UDP"
		state = transport.DatagramEndpointState(impl.state).String()
	case header.ICMPv4ProtocolNumber:
		transString = "ICMPv4"
	case header.ICMPv6ProtocolNumber:
		transString = "ICMPv6"
	default:
		transString = "UNKNOWN"
	}

	localAddress := net.IP(common.ID.LocalAddress)
	if len(localAddress) == 0 {
		localAddress = zeroAddress
	}
	remoteAddress := net.IP(common.ID.RemoteAddress)
	if len(remoteAddress) == 0 {
		remoteAddress = zeroAddress
	}

	localAddr := net.JoinHostPort(localAddress.String(), strconv.FormatUint(uint64(common.ID.LocalPort), 10))
	remoteAddr := net.JoinHostPort(remoteAddress.String(), strconv.FormatUint(uint64(common.ID.RemotePort), 10))
	properties := []inspect.Property{
		{Key: "NetworkProtocol", Value: inspect.PropertyValueWithStr(netString)},
		{Key: "TransportProtocol", Value: inspect.PropertyValueWithStr(transString)},
		{Key: "State", Value: inspect.PropertyValueWithStr(state)},
		{Key: "LocalAddress", Value: inspect.PropertyValueWithStr(localAddr)},
		{Key: "RemoteAddress", Value: inspect.PropertyValueWithStr(remoteAddr)},
		{Key: "BindAddress", Value: inspect.PropertyValueWithStr(common.BindAddr.String())},
		{Key: "BindNICID", Value: inspect.PropertyValueWithStr(strconv.FormatUint(uint64(common.BindNICID), 10))},
		{Key: "RegisterNICID", Value: inspect.PropertyValueWithStr(strconv.FormatUint(uint64(common.RegisterNICID), 10))},
	}

	return inspect.Object{
		Name:       impl.name,
		Properties: properties,
	}
}

func (*socketInfoInspectImpl) ListChildren() []string {
	return []string{
		statsLabel,
	}
}

func (impl *socketInfoInspectImpl) GetChild(childName string) inspectInner {
	switch childName {
	case statsLabel:
		var value reflect.Value
		switch t := impl.stats.(type) {
		case *tcp.Stats:
			value = reflect.ValueOf(t).Elem()
		case *tcpip.TransportEndpointStats:
			value = reflect.ValueOf(t).Elem()
		default:
			return nil
		}
		return &statCounterInspectImpl{
			name:  childName,
			value: value,
		}
	}
	return nil
}

var _ inspectInner = (*routingTableInspectImpl)(nil)

type routingTableInspectImpl struct {
	value []routes.ExtendedRoute
}

func (*routingTableInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: "Routes",
	}
}

func (impl *routingTableInspectImpl) ListChildren() []string {
	children := make([]string, len(impl.value))
	for i := range impl.value {
		children[i] = strconv.FormatUint(uint64(i), 10)
	}
	return children
}

func (impl *routingTableInspectImpl) GetChild(childName string) inspectInner {
	routeIndex, err := strconv.ParseUint(childName, 10, 64)
	if err != nil {
		_ = syslog.VLogTf(syslog.DebugVerbosity, inspect.InspectName, "GetChild(): %s", err)
		return nil
	}
	if routeIndex >= uint64(len(impl.value)) {
		_ = syslog.VLogTf(
			syslog.DebugVerbosity,
			inspect.InspectName,
			"GetChild(%s): index %d out of bounds, there are %d entries in the routing table",
			childName,
			routeIndex,
			len(impl.value),
		)
		return nil
	}
	return &routeInfoInspectImpl{
		name:  childName,
		value: impl.value[routeIndex],
	}
}

var _ inspectInner = (*routeInfoInspectImpl)(nil)

type routeInfoInspectImpl struct {
	name  string
	value routes.ExtendedRoute
}

func (impl *routeInfoInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
		Properties: []inspect.Property{
			{Key: "Destination", Value: inspect.PropertyValueWithStr(impl.value.Route.Destination.String())},
			{Key: "Gateway", Value: inspect.PropertyValueWithStr(impl.value.Route.Gateway.String())},
			{Key: "NIC", Value: inspect.PropertyValueWithStr(strconv.FormatUint(uint64(impl.value.Route.NIC), 10))},
			{Key: "Metric", Value: inspect.PropertyValueWithStr(strconv.FormatUint(uint64(impl.value.Metric), 10))},
			{Key: "MetricTracksInterface", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.MetricTracksInterface))},
			{Key: "Dynamic", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.Dynamic))},
			{Key: "Enabled", Value: inspect.PropertyValueWithStr(strconv.FormatBool(impl.value.Enabled))},
		},
	}
}

func (*routeInfoInspectImpl) ListChildren() []string {
	return nil
}

func (*routeInfoInspectImpl) GetChild(string) inspectInner {
	return nil
}

var _ inspectInner = (*neighborTableInspectImpl)(nil)

type neighborTableInspectImpl struct {
	name  string
	value map[string]stack.NeighborEntry
}

func (impl *neighborTableInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.name,
	}
}

func (impl *neighborTableInspectImpl) ListChildren() []string {
	children := make([]string, 0, len(impl.value))
	for k := range impl.value {
		children = append(children, k)
	}
	return children
}

func (impl *neighborTableInspectImpl) GetChild(childName string) inspectInner {
	entry, ok := impl.value[childName]
	if !ok {
		_ = syslog.VLogTf(syslog.DebugVerbosity, inspect.InspectName,
			"GetChild(%s): no entry found in the neighbor table",
			childName,
		)
		return nil
	}
	return &neighborInfoInspectImpl{
		value: entry,
	}
}

var _ inspectInner = (*neighborInfoInspectImpl)(nil)

type neighborInfoInspectImpl struct {
	value stack.NeighborEntry
}

func (impl *neighborInfoInspectImpl) ReadData() inspect.Object {
	return inspect.Object{
		Name: impl.value.Addr.String(),
		Properties: []inspect.Property{
			{Key: "Link address", Value: inspect.PropertyValueWithStr(impl.value.LinkAddr.String())},
			{Key: "State", Value: inspect.PropertyValueWithStr(impl.value.State.String())},
		},
		Metrics: []inspect.Metric{
			{Key: "Last updated", Value: inspect.MetricValueWithIntValue(impl.value.UpdatedAt.UnixNano())},
		},
	}
}

func (*neighborInfoInspectImpl) ListChildren() []string {
	return nil
}

func (*neighborInfoInspectImpl) GetChild(string) inspectInner {
	return nil
}
