// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Package vmimpl provides an abstract test machine (VM, physical machine, etc)
// interface for the rest of the system. For convenience test machines are subsequently
// collectively called VMs.
// The package also provides various utility functions for VM implementations.
package vmimpl

import (
	"errors"
	"fmt"
	"io"
	"math/rand"
	"net"
	"os/exec"
	"time"

	"github.com/google/syzkaller/pkg/log"
)

// Pool represents a set of test machines (VMs, physical devices, etc) of particular type.
type Pool interface {
	// Count returns total number of VMs in the pool.
	Count() int

	// Create creates and boots a new VM instance.
	Create(workdir string, index int) (Instance, error)
}

// Instance represents a single VM.
type Instance interface {
	// Copy copies a hostSrc file into VM and returns file name in VM.
	Copy(hostSrc string) (string, error)

	// Forward setups forwarding from within VM to host port port
	// and returns address to use in VM.
	Forward(port int) (string, error)

	// Run runs cmd inside of the VM (think of ssh cmd).
	// outc receives combined cmd and kernel console output.
	// errc receives either command Wait return error or vmimpl.ErrTimeout.
	// Command is terminated after timeout. Send on the stop chan can be used to terminate it earlier.
	Run(timeout time.Duration, stop <-chan bool, command string) (outc <-chan []byte, errc <-chan error, err error)

	// Diagnose forces VM to dump additional debugging info
	// (e.g. sending some sys-rq's or SIGABORT'ing a Go program).
	// Returns true if it did anything.
	Diagnose() bool

	// Close stops and destroys the VM.
	Close()
}

// Env contains global constant parameters for a pool of VMs.
type Env struct {
	// Unique name
	// Can be used for VM name collision resolution if several pools share global name space.
	Name    string
	OS      string // target OS
	Arch    string // target arch
	Workdir string
	Image   string
	SSHKey  string
	SSHUser string
	Debug   bool
	Config  []byte // json-serialized VM-type-specific config
}

// BootError is returned by Pool.Create when VM does not boot.
type BootError struct {
	Title  string
	Output []byte
}

func (err BootError) Error() string {
	return fmt.Sprintf("%v\n%s", err.Title, err.Output)
}

func (err BootError) BootError() (string, []byte) {
	return err.Title, err.Output
}

// Create creates a VM type that can be used to create individual VMs.
func Create(typ string, env *Env) (Pool, error) {
	ctor := ctors[typ]
	if ctor == nil {
		return nil, fmt.Errorf("unknown instance type '%v'", typ)
	}
	return ctor(env)
}

// Register registers a new VM type within the package.
func Register(typ string, ctor ctorFunc) {
	ctors[typ] = ctor
}

var (
	// Close to interrupt all pending operations in all VMs.
	Shutdown   = make(chan struct{})
	ErrTimeout = errors.New("timeout")

	ctors = make(map[string]ctorFunc)
)

type ctorFunc func(env *Env) (Pool, error)

func Multiplex(cmd *exec.Cmd, merger *OutputMerger, console io.Closer, timeout time.Duration,
	stop, closed <-chan bool, debug bool) (<-chan []byte, <-chan error, error) {
	errc := make(chan error, 1)
	signal := func(err error) {
		select {
		case errc <- err:
		default:
		}
	}
	go func() {
		select {
		case <-time.After(timeout):
			signal(ErrTimeout)
		case <-stop:
			signal(ErrTimeout)
		case <-closed:
			if debug {
				log.Logf(0, "instance closed")
			}
			signal(fmt.Errorf("instance closed"))
		case err := <-merger.Err:
			cmd.Process.Kill()
			console.Close()
			merger.Wait()
			if cmdErr := cmd.Wait(); cmdErr == nil {
				// If the command exited successfully, we got EOF error from merger.
				// But in this case no error has happened and the EOF is expected.
				err = nil
			}
			signal(err)
			return
		}
		cmd.Process.Kill()
		console.Close()
		merger.Wait()
		cmd.Wait()
	}()
	return merger.Output, errc, nil
}

func RandomPort() int {
	return rand.Intn(64<<10-1<<10) + 1<<10
}

func UnusedTCPPort() int {
	for {
		port := RandomPort()
		ln, err := net.Listen("tcp", fmt.Sprintf("localhost:%v", port))
		if err == nil {
			ln.Close()
			return port
		}
	}
}
