// 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 main

import (
	"flag"
	"fmt"
	"os"

	"app/context"
	"netstack/fidlconv"

	"fidl/fuchsia/net"
	"fidl/fuchsia/netstack"
)

type netstatApp struct {
	ctx      *context.Context
	netstack *netstack.NetstackInterface
}

type icmpHistogram struct {
	// see third_party/netstack/tcpip/header/icmpv{4,6}.go for an exhaustive list
	echoRequests uint64
	echoReplies  uint64
}

type icmpOutput struct {
	received        uint64
	inputFailed     uint64
	sent            uint64
	sentFailed      uint64
	inputHistogram  icmpHistogram
	outputHistogram icmpHistogram
}

type statsOutput struct {
	icmp icmpOutput
	ip   netstack.IpStats
	tcp  netstack.TcpStats
	udp  netstack.UdpStats
}

func (h icmpHistogram) String() string {
	return fmt.Sprintf("\t\techo request: %d\n\t\techo replies: %d", h.echoRequests, h.echoReplies)
}

func (o *statsOutput) String() string {
	return fmt.Sprintf(
		`IP:
	%d total packets received
	%d with invalid addresses
	%d incoming packets delivered
	%d requests sent out
	%d outgoing packets with errors
TCP:
	%d ActiveConnectionOpenings
	%d PassiveConnectionOpenings
	%d FailedConnectionAttempts
	%d ValidSegmentsReceived
	%d InvalidSegmentsReceived
	%d SegmentsSent
	%d ResetsSent
UDP:
	%d packets received
	%d packet receive errors
	%d packets to unknown ports received
	%d receive buffer errors
	%d malformed packets received
	%d packets sent
ICMP:
	%d ICMP messages received
	%d input ICMP message failed.
	ICMP input histogram:
%v
	%d ICMP messages sent
	%d ICMP messages failed
	ICMP output histogram:
%v`,
		o.ip.PacketsReceived,
		o.ip.InvalidAddressesReceived,
		o.ip.PacketsDelivered,
		o.ip.PacketsSent,
		o.ip.OutgoingPacketErrors,
		o.tcp.ActiveConnectionOpenings,
		o.tcp.PassiveConnectionOpenings,
		o.tcp.FailedConnectionAttempts,
		o.tcp.ValidSegmentsReceived,
		o.tcp.InvalidSegmentsReceived,
		o.tcp.SegmentsSent,
		o.tcp.ResetsSent,
		o.udp.PacketsReceived,
		o.udp.UnknownPortErrors+o.udp.ReceiveBufferErrors+o.udp.MalformedPacketsReceived,
		o.udp.UnknownPortErrors,
		o.udp.ReceiveBufferErrors,
		o.udp.MalformedPacketsReceived,
		o.udp.PacketsSent,
		o.icmp.received,
		o.icmp.inputFailed,
		o.icmp.inputHistogram,
		o.icmp.sent,
		o.icmp.sentFailed,
		o.icmp.outputHistogram)
}

func (o *statsOutput) add(stats netstack.NetInterfaceStats) {
	tx := stats.Tx
	rx := stats.Rx

	o.icmp.sent += tx.PktsEchoReq + tx.PktsEchoReqV6 + tx.PktsEchoRep + tx.PktsEchoRepV6
	o.icmp.received += rx.PktsEchoReq + rx.PktsEchoReqV6 + rx.PktsEchoRep + rx.PktsEchoRepV6
	o.icmp.outputHistogram.echoRequests += tx.PktsEchoReq + tx.PktsEchoReqV6
	o.icmp.outputHistogram.echoReplies += tx.PktsEchoRep + tx.PktsEchoRepV6
	o.icmp.inputHistogram.echoRequests += rx.PktsEchoReq + rx.PktsEchoReqV6
	o.icmp.inputHistogram.echoReplies += rx.PktsEchoRep + rx.PktsEchoRepV6
}

func dumpStats(a *netstatApp) {
	nics, err := a.netstack.GetInterfaces()
	if err != nil {
		errorf("Failed to get interfaces: %v\n.", err)
		return
	}

	stats := &statsOutput{}
	for _, nic := range nics {
		nicStats, err := a.netstack.GetStats(nic.Id)
		if err != nil {
			errorf("Failed to get statistics for nic: %v\n", err)
		} else {
			stats.add(nicStats)
		}
	}
	as, _ := a.netstack.GetAggregateStats()
	stats.ip = as.IpStats
	stats.tcp = as.TcpStats
	stats.udp = as.UdpStats
	fmt.Printf("%v\n", stats)
}

func dumpRouteTables(a *netstatApp) {
	entries, err := a.netstack.GetRouteTable()
	if err != nil {
		errorf("Failed to get route table: %v\n", err)
		return
	}
	for _, entry := range entries {
		if netAddressZero(entry.Destination) {
			fmt.Printf("default via %s, ", netAddressToString(entry.Gateway))
		} else {
			fmt.Printf("Destination: %s, ", netAddressToString(entry.Destination))
			fmt.Printf("Mask: %s, ", netAddressToString(entry.Netmask))
			if !netAddressZero(entry.Gateway) {
				fmt.Printf("Gateway: %s, ", netAddressToString(entry.Gateway))
			}
		}
		fmt.Printf("NICID: %d\n", entry.Nicid)
	}
}

func netAddressZero(addr net.IpAddress) bool {
	switch addr.Which() {
	case net.IpAddressIpv4:
		for _, b := range addr.Ipv4.Addr {
			if b != 0 {
				return false
			}
		}
		return true
	case net.IpAddressIpv6:
		for _, b := range addr.Ipv6.Addr {
			if b != 0 {
				return false
			}
		}
		return true
	}
	return true
}

// TODO(tamird): this is the same as netAddrToString in ifconfig.
func netAddressToString(addr net.IpAddress) string {
	return fidlconv.ToTCPIPAddress(addr).String()
}

func usage() {
	fmt.Printf("Usage: %s [OPTIONS]\n", os.Args[0])
	flag.PrintDefaults()
}

var hasErrors bool = false

func errorf(format string, args ...interface{}) {
	hasErrors = true
	fmt.Printf("netstat: "+format, args...)
}

func main() {
	a := &netstatApp{ctx: context.CreateFromStartupInfo()}

	flag.Usage = usage

	var showRouteTables bool
	var showStats bool
	flag.BoolVar(&showRouteTables, "r", false, "Dump the Route Tables")
	flag.BoolVar(&showStats, "s", false, "Show network statistics")
	flag.Parse()

	req, pxy, err := netstack.NewNetstackInterfaceRequest()
	if err != nil {
		panic(err.Error())
	}
	a.netstack = pxy
	defer a.netstack.Close()
	a.ctx.ConnectToEnvService(req)

	if showRouteTables {
		dumpRouteTables(a)
	}
	if showStats {
		dumpStats(a)
	}

	if hasErrors {
		os.Exit(1)
	}
}
