// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// TODO: Document the protocol once it settles.

package probe

import (
	"errors"
	"io" // Used only for the definitions of the various interfaces and errors.
	"net"

	"code.google.com/p/ogle/socket"
)

var (
	tracing   = false
	listening = make(chan struct{})
)

// init starts a listener and leaves it in the background waiting for connections.
func init() {
	go demon()
}

// demon answers consecutive connection requests and starts a server to manage each one.
// The server runs in the same goroutine as the demon, so a new connection cannot be
// established until the previous one is completed.
func demon() {
	listener, err := socket.Listen()
	close(listening)
	if err != nil {
		trace("listen:", err)
		return
	}
	trace("listening")
	for {
		conn, err := listener.Accept()
		if err != nil {
			trace("accept", err)
			continue
		}
		trace("accepted a connection")
		serve(conn)
		conn.Close()
	}
}

// stringer is the same as fmt.Stringer. We redefine it here to avoid pulling in fmt.
type stringer interface {
	String() string
}

func printHex(b byte) {
	const hex = "0123456789ABCDEF"
	b1, b0 := b>>4&0xF, b&0xF
	print(hex[b1:b1+1], hex[b0:b0+1])
}

// trace is a simple version of println that is enabled by the tracing boolean.
func trace(args ...interface{}) {
	if !tracing {
		return
	}
	print("ogle demon: ")
	for i, arg := range args {
		if i > 0 {
			print(" ")
		}
		// A little help. Built-in print isn't very capable.
		switch arg := arg.(type) {
		case stringer:
			print(arg.String())
		case error:
			print(arg.Error())
		case []byte:
			print("[")
			for i := range arg {
				if i > 0 {
					print(" ")
				}
				printHex(arg[i])
			}
			print("]")
		case int:
			print(arg)
		case string:
			print(arg)
		case uintptr:
			print("0x")
			for i := ptrSize - 1; i >= 0; i-- {
				printHex(byte(arg >> uint(8*i)))
			}
		default:
			print(arg)
		}
	}
	print("\n")
}

func serve(conn net.Conn) {
	const (
		bufSize = 1 << 16
	)
	var buf [bufSize]byte
	network := &pipe{
		rw: conn,
	}
	for {
		// One message per loop.
		n, err := network.Read(buf[:1])
		if n != 1 || err != nil {
			return
		}
		switch buf[0] {
		case 'r':
			// Read: ['r', address, size] => [0, size, size bytes]
			u, err := network.readUintptr()
			if err != nil {
				return
			}
			n, err := network.readInt()
			if err != nil {
				return
			}
			if !validRead(u, n) {
				trace("read", err)
				network.error("invalid read address")
				continue
			}
			network.sendReadResponse(u, n)
		default:
			// TODO: shut down connection?
			trace("unknown message type:", buf[0])
		}
	}
}

// pipe is a buffered network connection (actually just a reader/writer) that
// implements Read and ReadByte as well as readFull.
// It also has support routines to make it easier to read and write
// network messages.
type pipe struct {
	rw      io.ReadWriter
	pos     int
	end     int
	oneByte [1]byte
	buf     [4096]byte
}

// readFull fills the argument slice with data from the wire. If it cannot fill the
// slice, it returns an error.
// TODO: unused for now; write will need it.
func (p *pipe) readFull(buf []byte) error {
	for len(buf) > 0 {
		n, err := p.rw.Read(buf)
		if n == len(buf) {
			return nil
		}
		if err != nil {
			if err == io.EOF {
				err = io.ErrUnexpectedEOF
			}
			return err
		}
		if n == 0 {
			return io.EOF
		}
		buf = buf[n:]
	}
	return nil
}

// Read satisfies io.Reader.
func (p *pipe) Read(buf []byte) (int, error) {
	n := len(buf)
	if p.end == p.pos {
		p.pos = 0
		// Read from network
		var err error
		p.end, err = p.rw.Read(p.buf[:])
		if err != nil {
			trace("read:", err)
			return p.end, err
		}
		if p.end == 0 {
			trace("read: eof")
			return p.end, io.EOF
		}
	}
	if n > p.end-p.pos {
		n = p.end - p.pos
	}
	copy(buf, p.buf[p.pos:p.pos+n])
	p.pos += n
	return n, nil
}

// ReadByte satisfies io.ByteReader.
func (p *pipe) ReadByte() (byte, error) {
	_, err := p.Read(p.oneByte[:])
	return p.oneByte[0], err
}

// readUintptr reads a varint-encoded uinptr value from the connection.
func (p *pipe) readUintptr() (uintptr, error) {
	u, err := readUvarint(p)
	if err != nil {
		trace("read uintptr:", err)
		return 0, err
	}
	if u > uint64(^uintptr(0)) {
		trace("read uintptr: overflow")
		return 0, err
	}
	return uintptr(u), nil
}

var intOverflow = errors.New("ogle probe: varint overflows int")

// readInt reads an varint-encoded int value from the connection.
// The transported value is always a uint64; this routine
// verifies that it fits in an int.
func (p *pipe) readInt() (int, error) {
	u, err := readUvarint(p)
	if err != nil {
		trace("read int:", err)
		return 0, err
	}
	// Does it fit in an int?
	if u > maxInt {
		trace("int overflow")
		return 0, intOverflow
	}
	return int(u), nil
}

// error writes an error message to the connection.
// The format is [size, size bytes].
func (p *pipe) error(msg string) {
	// A zero-length message is problematic. It should never arise, but be safe.
	if len(msg) == 0 {
		msg = "undefined error"
	}
	// Truncate if necessary. Extremely unlikely.
	if len(msg) > len(p.buf)-maxVarintLen64 {
		msg = msg[:len(p.buf)-maxVarintLen64]
	}
	n := putUvarint(p.buf[:], uint64(len(msg)))
	n += copy(p.buf[n:], msg)
	_, err := p.rw.Write(p.buf[:n])
	if err != nil {
		trace("write:", err)
		// TODO: shut down connection?
	}
}

// sendReadResponse sends a read response to the connection.
// The format is [0, size, size bytes].
func (p *pipe) sendReadResponse(addr uintptr, size int) {
	trace("sendRead:", addr, size)
	m := 0
	m += putUvarint(p.buf[m:], 0)            // No error.
	m += putUvarint(p.buf[m:], uint64(size)) // Number of bytes to follow.
	for m > 0 || size > 0 {
		n := len(p.buf) - m
		if n > size {
			n = size
		}
		if !read(addr, p.buf[m:m+n]) {
			trace("copy error")
			// TODO: shut down connection?
			// TODO: for now, continue delivering data. We said we would.
		}
		_, err := p.rw.Write(p.buf[:m+n])
		if err != nil {
			trace("write:", err)
			// TODO: shut down connection?
		}
		addr += uintptr(n)
		size -= n
		// Next time we can use the whole buffer.
		m = 0
	}
}
