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

// +build darwin freebsd linux netbsd openbsd windows

// Sockets

package net

import (
	"io"
	"os"
	"reflect"
	"syscall"
)

// Boolean to int.
func boolint(b bool) int {
	if b {
		return 1
	}
	return 0
}

// Generic socket creation.
func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
	// See ../syscall/exec.go for description of ForkLock.
	syscall.ForkLock.RLock()
	s, e := syscall.Socket(f, p, t)
	if err != nil {
		syscall.ForkLock.RUnlock()
		return nil, err
	}
	syscall.CloseOnExec(s)
	syscall.ForkLock.RUnlock()

	setKernelSpecificSockopt(s, f)

	if la != nil {
		e = syscall.Bind(s, la)
		if e != nil {
			closesocket(s)
			return nil, e
		}
	}

	if fd, err = newFD(s, f, p, net); err != nil {
		closesocket(s)
		return nil, err
	}

	if ra != nil {
		if err = fd.connect(ra); err != nil {
			closesocket(s)
			fd.Close()
			return nil, err
		}
	}

	sa, _ := syscall.Getsockname(s)
	laddr := toAddr(sa)
	sa, _ = syscall.Getpeername(s)
	raddr := toAddr(sa)

	fd.setAddr(laddr, raddr)
	return fd, nil
}

func setsockoptInt(fd *netFD, level, opt int, value int) error {
	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, level, opt, value))
}

func setsockoptNsec(fd *netFD, level, opt int, nsec int64) error {
	var tv = syscall.NsecToTimeval(nsec)
	return os.NewSyscallError("setsockopt", syscall.SetsockoptTimeval(fd.sysfd, level, opt, &tv))
}

func setReadBuffer(fd *netFD, bytes int) error {
	fd.incref()
	defer fd.decref()
	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
}

func setWriteBuffer(fd *netFD, bytes int) error {
	fd.incref()
	defer fd.decref()
	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
}

func setReadTimeout(fd *netFD, nsec int64) error {
	fd.rdeadline_delta = nsec
	return nil
}

func setWriteTimeout(fd *netFD, nsec int64) error {
	fd.wdeadline_delta = nsec
	return nil
}

func setTimeout(fd *netFD, nsec int64) error {
	if e := setReadTimeout(fd, nsec); e != nil {
		return e
	}
	return setWriteTimeout(fd, nsec)
}

func setReuseAddr(fd *netFD, reuse bool) error {
	fd.incref()
	defer fd.decref()
	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
}

func setDontRoute(fd *netFD, dontroute bool) error {
	fd.incref()
	defer fd.decref()
	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))
}

func setKeepAlive(fd *netFD, keepalive bool) error {
	fd.incref()
	defer fd.decref()
	return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
}

func setNoDelay(fd *netFD, noDelay bool) error {
	fd.incref()
	defer fd.decref()
	return setsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
}

func setLinger(fd *netFD, sec int) error {
	var l syscall.Linger
	if sec >= 0 {
		l.Onoff = 1
		l.Linger = int32(sec)
	} else {
		l.Onoff = 0
		l.Linger = 0
	}
	fd.incref()
	defer fd.decref()
	e := syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
	return os.NewSyscallError("setsockopt", e)
}

type UnknownSocketError struct {
	sa syscall.Sockaddr
}

func (e *UnknownSocketError) Error() string {
	return "unknown socket address type " + reflect.TypeOf(e.sa).String()
}

type writerOnly struct {
	io.Writer
}

// Fallback implementation of io.ReaderFrom's ReadFrom, when sendfile isn't
// applicable.
func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
	// Use wrapper to hide existing r.ReadFrom from io.Copy.
	return io.Copy(writerOnly{w}, r)
}
