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

//go:build unix

package net

import (
	
	
	
)

func dupSocket( *os.File) (int, error) {
	, ,  := poll.DupCloseOnExec(int(.Fd()))
	if  != nil {
		if  != "" {
			 = os.NewSyscallError(, )
		}
		return -1, 
	}
	if  := syscall.SetNonblock(, true);  != nil {
		poll.CloseFunc()
		return -1, os.NewSyscallError("setnonblock", )
	}
	return , nil
}

func newFileFD( *os.File) (*netFD, error) {
	,  := dupSocket()
	if  != nil {
		return nil, 
	}
	 := syscall.AF_UNSPEC
	,  := syscall.GetsockoptInt(, syscall.SOL_SOCKET, syscall.SO_TYPE)
	if  != nil {
		poll.CloseFunc()
		return nil, os.NewSyscallError("getsockopt", )
	}
	,  := syscall.Getsockname()
	,  := syscall.Getpeername()
	switch .(type) {
	case *syscall.SockaddrInet4:
		 = syscall.AF_INET
	case *syscall.SockaddrInet6:
		 = syscall.AF_INET6
	case *syscall.SockaddrUnix:
		 = syscall.AF_UNIX
	default:
		poll.CloseFunc()
		return nil, syscall.EPROTONOSUPPORT
	}
	,  := newFD(, , , "")
	if  != nil {
		poll.CloseFunc()
		return nil, 
	}
	 := .addrFunc()()
	 := .addrFunc()()
	.net = .Network()
	if  := .init();  != nil {
		.Close()
		return nil, 
	}
	.setAddr(, )
	return , nil
}

func fileConn( *os.File) (Conn, error) {
	,  := newFileFD()
	if  != nil {
		return nil, 
	}
	switch .laddr.(type) {
	case *TCPAddr:
		return newTCPConn(, defaultTCPKeepAliveIdle, KeepAliveConfig{}, testPreHookSetKeepAlive, testHookSetKeepAlive), nil
	case *UDPAddr:
		return newUDPConn(), nil
	case *IPAddr:
		return newIPConn(), nil
	case *UnixAddr:
		return newUnixConn(), nil
	}
	.Close()
	return nil, syscall.EINVAL
}

func fileListener( *os.File) (Listener, error) {
	,  := newFileFD()
	if  != nil {
		return nil, 
	}
	switch laddr := .laddr.(type) {
	case *TCPAddr:
		return &TCPListener{fd: }, nil
	case *UnixAddr:
		return &UnixListener{fd: , path: .Name, unlink: false}, nil
	}
	.Close()
	return nil, syscall.EINVAL
}

func filePacketConn( *os.File) (PacketConn, error) {
	,  := newFileFD()
	if  != nil {
		return nil, 
	}
	switch .laddr.(type) {
	case *UDPAddr:
		return newUDPConn(), nil
	case *IPAddr:
		return newIPConn(), nil
	case *UnixAddr:
		return newUnixConn(), nil
	}
	.Close()
	return nil, syscall.EINVAL
}