...
Run Format

Source file src/net/unixsock.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package net
     6	
     7	import (
     8		"context"
     9		"os"
    10		"sync"
    11		"syscall"
    12		"time"
    13	)
    14	
    15	// UnixAddr represents the address of a Unix domain socket end point.
    16	type UnixAddr struct {
    17		Name string
    18		Net  string
    19	}
    20	
    21	// Network returns the address's network name, "unix", "unixgram" or
    22	// "unixpacket".
    23	func (a *UnixAddr) Network() string {
    24		return a.Net
    25	}
    26	
    27	func (a *UnixAddr) String() string {
    28		if a == nil {
    29			return "<nil>"
    30		}
    31		return a.Name
    32	}
    33	
    34	func (a *UnixAddr) isWildcard() bool {
    35		return a == nil || a.Name == ""
    36	}
    37	
    38	func (a *UnixAddr) opAddr() Addr {
    39		if a == nil {
    40			return nil
    41		}
    42		return a
    43	}
    44	
    45	// ResolveUnixAddr parses addr as a Unix domain socket address.
    46	// The string net gives the network name, "unix", "unixgram" or
    47	// "unixpacket".
    48	func ResolveUnixAddr(net, addr string) (*UnixAddr, error) {
    49		switch net {
    50		case "unix", "unixgram", "unixpacket":
    51			return &UnixAddr{Name: addr, Net: net}, nil
    52		default:
    53			return nil, UnknownNetworkError(net)
    54		}
    55	}
    56	
    57	// UnixConn is an implementation of the Conn interface for connections
    58	// to Unix domain sockets.
    59	type UnixConn struct {
    60		conn
    61	}
    62	
    63	// CloseRead shuts down the reading side of the Unix domain connection.
    64	// Most callers should just use Close.
    65	func (c *UnixConn) CloseRead() error {
    66		if !c.ok() {
    67			return syscall.EINVAL
    68		}
    69		if err := c.fd.closeRead(); err != nil {
    70			return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
    71		}
    72		return nil
    73	}
    74	
    75	// CloseWrite shuts down the writing side of the Unix domain connection.
    76	// Most callers should just use Close.
    77	func (c *UnixConn) CloseWrite() error {
    78		if !c.ok() {
    79			return syscall.EINVAL
    80		}
    81		if err := c.fd.closeWrite(); err != nil {
    82			return &OpError{Op: "close", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
    83		}
    84		return nil
    85	}
    86	
    87	// ReadFromUnix reads a packet from c, copying the payload into b. It
    88	// returns the number of bytes copied into b and the source address of
    89	// the packet.
    90	//
    91	// ReadFromUnix can be made to time out and return an error with
    92	// Timeout() == true after a fixed time limit; see SetDeadline and
    93	// SetReadDeadline.
    94	func (c *UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error) {
    95		if !c.ok() {
    96			return 0, nil, syscall.EINVAL
    97		}
    98		n, addr, err := c.readFrom(b)
    99		if err != nil {
   100			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   101		}
   102		return n, addr, err
   103	}
   104	
   105	// ReadFrom implements the PacketConn ReadFrom method.
   106	func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
   107		if !c.ok() {
   108			return 0, nil, syscall.EINVAL
   109		}
   110		n, addr, err := c.readFrom(b)
   111		if err != nil {
   112			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   113		}
   114		if addr == nil {
   115			return n, nil, err
   116		}
   117		return n, addr, err
   118	}
   119	
   120	// ReadMsgUnix reads a packet from c, copying the payload into b and
   121	// the associated out-of-band data into oob. It returns the number of
   122	// bytes copied into b, the number of bytes copied into oob, the flags
   123	// that were set on the packet, and the source address of the packet.
   124	//
   125	// Note that if len(b) == 0 and len(oob) > 0, this function will still
   126	// read (and discard) 1 byte from the connection.
   127	func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
   128		if !c.ok() {
   129			return 0, 0, 0, nil, syscall.EINVAL
   130		}
   131		n, oobn, flags, addr, err = c.readMsg(b, oob)
   132		if err != nil {
   133			err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
   134		}
   135		return
   136	}
   137	
   138	// WriteToUnix writes a packet to addr via c, copying the payload from b.
   139	//
   140	// WriteToUnix can be made to time out and return an error with
   141	// Timeout() == true after a fixed time limit; see SetDeadline and
   142	// SetWriteDeadline. On packet-oriented connections, write timeouts
   143	// are rare.
   144	func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
   145		if !c.ok() {
   146			return 0, syscall.EINVAL
   147		}
   148		n, err := c.writeTo(b, addr)
   149		if err != nil {
   150			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   151		}
   152		return n, err
   153	}
   154	
   155	// WriteTo implements the PacketConn WriteTo method.
   156	func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
   157		if !c.ok() {
   158			return 0, syscall.EINVAL
   159		}
   160		a, ok := addr.(*UnixAddr)
   161		if !ok {
   162			return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
   163		}
   164		n, err := c.writeTo(b, a)
   165		if err != nil {
   166			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: a.opAddr(), Err: err}
   167		}
   168		return n, err
   169	}
   170	
   171	// WriteMsgUnix writes a packet to addr via c, copying the payload
   172	// from b and the associated out-of-band data from oob. It returns
   173	// the number of payload and out-of-band bytes written.
   174	//
   175	// Note that if len(b) == 0 and len(oob) > 0, this function will still
   176	// write 1 byte to the connection.
   177	func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
   178		if !c.ok() {
   179			return 0, 0, syscall.EINVAL
   180		}
   181		n, oobn, err = c.writeMsg(b, oob, addr)
   182		if err != nil {
   183			err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
   184		}
   185		return
   186	}
   187	
   188	func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{conn{fd}} }
   189	
   190	// DialUnix connects to the remote address raddr on the network net,
   191	// which must be "unix", "unixgram" or "unixpacket".  If laddr is not
   192	// nil, it is used as the local address for the connection.
   193	func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
   194		switch net {
   195		case "unix", "unixgram", "unixpacket":
   196		default:
   197			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
   198		}
   199		c, err := dialUnix(context.Background(), net, laddr, raddr)
   200		if err != nil {
   201			return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
   202		}
   203		return c, nil
   204	}
   205	
   206	// UnixListener is a Unix domain socket listener. Clients should
   207	// typically use variables of type Listener instead of assuming Unix
   208	// domain sockets.
   209	type UnixListener struct {
   210		fd         *netFD
   211		path       string
   212		unlink     bool
   213		unlinkOnce sync.Once
   214	}
   215	
   216	func (ln *UnixListener) ok() bool { return ln != nil && ln.fd != nil }
   217	
   218	// AcceptUnix accepts the next incoming call and returns the new
   219	// connection.
   220	func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
   221		if !l.ok() {
   222			return nil, syscall.EINVAL
   223		}
   224		c, err := l.accept()
   225		if err != nil {
   226			return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   227		}
   228		return c, nil
   229	}
   230	
   231	// Accept implements the Accept method in the Listener interface.
   232	// Returned connections will be of type *UnixConn.
   233	func (l *UnixListener) Accept() (Conn, error) {
   234		if !l.ok() {
   235			return nil, syscall.EINVAL
   236		}
   237		c, err := l.accept()
   238		if err != nil {
   239			return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   240		}
   241		return c, nil
   242	}
   243	
   244	// Close stops listening on the Unix address. Already accepted
   245	// connections are not closed.
   246	func (l *UnixListener) Close() error {
   247		if !l.ok() {
   248			return syscall.EINVAL
   249		}
   250		if err := l.close(); err != nil {
   251			return &OpError{Op: "close", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   252		}
   253		return nil
   254	}
   255	
   256	// Addr returns the listener's network address.
   257	// The Addr returned is shared by all invocations of Addr, so
   258	// do not modify it.
   259	func (l *UnixListener) Addr() Addr { return l.fd.laddr }
   260	
   261	// SetDeadline sets the deadline associated with the listener.
   262	// A zero time value disables the deadline.
   263	func (l *UnixListener) SetDeadline(t time.Time) error {
   264		if !l.ok() {
   265			return syscall.EINVAL
   266		}
   267		if err := l.fd.setDeadline(t); err != nil {
   268			return &OpError{Op: "set", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   269		}
   270		return nil
   271	}
   272	
   273	// File returns a copy of the underlying os.File, set to blocking
   274	// mode. It is the caller's responsibility to close f when finished.
   275	// Closing l does not affect f, and closing f does not affect l.
   276	//
   277	// The returned os.File's file descriptor is different from the
   278	// connection's. Attempting to change properties of the original
   279	// using this duplicate may or may not have the desired effect.
   280	func (l *UnixListener) File() (f *os.File, err error) {
   281		if !l.ok() {
   282			return nil, syscall.EINVAL
   283		}
   284		f, err = l.file()
   285		if err != nil {
   286			err = &OpError{Op: "file", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
   287		}
   288		return
   289	}
   290	
   291	// ListenUnix announces on the Unix domain socket laddr and returns a
   292	// Unix listener. The network net must be "unix" or "unixpacket".
   293	func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
   294		switch net {
   295		case "unix", "unixpacket":
   296		default:
   297			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
   298		}
   299		if laddr == nil {
   300			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: errMissingAddress}
   301		}
   302		ln, err := listenUnix(context.Background(), net, laddr)
   303		if err != nil {
   304			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: err}
   305		}
   306		return ln, nil
   307	}
   308	
   309	// ListenUnixgram listens for incoming Unix datagram packets addressed
   310	// to the local address laddr. The network net must be "unixgram".
   311	// The returned connection's ReadFrom and WriteTo methods can be used
   312	// to receive and send packets with per-packet addressing.
   313	func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
   314		switch net {
   315		case "unixgram":
   316		default:
   317			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
   318		}
   319		if laddr == nil {
   320			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: errMissingAddress}
   321		}
   322		c, err := listenUnixgram(context.Background(), net, laddr)
   323		if err != nil {
   324			return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: err}
   325		}
   326		return c, nil
   327	}
   328	

View as plain text