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

package net

import (
	
	
	
	
	
)

// BUG(mikio): On JS, WASIP1 and Plan 9, methods and functions related
// to UnixConn and UnixListener are not implemented.

// BUG(mikio): On Windows, methods and functions related to UnixConn
// and UnixListener don't work for "unixgram" and "unixpacket".

// UnixAddr represents the address of a Unix domain socket end point.
type UnixAddr struct {
	Name string
	Net  string
}

// Network returns the address's network name, "unix", "unixgram" or
// "unixpacket".
func ( *UnixAddr) () string {
	return .Net
}

func ( *UnixAddr) () string {
	if  == nil {
		return "<nil>"
	}
	return .Name
}

func ( *UnixAddr) () bool {
	return  == nil || .Name == ""
}

func ( *UnixAddr) () Addr {
	if  == nil {
		return nil
	}
	return 
}

// ResolveUnixAddr returns an address of Unix domain socket end point.
//
// The network must be a Unix network name.
//
// See func [Dial] for a description of the network and address
// parameters.
func (,  string) (*UnixAddr, error) {
	switch  {
	case "unix", "unixgram", "unixpacket":
		return &UnixAddr{Name: , Net: }, nil
	default:
		return nil, UnknownNetworkError()
	}
}

// UnixConn is an implementation of the [Conn] interface for connections
// to Unix domain sockets.
type UnixConn struct {
	conn
}

// SyscallConn returns a raw network connection.
// This implements the [syscall.Conn] interface.
func ( *UnixConn) () (syscall.RawConn, error) {
	if !.ok() {
		return nil, syscall.EINVAL
	}
	return newRawConn(.fd), nil
}

// CloseRead shuts down the reading side of the Unix domain connection.
// Most callers should just use Close.
func ( *UnixConn) () error {
	if !.ok() {
		return syscall.EINVAL
	}
	if  := .fd.closeRead();  != nil {
		return &OpError{Op: "close", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: }
	}
	return nil
}

// CloseWrite shuts down the writing side of the Unix domain connection.
// Most callers should just use Close.
func ( *UnixConn) () error {
	if !.ok() {
		return syscall.EINVAL
	}
	if  := .fd.closeWrite();  != nil {
		return &OpError{Op: "close", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: }
	}
	return nil
}

// ReadFromUnix acts like [UnixConn.ReadFrom] but returns a [UnixAddr].
func ( *UnixConn) ( []byte) (int, *UnixAddr, error) {
	if !.ok() {
		return 0, nil, syscall.EINVAL
	}
	, ,  := .readFrom()
	if  != nil {
		 = &OpError{Op: "read", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: }
	}
	return , , 
}

// ReadFrom implements the [PacketConn] ReadFrom method.
func ( *UnixConn) ( []byte) (int, Addr, error) {
	if !.ok() {
		return 0, nil, syscall.EINVAL
	}
	, ,  := .readFrom()
	if  != nil {
		 = &OpError{Op: "read", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: }
	}
	if  == nil {
		return , nil, 
	}
	return , , 
}

// ReadMsgUnix reads a message from c, copying the payload into b and
// the associated out-of-band data into oob. It returns the number of
// bytes copied into b, the number of bytes copied into oob, the flags
// that were set on the message and the source address of the message.
//
// Note that if len(b) == 0 and len(oob) > 0, this function will still
// read (and discard) 1 byte from the connection.
func ( *UnixConn) (,  []byte) (, ,  int,  *UnixAddr,  error) {
	if !.ok() {
		return 0, 0, 0, nil, syscall.EINVAL
	}
	, , , ,  = .readMsg(, )
	if  != nil {
		 = &OpError{Op: "read", Net: .fd.net, Source: .fd.laddr, Addr: .fd.raddr, Err: }
	}
	return
}

// WriteToUnix acts like [UnixConn.WriteTo] but takes a [UnixAddr].
func ( *UnixConn) ( []byte,  *UnixAddr) (int, error) {
	if !.ok() {
		return 0, syscall.EINVAL
	}
	,  := .writeTo(, )
	if  != nil {
		 = &OpError{Op: "write", Net: .fd.net, Source: .fd.laddr, Addr: .opAddr(), Err: }
	}
	return , 
}

// WriteTo implements the [PacketConn] WriteTo method.
func ( *UnixConn) ( []byte,  Addr) (int, error) {
	if !.ok() {
		return 0, syscall.EINVAL
	}
	,  := .(*UnixAddr)
	if ! {
		return 0, &OpError{Op: "write", Net: .fd.net, Source: .fd.laddr, Addr: , Err: syscall.EINVAL}
	}
	,  := .writeTo(, )
	if  != nil {
		 = &OpError{Op: "write", Net: .fd.net, Source: .fd.laddr, Addr: .opAddr(), Err: }
	}
	return , 
}

// WriteMsgUnix writes a message to addr via c, copying the payload
// from b and the associated out-of-band data from oob. It returns the
// number of payload and out-of-band bytes written.
//
// Note that if len(b) == 0 and len(oob) > 0, this function will still
// write 1 byte to the connection.
func ( *UnixConn) (,  []byte,  *UnixAddr) (,  int,  error) {
	if !.ok() {
		return 0, 0, syscall.EINVAL
	}
	, ,  = .writeMsg(, , )
	if  != nil {
		 = &OpError{Op: "write", Net: .fd.net, Source: .fd.laddr, Addr: .opAddr(), Err: }
	}
	return
}

func newUnixConn( *netFD) *UnixConn { return &UnixConn{conn{}} }

// DialUnix acts like [Dial] for Unix networks.
//
// The network must be a Unix network name; see func Dial for details.
//
// If laddr is non-nil, it is used as the local address for the
// connection.
func ( string, ,  *UnixAddr) (*UnixConn, error) {
	switch  {
	case "unix", "unixgram", "unixpacket":
	default:
		return nil, &OpError{Op: "dial", Net: , Source: .opAddr(), Addr: .opAddr(), Err: UnknownNetworkError()}
	}
	 := &sysDialer{network: , address: .String()}
	,  := .dialUnix(context.Background(), , )
	if  != nil {
		return nil, &OpError{Op: "dial", Net: , Source: .opAddr(), Addr: .opAddr(), Err: }
	}
	return , nil
}

// UnixListener is a Unix domain socket listener. Clients should
// typically use variables of type [Listener] instead of assuming Unix
// domain sockets.
type UnixListener struct {
	fd         *netFD
	path       string
	unlink     bool
	unlinkOnce sync.Once
}

func ( *UnixListener) () bool { return  != nil && .fd != nil }

// SyscallConn returns a raw network connection.
// This implements the [syscall.Conn] interface.
//
// The returned RawConn only supports calling Control. Read and
// Write return an error.
func ( *UnixListener) () (syscall.RawConn, error) {
	if !.ok() {
		return nil, syscall.EINVAL
	}
	return newRawListener(.fd), nil
}

// AcceptUnix accepts the next incoming call and returns the new
// connection.
func ( *UnixListener) () (*UnixConn, error) {
	if !.ok() {
		return nil, syscall.EINVAL
	}
	,  := .accept()
	if  != nil {
		return nil, &OpError{Op: "accept", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: }
	}
	return , nil
}

// Accept implements the Accept method in the [Listener] interface.
// Returned connections will be of type [*UnixConn].
func ( *UnixListener) () (Conn, error) {
	if !.ok() {
		return nil, syscall.EINVAL
	}
	,  := .accept()
	if  != nil {
		return nil, &OpError{Op: "accept", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: }
	}
	return , nil
}

// Close stops listening on the Unix address. Already accepted
// connections are not closed.
func ( *UnixListener) () error {
	if !.ok() {
		return syscall.EINVAL
	}
	if  := .close();  != nil {
		return &OpError{Op: "close", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: }
	}
	return nil
}

// Addr returns the listener's network address.
// The Addr returned is shared by all invocations of Addr, so
// do not modify it.
func ( *UnixListener) () Addr { return .fd.laddr }

// SetDeadline sets the deadline associated with the listener.
// A zero time value disables the deadline.
func ( *UnixListener) ( time.Time) error {
	if !.ok() {
		return syscall.EINVAL
	}
	return .fd.SetDeadline()
}

// File returns a copy of the underlying [os.File].
// It is the caller's responsibility to close f when finished.
// Closing l does not affect f, and closing f does not affect l.
//
// The returned os.File's file descriptor is different from the
// connection's. Attempting to change properties of the original
// using this duplicate may or may not have the desired effect.
func ( *UnixListener) () ( *os.File,  error) {
	if !.ok() {
		return nil, syscall.EINVAL
	}
	,  = .file()
	if  != nil {
		 = &OpError{Op: "file", Net: .fd.net, Source: nil, Addr: .fd.laddr, Err: }
	}
	return
}

// ListenUnix acts like [Listen] for Unix networks.
//
// The network must be "unix" or "unixpacket".
func ( string,  *UnixAddr) (*UnixListener, error) {
	switch  {
	case "unix", "unixpacket":
	default:
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: .opAddr(), Err: UnknownNetworkError()}
	}
	if  == nil {
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: .opAddr(), Err: errMissingAddress}
	}
	 := &sysListener{network: , address: .String()}
	,  := .listenUnix(context.Background(), )
	if  != nil {
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: .opAddr(), Err: }
	}
	return , nil
}

// ListenUnixgram acts like [ListenPacket] for Unix networks.
//
// The network must be "unixgram".
func ( string,  *UnixAddr) (*UnixConn, error) {
	switch  {
	case "unixgram":
	default:
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: .opAddr(), Err: UnknownNetworkError()}
	}
	if  == nil {
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: nil, Err: errMissingAddress}
	}
	 := &sysListener{network: , address: .String()}
	,  := .listenUnixgram(context.Background(), )
	if  != nil {
		return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: .opAddr(), Err: }
	}
	return , nil
}