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

// IP sockets stubs for Plan 9

package net

import (
	"errors"
	"io"
	"os"
)

// probeIPv6Stack returns two boolean values.  If the first boolean value is
// true, kernel supports basic IPv6 functionality.  If the second
// boolean value is true, kernel supports IPv6 IPv4-mapping.
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
	return false, false
}

// parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80).
func parsePlan9Addr(s string) (ip IP, iport int, err error) {
	var (
		addr IP
		p, i int
		ok   bool
	)
	addr = IPv4zero // address contains port only
	i = byteIndex(s, '!')
	if i >= 0 {
		addr = ParseIP(s[:i])
		if addr == nil {
			err = errors.New("net: parsing IP failed")
			goto Error
		}
	}
	p, _, ok = dtoi(s[i+1:], 0)
	if !ok {
		err = errors.New("net: parsing port failed")
		goto Error
	}
	if p < 0 || p > 0xFFFF {
		err = &AddrError{"invalid port", string(p)}
		goto Error
	}
	return addr, p, nil

Error:
	return nil, 0, err
}

func readPlan9Addr(proto, filename string) (addr Addr, err error) {
	var buf [128]byte

	f, err := os.Open(filename)
	if err != nil {
		return
	}
	n, err := f.Read(buf[:])
	if err != nil {
		return
	}
	ip, port, err := parsePlan9Addr(string(buf[:n]))
	if err != nil {
		return
	}
	switch proto {
	case "tcp":
		addr = &TCPAddr{ip, port}
	case "udp":
		addr = &UDPAddr{ip, port}
	default:
		return nil, errors.New("unknown protocol " + proto)
	}
	return addr, nil
}

type plan9Conn struct {
	proto, name, dir string
	ctl, data        *os.File
	laddr, raddr     Addr
}

func newPlan9Conn(proto, name string, ctl *os.File, laddr, raddr Addr) *plan9Conn {
	return &plan9Conn{proto, name, "/net/" + proto + "/" + name, ctl, nil, laddr, raddr}
}

func (c *plan9Conn) ok() bool { return c != nil && c.ctl != nil }

// Implementation of the Conn interface - see Conn for documentation.

// Read implements the net.Conn Read method.
func (c *plan9Conn) Read(b []byte) (n int, err error) {
	if !c.ok() {
		return 0, os.EINVAL
	}
	if c.data == nil {
		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
		if err != nil {
			return 0, err
		}
	}
	n, err = c.data.Read(b)
	if c.proto == "udp" && err == io.EOF {
		n = 0
		err = nil
	}
	return
}

// Write implements the net.Conn Write method.
func (c *plan9Conn) Write(b []byte) (n int, err error) {
	if !c.ok() {
		return 0, os.EINVAL
	}
	if c.data == nil {
		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
		if err != nil {
			return 0, err
		}
	}
	return c.data.Write(b)
}

// Close closes the connection.
func (c *plan9Conn) Close() error {
	if !c.ok() {
		return os.EINVAL
	}
	err := c.ctl.Close()
	if err != nil {
		return err
	}
	if c.data != nil {
		err = c.data.Close()
	}
	c.ctl = nil
	c.data = nil
	return err
}

// LocalAddr returns the local network address.
func (c *plan9Conn) LocalAddr() Addr {
	if !c.ok() {
		return nil
	}
	return c.laddr
}

// RemoteAddr returns the remote network address.
func (c *plan9Conn) RemoteAddr() Addr {
	if !c.ok() {
		return nil
	}
	return c.raddr
}

// SetTimeout implements the net.Conn SetTimeout method.
func (c *plan9Conn) SetTimeout(nsec int64) error {
	if !c.ok() {
		return os.EINVAL
	}
	return os.EPLAN9
}

// SetReadTimeout implements the net.Conn SetReadTimeout method.
func (c *plan9Conn) SetReadTimeout(nsec int64) error {
	if !c.ok() {
		return os.EINVAL
	}
	return os.EPLAN9
}

// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
func (c *plan9Conn) SetWriteTimeout(nsec int64) error {
	if !c.ok() {
		return os.EINVAL
	}
	return os.EPLAN9
}

func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) {
	var (
		ip   IP
		port int
	)
	switch a := addr.(type) {
	case *TCPAddr:
		proto = "tcp"
		ip = a.IP
		port = a.Port
	case *UDPAddr:
		proto = "udp"
		ip = a.IP
		port = a.Port
	default:
		err = UnknownNetworkError(net)
		return
	}

	clone, dest, err := queryCS1(proto, ip, port)
	if err != nil {
		return
	}
	f, err := os.OpenFile(clone, os.O_RDWR, 0)
	if err != nil {
		return
	}
	var buf [16]byte
	n, err := f.Read(buf[:])
	if err != nil {
		return
	}
	return f, dest, proto, string(buf[:n]), nil
}

func dialPlan9(net string, laddr, raddr Addr) (c *plan9Conn, err error) {
	f, dest, proto, name, err := startPlan9(net, raddr)
	if err != nil {
		return
	}
	_, err = f.WriteString("connect " + dest)
	if err != nil {
		return
	}
	laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
	if err != nil {
		return
	}
	raddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/remote")
	if err != nil {
		return
	}
	return newPlan9Conn(proto, name, f, laddr, raddr), nil
}

type plan9Listener struct {
	proto, name, dir string
	ctl              *os.File
	laddr            Addr
}

func listenPlan9(net string, laddr Addr) (l *plan9Listener, err error) {
	f, dest, proto, name, err := startPlan9(net, laddr)
	if err != nil {
		return
	}
	_, err = f.WriteString("announce " + dest)
	if err != nil {
		return
	}
	laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local")
	if err != nil {
		return
	}
	l = new(plan9Listener)
	l.proto = proto
	l.name = name
	l.dir = "/net/" + proto + "/" + name
	l.ctl = f
	l.laddr = laddr
	return l, nil
}

func (l *plan9Listener) plan9Conn() *plan9Conn {
	return newPlan9Conn(l.proto, l.name, l.ctl, l.laddr, nil)
}

func (l *plan9Listener) acceptPlan9() (c *plan9Conn, err error) {
	f, err := os.Open(l.dir + "/listen")
	if err != nil {
		return
	}
	var buf [16]byte
	n, err := f.Read(buf[:])
	if err != nil {
		return
	}
	name := string(buf[:n])
	laddr, err := readPlan9Addr(l.proto, l.dir+"/local")
	if err != nil {
		return
	}
	raddr, err := readPlan9Addr(l.proto, l.dir+"/remote")
	if err != nil {
		return
	}
	return newPlan9Conn(l.proto, name, f, laddr, raddr), nil
}

func (l *plan9Listener) Accept() (c Conn, err error) {
	c1, err := l.acceptPlan9()
	if err != nil {
		return
	}
	return c1, nil
}

func (l *plan9Listener) Close() error {
	if l == nil || l.ctl == nil {
		return os.EINVAL
	}
	return l.ctl.Close()
}

func (l *plan9Listener) Addr() Addr { return l.laddr }
