// Copyright 2016 The Netstack 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 dhcp

import (
	"bytes"
	"context"
	"crypto/rand"
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/buffer"
	"github.com/google/netstack/tcpip/network/ipv4"
	"github.com/google/netstack/tcpip/stack"
	"github.com/google/netstack/tcpip/transport/udp"
	"github.com/google/netstack/waiter"
)

// Client is a DHCP client.
type Client struct {
	stack        *stack.Stack
	nicid        tcpip.NICID
	linkAddr     tcpip.LinkAddress
	acquiredFunc func(old, new tcpip.Address, cfg Config)

	mu          sync.Mutex
	addr        tcpip.Address
	cfg         Config
	lease       time.Duration
	cancelRenew func()
}

// NewClient creates a DHCP client.
//
// TODO(crawshaw): add s.LinkAddr(nicid) to *stack.Stack.
func NewClient(s *stack.Stack, nicid tcpip.NICID, linkAddr tcpip.LinkAddress, acquiredFunc func(old, new tcpip.Address, cfg Config)) *Client {
	return &Client{
		stack:        s,
		nicid:        nicid,
		linkAddr:     linkAddr,
		acquiredFunc: acquiredFunc,
	}
}

// Start starts the DHCP client.
// It will periodically search for an IP address using the Request method.
func (c *Client) Start() {
	go func() {
		for {
			ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
			err := c.Request(ctx, "")
			cancel()
			if err == nil {
				break
			}
			time.Sleep(1 * time.Second)
		}
	}()
}

// Address reports the IP address acquired by the DHCP client.
func (c *Client) Address() tcpip.Address {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.addr
}

// Config reports the DHCP configuration acquired with the IP address lease.
func (c *Client) Config() Config {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.cfg
}

// Shutdown relinquishes any lease and ends any outstanding renewal timers.
func (c *Client) Shutdown() {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.addr != "" {
		c.stack.RemoveAddress(c.nicid, c.addr)
	}
	if c.cancelRenew != nil {
		c.cancelRenew()
	}
}

// Request executes a DHCP request session.
//
// On success, it adds a new address to this client's TCPIP stack.
// If the server sets a lease limit a timer is set to automatically
// renew it.
func (c *Client) Request(ctx context.Context, requestedAddr tcpip.Address) (reterr error) {
	if err := c.stack.AddAddress(c.nicid, ipv4.ProtocolNumber, "\xff\xff\xff\xff"); err != nil && err != tcpip.ErrDuplicateAddress {
		return fmt.Errorf("dhcp: %v", err)
	}
	if err := c.stack.AddAddress(c.nicid, ipv4.ProtocolNumber, "\x00\x00\x00\x00"); err != nil && err != tcpip.ErrDuplicateAddress {
		return fmt.Errorf("dhcp: %v", err)
	}
	defer c.stack.RemoveAddress(c.nicid, "\xff\xff\xff\xff")
	defer c.stack.RemoveAddress(c.nicid, "\x00\x00\x00\x00")

	var wq waiter.Queue
	ep, err := c.stack.NewEndpoint(udp.ProtocolNumber, ipv4.ProtocolNumber, &wq)
	if err != nil {
		return fmt.Errorf("dhcp: outbound endpoint: %v", err)
	}
	err = ep.Bind(tcpip.FullAddress{
		Addr: "\x00\x00\x00\x00",
		Port: clientPort,
		NIC:  c.nicid,
	}, nil)
	defer ep.Close()
	if err != nil {
		return fmt.Errorf("dhcp: connect failed: %v", err)
	}

	epin, err := c.stack.NewEndpoint(udp.ProtocolNumber, ipv4.ProtocolNumber, &wq)
	if err != nil {
		return fmt.Errorf("dhcp: inbound endpoint: %v", err)
	}
	err = epin.Bind(tcpip.FullAddress{
		Addr: "\xff\xff\xff\xff",
		Port: clientPort,
		NIC:  c.nicid,
	}, nil)
	defer epin.Close()
	if err != nil {
		return fmt.Errorf("dhcp: connect failed: %v", err)
	}

	var xid [4]byte
	rand.Read(xid[:])

	// DHCPDISCOVERY
	options := options{
		{optDHCPMsgType, []byte{byte(dhcpDISCOVER)}},
		{optParamReq, []byte{
			1,  // request subnet mask
			3,  // request router
			15, // domain name
			6,  // domain name server
		}},
	}
	if requestedAddr != "" {
		options = append(options, option{optReqIPAddr, []byte(requestedAddr)})
	}
	var clientID []byte
	if len(c.linkAddr) == 6 {
		clientID = make([]byte, 7)
		clientID[0] = 1 // htype: ARP Ethernet from RFC 1700
		copy(clientID[1:], c.linkAddr)
		options = append(options, option{optClientID, clientID})
	}
	h := make(header, headerBaseSize+options.len())
	h.init()
	h.setOp(opRequest)
	copy(h.xidbytes(), xid[:])
	h.setBroadcast()
	copy(h.chaddr(), c.linkAddr)
	h.setOptions(options)

	serverAddr := &tcpip.FullAddress{
		Addr: "\xff\xff\xff\xff",
		Port: serverPort,
		NIC:  c.nicid,
	}
	if _, err := ep.Write(buffer.View(h), serverAddr); err != nil {
		return fmt.Errorf("dhcp discovery write: %v", err)
	}

	we, ch := waiter.NewChannelEntry(nil)
	wq.EventRegister(&we, waiter.EventIn)
	defer wq.EventUnregister(&we)

	// DHCPOFFER
	for {
		var addr tcpip.FullAddress
		v, err := epin.Read(&addr)
		if err == tcpip.ErrWouldBlock {
			select {
			case <-ch:
				continue
			case <-ctx.Done():
				return tcpip.ErrAborted
			}
		}
		h = header(v)
		if h.isValid() && h.op() == opReply && bytes.Equal(h.xidbytes(), xid[:]) {
			break
		}
	}
	opts, err := h.options()
	if err != nil {
		return fmt.Errorf("dhcp offer: %v", err)
	}

	var ack bool
	var cfg Config
	if err := cfg.decode(opts); err != nil {
		return fmt.Errorf("dhcp offer: %v", err)
	}

	// DHCPREQUEST
	addr := tcpip.Address(h.yiaddr())
	if err := c.stack.AddAddress(c.nicid, ipv4.ProtocolNumber, addr); err != nil {
		if err != tcpip.ErrDuplicateAddress {
			return err
		}
	}
	defer func() {
		if !ack || reterr != nil {
			c.stack.RemoveAddress(c.nicid, addr)
			addr = ""
			cfg = Config{Error: reterr}
		}

		c.mu.Lock()
		oldAddr := c.addr
		c.addr = addr
		c.cfg = cfg
		c.mu.Unlock()

		if c.acquiredFunc != nil {
			c.acquiredFunc(oldAddr, addr, cfg)
		}
		if requestedAddr != "" && requestedAddr != addr {
			c.stack.RemoveAddress(c.nicid, requestedAddr)
		}
	}()
	h.setOp(opRequest)
	for i, b := 0, h.yiaddr(); i < len(b); i++ {
		b[i] = 0
	}
	options = []option{
		{optDHCPMsgType, []byte{byte(dhcpREQUEST)}},
		{optReqIPAddr, []byte(addr)},
		{optDHCPServer, []byte(cfg.ServerAddress)},
	}
	if len(clientID) != 0 {
		options = append(options, option{optClientID, clientID})
	}
	h.setOptions(options)
	if _, err := ep.Write([]byte(h), serverAddr); err != nil {
		return fmt.Errorf("dhcp discovery write: %v", err)
	}

	// DHCPACK
	for {
		var addr tcpip.FullAddress
		v, err := epin.Read(&addr)
		if err == tcpip.ErrWouldBlock {
			select {
			case <-ch:
				continue
			case <-ctx.Done():
				return tcpip.ErrAborted
			}
		}
		h = header(v)
		if h.isValid() && h.op() == opReply && bytes.Equal(h.xidbytes(), xid[:]) {
			break
		}
	}
	opts, err = h.options()
	if err != nil {
		return fmt.Errorf("dhcp ack: %v", err)
	}
	if err := cfg.decode(opts); err != nil {
		return fmt.Errorf("dhcp ack bad options: %v", err)
	}
	msgtype, err := opts.dhcpMsgType()
	if err != nil {
		return fmt.Errorf("dhcp ack: %v", err)
	}
	if msgtype == dhcpNAK {
		if msg := opts.message(); msg != "" {
			return fmt.Errorf("dhcp: NAK %q", msg)
		}
		return fmt.Errorf("dhcp: NAK with no message")
	}
	ack = msgtype == dhcpACK
	if !ack {
		return fmt.Errorf("dhcp: request not acknowledged")
	}
	if cfg.LeaseLength != 0 {
		go c.renewAfter(cfg.LeaseLength)
	}
	return nil
}

func (c *Client) renewAfter(d time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.cancelRenew != nil {
		c.cancelRenew()
	}
	ctx, cancel := context.WithCancel(context.Background())
	c.cancelRenew = cancel
	go func() {
		timer := time.NewTimer(d)
		defer timer.Stop()
		select {
		case <-ctx.Done():
		case <-timer.C:
			if err := c.Request(ctx, c.addr); err != nil {
				log.Printf("address renewal failed: %v", err)
				go c.renewAfter(1 * time.Minute)
			}
		}
	}()
}
