...

Source file src/net/unixsock.go

Documentation: net

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

View as plain text