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

package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"time"

	"go.fuchsia.dev/fuchsia/tools/net/mdns"
)

// TODO(jakehehrlich): This doesn't retry or anything, it just times out. It would
// be nice to make this more robust.
// sends out a request for the ip of domain. Waits for up to |dur| amount of time.
// Will stop waiting for a response if ctx is done. The default port for mDNS is
// 5353 but you're allowed to specify via port.
func mDNSResolve(ctx context.Context, domain string, port int, dur time.Duration) (net.IP, error) {
	m := mdns.NewMDNS()
	m.EnableIPv4()
	m.EnableIPv6()
	out := make(chan net.IP)
	// Add all of our handlers
	m.AddHandler(func(addr net.Addr, packet mdns.Packet) {
		for _, a := range packet.Answers {
			if a.Class != mdns.IN || a.Domain != domain {
				continue
			}
			if a.Type == mdns.A || a.Type == mdns.AAAA {
				out <- net.IP(a.Data)
				return
			}
		}
	})
	m.AddWarningHandler(func(addr net.Addr, err error) {
		log.Printf("from: %v warn: %v", addr, err)
	})
	errs := make(chan error)
	m.AddErrorHandler(func(err error) {
		errs <- err
	})
	// Before we start we need to add a context to timeout with
	ctx, cancel := context.WithTimeout(ctx, dur)
	defer cancel()
	// Start up the mdns loop
	if err := m.Start(ctx, port); err != nil {
		return nil, fmt.Errorf("starting mdns: %v", err)
	}
	// Send a packet requesting an answer to "what is the IP of |domain|?"
	m.Send(ctx, mdns.QuestionPacket(domain))
	// Now wait for either a timeout, an error, or an answer.
	select {
	case <-ctx.Done():
		return nil, fmt.Errorf("timeout")
	case err := <-errs:
		return nil, err
	case ip := <-out:
		return ip, nil
	}
}

// TODO(jakehehrlich): Add support for unicast.
// mDNSPublish will respond to requests for the ip of domain by responding with ip.
// Note that this responds on both IPv4 and IPv6 interfaces, independent on the type
// of ip itself. You can stop the server by canceling ctx. Even though mDNS is
// generally on 5353 you can specify any port via port.
func mDNSPublish(ctx context.Context, domain string, port int, ip net.IP) error {
	// Now create and mDNS server
	m := mdns.NewMDNS()
	m.EnableIPv4()
	m.EnableIPv6()
	addrType := mdns.IpToDnsRecordType(ip)
	m.AddHandler(func(addr net.Addr, packet mdns.Packet) {
		log.Printf("from %v packet %v", addr, packet)
		for _, q := range packet.Questions {
			if q.Class == mdns.IN && q.Type == addrType && q.Domain == domain {
				// We ignore the Unicast bit here but in theory this could be handled via SendTo and addr.
				m.Send(ctx, mdns.AnswerPacket(domain, ip))
			}
		}
	})
	m.AddWarningHandler(func(addr net.Addr, err error) {
		log.Printf("from: %v warn: %v", addr, err)
	})
	errs := make(chan error)
	m.AddErrorHandler(func(err error) {
		errs <- err
	})
	// Now start the server.
	if err := m.Start(ctx, port); err != nil {
		return fmt.Errorf("starting mdns: %v", err)
	}
	// Now wait for either a timeout, an error, or an answer.
	select {
	case <-ctx.Done():
		return nil
	case err := <-errs:
		return err
	}
}

// This function makes a faulty assumption. It assumes that the first
// multicast interface it finds with an ipv4 address will be the
// address the user wants. There isn't really a way to guess exactly
// the address that the user will want. If an IPv6 address is needed, then
// using the -ip <address> option is required.
func getMulticastIP() net.IP {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil
	}
	for _, i := range ifaces {
		if i.Flags&net.FlagMulticast == 0 {
			continue
		}
		addrs, err := i.Addrs()
		if err != nil {
			return nil
		}
		for _, addr := range addrs {
			switch v := addr.(type) {
			case *net.IPNet:
				if ip4 := v.IP.To4(); ip4 != nil {
					return ip4
				}
			}
		}
	}
	return nil
}

var (
	port    int
	timeout time.Duration
	ipAddr  string
)

func init() {
	flag.StringVar(&ipAddr, "ip", "", "the ip to respond with when serving.")
	flag.IntVar(&port, "port", 5353, "the port your mDNS servers operate on")
	flag.DurationVar(&timeout, "timeout", 2*time.Second, "the duration before declaring a timeout")
}

func publish(args ...string) error {
	if len(args) < 1 {
		return fmt.Errorf("missing domain to serve")
	}
	var ip net.IP
	if ipAddr == "" {
		ip = getMulticastIP()
		if ip = getMulticastIP(); ip == nil {
			return fmt.Errorf("could not find a suitable ip")
		}
	} else {
		if ip = net.ParseIP(ipAddr); ip == nil {
			return fmt.Errorf("'%s' is not a valid ip address", ipAddr)
		}
	}
	domain := args[0]
	if err := mDNSPublish(context.Background(), domain, port, ip); err != nil {
		return err
	}
	return nil
}

func resolve(args ...string) error {
	if len(args) < 1 {
		return fmt.Errorf("missing domain to request")
	}
	domain := args[0]
	ip, err := mDNSResolve(context.Background(), domain, port, timeout)
	if err != nil {
		return err
	}
	fmt.Printf("%v\n", ip)
	return nil
}

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) < 1 {
		log.Printf("error: no command given")
		os.Exit(1)
	}
	mp := map[string]func(...string) error{
		"publish": publish,
		"resolve": resolve,
	}
	if f, ok := mp[args[0]]; ok {
		if err := f(args[1:]...); err != nil {
			log.Printf("error: %v", err)
		}
		return
	} else {
		log.Printf("error: %s is not a command", args[0])
	}
	os.Exit(1)
}
