blob: 2521969eb0981b6d1170df6f7caca00d6eef2a24 [file] [log] [blame]
Russ Cox35ace1d2009-11-01 11:15:34 -08001// 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// Unix domain sockets
6
7package net
8
9import (
Robert Griesemera3d10452009-12-15 15:35:38 -080010 "os"
11 "syscall"
Russ Cox35ace1d2009-11-01 11:15:34 -080012)
13
Russ Coxc83b8382009-11-02 18:37:30 -080014func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err os.Error) {
Robert Griesemera3d10452009-12-15 15:35:38 -080015 var proto int
Russ Cox35ace1d2009-11-01 11:15:34 -080016 switch net {
17 default:
Robert Griesemer40621d52009-11-09 12:07:39 -080018 return nil, UnknownNetworkError(net)
Russ Cox35ace1d2009-11-01 11:15:34 -080019 case "unix":
Robert Griesemer40621d52009-11-09 12:07:39 -080020 proto = syscall.SOCK_STREAM
Russ Coxc83b8382009-11-02 18:37:30 -080021 case "unixgram":
Robert Griesemer40621d52009-11-09 12:07:39 -080022 proto = syscall.SOCK_DGRAM
Russ Cox35ace1d2009-11-01 11:15:34 -080023 }
24
Robert Griesemera3d10452009-12-15 15:35:38 -080025 var la, ra syscall.Sockaddr
Russ Cox35ace1d2009-11-01 11:15:34 -080026 switch mode {
27 default:
Russ Cox00f9f0c2010-03-30 10:34:57 -070028 panic("unixSocket mode " + mode)
Russ Cox35ace1d2009-11-01 11:15:34 -080029
30 case "dial":
Russ Coxc83b8382009-11-02 18:37:30 -080031 if laddr != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080032 la = &syscall.SockaddrUnix{Name: laddr.Name}
Russ Cox35ace1d2009-11-01 11:15:34 -080033 }
Russ Coxc83b8382009-11-02 18:37:30 -080034 if raddr != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080035 ra = &syscall.SockaddrUnix{Name: raddr.Name}
Russ Coxc83b8382009-11-02 18:37:30 -080036 } else if proto != syscall.SOCK_DGRAM || laddr == nil {
Russ Cox47a05332010-04-26 22:15:25 -070037 return nil, &OpError{Op: mode, Net: net, Error: errMissingAddress}
Russ Cox35ace1d2009-11-01 11:15:34 -080038 }
Russ Cox35ace1d2009-11-01 11:15:34 -080039
40 case "listen":
Russ Coxc83b8382009-11-02 18:37:30 -080041 if laddr == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080042 return nil, &OpError{mode, net, nil, errMissingAddress}
Russ Cox35ace1d2009-11-01 11:15:34 -080043 }
Robert Griesemera3d10452009-12-15 15:35:38 -080044 la = &syscall.SockaddrUnix{Name: laddr.Name}
Russ Coxc83b8382009-11-02 18:37:30 -080045 if raddr != nil {
Russ Cox47a05332010-04-26 22:15:25 -070046 return nil, &OpError{Op: mode, Net: net, Addr: raddr, Error: &AddrError{Error: "unexpected remote address", Addr: raddr.String()}}
Russ Cox35ace1d2009-11-01 11:15:34 -080047 }
48 }
49
Robert Griesemera3d10452009-12-15 15:35:38 -080050 f := sockaddrToUnix
Russ Coxc83b8382009-11-02 18:37:30 -080051 if proto != syscall.SOCK_STREAM {
Robert Griesemer40621d52009-11-09 12:07:39 -080052 f = sockaddrToUnixgram
Russ Coxc83b8382009-11-02 18:37:30 -080053 }
Russ Cox47a05332010-04-26 22:15:25 -070054 fd, oserr := socket(net, syscall.AF_UNIX, proto, 0, la, ra, f)
55 if oserr != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080056 goto Error
Russ Cox35ace1d2009-11-01 11:15:34 -080057 }
Robert Griesemera3d10452009-12-15 15:35:38 -080058 return fd, nil
Russ Cox35ace1d2009-11-01 11:15:34 -080059
60Error:
Robert Griesemera3d10452009-12-15 15:35:38 -080061 addr := raddr
Russ Cox35ace1d2009-11-01 11:15:34 -080062 if mode == "listen" {
Robert Griesemer40621d52009-11-09 12:07:39 -080063 addr = laddr
Russ Cox35ace1d2009-11-01 11:15:34 -080064 }
Russ Cox47a05332010-04-26 22:15:25 -070065 return nil, &OpError{Op: mode, Net: net, Addr: addr, Error: oserr}
Russ Cox35ace1d2009-11-01 11:15:34 -080066}
67
Russ Coxc83b8382009-11-02 18:37:30 -080068// UnixAddr represents the address of a Unix domain socket end point.
69type UnixAddr struct {
Robert Griesemera3d10452009-12-15 15:35:38 -080070 Name string
71 Datagram bool
Russ Coxc83b8382009-11-02 18:37:30 -080072}
73
74func sockaddrToUnix(sa syscall.Sockaddr) Addr {
75 if s, ok := sa.(*syscall.SockaddrUnix); ok {
Robert Griesemer40621d52009-11-09 12:07:39 -080076 return &UnixAddr{s.Name, false}
Russ Coxc83b8382009-11-02 18:37:30 -080077 }
Robert Griesemera3d10452009-12-15 15:35:38 -080078 return nil
Russ Coxc83b8382009-11-02 18:37:30 -080079}
80
81func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
82 if s, ok := sa.(*syscall.SockaddrUnix); ok {
Robert Griesemer40621d52009-11-09 12:07:39 -080083 return &UnixAddr{s.Name, true}
Russ Coxc83b8382009-11-02 18:37:30 -080084 }
Robert Griesemera3d10452009-12-15 15:35:38 -080085 return nil
Russ Coxc83b8382009-11-02 18:37:30 -080086}
87
88// Network returns the address's network name, "unix" or "unixgram".
89func (a *UnixAddr) Network() string {
90 if a == nil || !a.Datagram {
Robert Griesemer40621d52009-11-09 12:07:39 -080091 return "unix"
Russ Coxc83b8382009-11-02 18:37:30 -080092 }
Robert Griesemera3d10452009-12-15 15:35:38 -080093 return "unixgram"
Russ Coxc83b8382009-11-02 18:37:30 -080094}
95
96func (a *UnixAddr) String() string {
97 if a == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080098 return "<nil>"
Russ Coxc83b8382009-11-02 18:37:30 -080099 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800100 return a.Name
Russ Coxc83b8382009-11-02 18:37:30 -0800101}
102
103func (a *UnixAddr) toAddr() Addr {
Robert Griesemera3d10452009-12-15 15:35:38 -0800104 if a == nil { // nil *UnixAddr
105 return nil // nil interface
Russ Coxc83b8382009-11-02 18:37:30 -0800106 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800107 return a
Russ Coxc83b8382009-11-02 18:37:30 -0800108}
109
110// ResolveUnixAddr parses addr as a Unix domain socket address.
111// The string net gives the network name, "unix" or "unixgram".
112func ResolveUnixAddr(net, addr string) (*UnixAddr, os.Error) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800113 var datagram bool
Russ Coxc83b8382009-11-02 18:37:30 -0800114 switch net {
115 case "unix":
116 case "unixgram":
Robert Griesemer40621d52009-11-09 12:07:39 -0800117 datagram = true
Russ Coxc83b8382009-11-02 18:37:30 -0800118 default:
Robert Griesemer40621d52009-11-09 12:07:39 -0800119 return nil, UnknownNetworkError(net)
Russ Coxc83b8382009-11-02 18:37:30 -0800120 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800121 return &UnixAddr{addr, datagram}, nil
Russ Coxc83b8382009-11-02 18:37:30 -0800122}
123
124// UnixConn is an implementation of the Conn interface
Russ Cox35ace1d2009-11-01 11:15:34 -0800125// for connections to Unix domain sockets.
Russ Coxc83b8382009-11-02 18:37:30 -0800126type UnixConn struct {
Robert Griesemera3d10452009-12-15 15:35:38 -0800127 fd *netFD
Russ Cox35ace1d2009-11-01 11:15:34 -0800128}
129
Robert Griesemera3d10452009-12-15 15:35:38 -0800130func newUnixConn(fd *netFD) *UnixConn { return &UnixConn{fd} }
Russ Cox35ace1d2009-11-01 11:15:34 -0800131
Robert Griesemera3d10452009-12-15 15:35:38 -0800132func (c *UnixConn) ok() bool { return c != nil && c.fd != nil }
Russ Coxc83b8382009-11-02 18:37:30 -0800133
134// Implementation of the Conn interface - see Conn for documentation.
135
Russ Cox47a05332010-04-26 22:15:25 -0700136// Read implements the net.Conn Read method.
Russ Coxc83b8382009-11-02 18:37:30 -0800137func (c *UnixConn) Read(b []byte) (n int, err os.Error) {
138 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800139 return 0, os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800140 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800141 return c.fd.Read(b)
Russ Coxc83b8382009-11-02 18:37:30 -0800142}
143
Russ Cox47a05332010-04-26 22:15:25 -0700144// Write implements the net.Conn Write method.
Russ Coxc83b8382009-11-02 18:37:30 -0800145func (c *UnixConn) Write(b []byte) (n int, err os.Error) {
146 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800147 return 0, os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800148 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800149 return c.fd.Write(b)
Russ Coxc83b8382009-11-02 18:37:30 -0800150}
151
152// Close closes the Unix domain connection.
153func (c *UnixConn) Close() os.Error {
154 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800155 return os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800156 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800157 err := c.fd.Close()
158 c.fd = nil
159 return err
Russ Coxc83b8382009-11-02 18:37:30 -0800160}
161
162// LocalAddr returns the local network address, a *UnixAddr.
163// Unlike in other protocols, LocalAddr is usually nil for dialed connections.
164func (c *UnixConn) LocalAddr() Addr {
165 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800166 return nil
Russ Coxc83b8382009-11-02 18:37:30 -0800167 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800168 return c.fd.laddr
Russ Coxc83b8382009-11-02 18:37:30 -0800169}
170
171// RemoteAddr returns the remote network address, a *UnixAddr.
172// Unlike in other protocols, RemoteAddr is usually nil for connections
173// accepted by a listener.
174func (c *UnixConn) RemoteAddr() Addr {
175 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800176 return nil
Russ Coxc83b8382009-11-02 18:37:30 -0800177 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800178 return c.fd.raddr
Russ Coxc83b8382009-11-02 18:37:30 -0800179}
180
Russ Cox47a05332010-04-26 22:15:25 -0700181// SetTimeout implements the net.Conn SetTimeout method.
Russ Coxc83b8382009-11-02 18:37:30 -0800182func (c *UnixConn) SetTimeout(nsec int64) os.Error {
183 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800184 return os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800185 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800186 return setTimeout(c.fd, nsec)
Russ Coxc83b8382009-11-02 18:37:30 -0800187}
188
Russ Cox47a05332010-04-26 22:15:25 -0700189// SetReadTimeout implements the net.Conn SetReadTimeout method.
Russ Coxc83b8382009-11-02 18:37:30 -0800190func (c *UnixConn) SetReadTimeout(nsec int64) os.Error {
191 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800192 return os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800193 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800194 return setReadTimeout(c.fd, nsec)
Russ Coxc83b8382009-11-02 18:37:30 -0800195}
196
Russ Cox47a05332010-04-26 22:15:25 -0700197// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
Russ Coxc83b8382009-11-02 18:37:30 -0800198func (c *UnixConn) SetWriteTimeout(nsec int64) os.Error {
199 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800200 return os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800201 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800202 return setWriteTimeout(c.fd, nsec)
Russ Coxc83b8382009-11-02 18:37:30 -0800203}
204
205// SetReadBuffer sets the size of the operating system's
206// receive buffer associated with the connection.
207func (c *UnixConn) SetReadBuffer(bytes int) os.Error {
208 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800209 return os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800210 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800211 return setReadBuffer(c.fd, bytes)
Russ Coxc83b8382009-11-02 18:37:30 -0800212}
213
214// SetWriteBuffer sets the size of the operating system's
215// transmit buffer associated with the connection.
216func (c *UnixConn) SetWriteBuffer(bytes int) os.Error {
217 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800218 return os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800219 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800220 return setWriteBuffer(c.fd, bytes)
Russ Coxc83b8382009-11-02 18:37:30 -0800221}
222
223// ReadFromUnix reads a packet from c, copying the payload into b.
224// It returns the number of bytes copied into b and the return address
225// that was on the packet.
226//
Russ Cox47a05332010-04-26 22:15:25 -0700227// ReadFromUnix can be made to time out and return
228// an error with Timeout() == true after a fixed time limit;
229// see SetTimeout and SetReadTimeout.
Russ Coxc83b8382009-11-02 18:37:30 -0800230func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err os.Error) {
231 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800232 return 0, nil, os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800233 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800234 n, sa, err := c.fd.ReadFrom(b)
Russ Coxc83b8382009-11-02 18:37:30 -0800235 switch sa := sa.(type) {
236 case *syscall.SockaddrUnix:
Robert Griesemer40621d52009-11-09 12:07:39 -0800237 addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM}
Russ Coxc83b8382009-11-02 18:37:30 -0800238 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800239 return
Russ Coxc83b8382009-11-02 18:37:30 -0800240}
241
Russ Cox47a05332010-04-26 22:15:25 -0700242// ReadFrom implements the net.PacketConn ReadFrom method.
Russ Coxc83b8382009-11-02 18:37:30 -0800243func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
244 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800245 return 0, nil, os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800246 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800247 n, uaddr, err := c.ReadFromUnix(b)
248 return n, uaddr.toAddr(), err
Russ Coxc83b8382009-11-02 18:37:30 -0800249}
250
251// WriteToUnix writes a packet to addr via c, copying the payload from b.
252//
Russ Cox47a05332010-04-26 22:15:25 -0700253// WriteToUnix can be made to time out and return
254// an error with Timeout() == true after a fixed time limit;
255// see SetTimeout and SetWriteTimeout.
256// On packet-oriented connections, write timeouts are rare.
Russ Coxc83b8382009-11-02 18:37:30 -0800257func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err os.Error) {
258 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800259 return 0, os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800260 }
261 if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) {
Robert Griesemer40621d52009-11-09 12:07:39 -0800262 return 0, os.EAFNOSUPPORT
Russ Coxc83b8382009-11-02 18:37:30 -0800263 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800264 sa := &syscall.SockaddrUnix{Name: addr.Name}
265 return c.fd.WriteTo(b, sa)
Russ Coxc83b8382009-11-02 18:37:30 -0800266}
267
Russ Cox47a05332010-04-26 22:15:25 -0700268// WriteTo implements the net.PacketConn WriteTo method.
Russ Coxc83b8382009-11-02 18:37:30 -0800269func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
270 if !c.ok() {
Robert Griesemer40621d52009-11-09 12:07:39 -0800271 return 0, os.EINVAL
Russ Coxc83b8382009-11-02 18:37:30 -0800272 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800273 a, ok := addr.(*UnixAddr)
Russ Coxc83b8382009-11-02 18:37:30 -0800274 if !ok {
Robert Griesemer40621d52009-11-09 12:07:39 -0800275 return 0, &OpError{"writeto", "unix", addr, os.EINVAL}
Russ Coxc83b8382009-11-02 18:37:30 -0800276 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800277 return c.WriteToUnix(b, a)
Russ Coxc83b8382009-11-02 18:37:30 -0800278}
279
Albert Strasheimcf6c2122010-12-07 13:40:14 -0500280func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err os.Error) {
281 if !c.ok() {
282 return 0, 0, 0, nil, os.EINVAL
283 }
284 n, oobn, flags, sa, err := c.fd.ReadMsg(b, oob)
285 switch sa := sa.(type) {
286 case *syscall.SockaddrUnix:
287 addr = &UnixAddr{sa.Name, c.fd.proto == syscall.SOCK_DGRAM}
288 }
289 return
290}
291
292func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err os.Error) {
293 if !c.ok() {
294 return 0, 0, os.EINVAL
295 }
296 if addr != nil {
297 if addr.Datagram != (c.fd.proto == syscall.SOCK_DGRAM) {
298 return 0, 0, os.EAFNOSUPPORT
299 }
300 sa := &syscall.SockaddrUnix{Name: addr.Name}
301 return c.fd.WriteMsg(b, oob, sa)
302 }
303 return c.fd.WriteMsg(b, oob, nil)
304}
305
Keith Raricka144e3e2010-11-05 14:02:03 -0400306// File returns a copy of the underlying os.File, set to blocking mode.
307// It is the caller's responsibility to close f when finished.
308// Closing c does not affect f, and closing f does not affect c.
309func (c *UnixConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
310
Stephen Weinbergb86c0b02010-02-25 14:49:14 -0800311// DialUnix connects to the remote address raddr on the network net,
Conrad Meyer5789c862010-05-05 09:55:11 -0700312// which must be "unix" or "unixgram". If laddr is not nil, it is used
Russ Coxc83b8382009-11-02 18:37:30 -0800313// as the local address for the connection.
314func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err os.Error) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800315 fd, e := unixSocket(net, laddr, raddr, "dial")
Russ Cox35ace1d2009-11-01 11:15:34 -0800316 if e != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800317 return nil, e
Russ Cox35ace1d2009-11-01 11:15:34 -0800318 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800319 return newUnixConn(fd), nil
Russ Cox35ace1d2009-11-01 11:15:34 -0800320}
321
Russ Coxc83b8382009-11-02 18:37:30 -0800322// UnixListener is a Unix domain socket listener.
Russ Cox35ace1d2009-11-01 11:15:34 -0800323// Clients should typically use variables of type Listener
324// instead of assuming Unix domain sockets.
Russ Coxc83b8382009-11-02 18:37:30 -0800325type UnixListener struct {
Robert Griesemera3d10452009-12-15 15:35:38 -0800326 fd *netFD
327 path string
Russ Cox35ace1d2009-11-01 11:15:34 -0800328}
329
330// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
Russ Coxc83b8382009-11-02 18:37:30 -0800331// Net must be "unix" (stream sockets).
332func ListenUnix(net string, laddr *UnixAddr) (l *UnixListener, err os.Error) {
333 if net != "unix" && net != "unixgram" {
Robert Griesemer40621d52009-11-09 12:07:39 -0800334 return nil, UnknownNetworkError(net)
Russ Coxc83b8382009-11-02 18:37:30 -0800335 }
336 if laddr != nil {
Robert Griesemera3d10452009-12-15 15:35:38 -0800337 laddr = &UnixAddr{laddr.Name, net == "unixgram"} // make our own copy
Russ Coxc83b8382009-11-02 18:37:30 -0800338 }
Russ Cox47a05332010-04-26 22:15:25 -0700339 fd, err := unixSocket(net, laddr, nil, "listen")
340 if err != nil {
341 return nil, err
Russ Cox35ace1d2009-11-01 11:15:34 -0800342 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800343 e1 := syscall.Listen(fd.sysfd, 8) // listenBacklog());
Russ Cox35ace1d2009-11-01 11:15:34 -0800344 if e1 != 0 {
Alex Brainman3a052b52011-01-12 15:55:17 +1100345 closesocket(fd.sysfd)
Russ Cox47a05332010-04-26 22:15:25 -0700346 return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Error: os.Errno(e1)}
Russ Cox35ace1d2009-11-01 11:15:34 -0800347 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800348 return &UnixListener{fd, laddr.Name}, nil
Russ Cox35ace1d2009-11-01 11:15:34 -0800349}
350
351// AcceptUnix accepts the next incoming call and returns the new connection
352// and the remote address.
Russ Coxc83b8382009-11-02 18:37:30 -0800353func (l *UnixListener) AcceptUnix() (c *UnixConn, err os.Error) {
Devon H. O'Delleb163462009-12-01 23:28:57 -0800354 if l == nil || l.fd == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800355 return nil, os.EINVAL
Russ Cox35ace1d2009-11-01 11:15:34 -0800356 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800357 fd, e := l.fd.accept(sockaddrToUnix)
Russ Cox35ace1d2009-11-01 11:15:34 -0800358 if e != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800359 return nil, e
Russ Cox35ace1d2009-11-01 11:15:34 -0800360 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800361 c = newUnixConn(fd)
362 return c, nil
Russ Cox35ace1d2009-11-01 11:15:34 -0800363}
364
365// Accept implements the Accept method in the Listener interface;
366// it waits for the next call and returns a generic Conn.
Russ Coxc83b8382009-11-02 18:37:30 -0800367func (l *UnixListener) Accept() (c Conn, err os.Error) {
Robert Griesemera3d10452009-12-15 15:35:38 -0800368 c1, err := l.AcceptUnix()
Russ Coxc83b8382009-11-02 18:37:30 -0800369 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800370 return nil, err
Russ Coxc83b8382009-11-02 18:37:30 -0800371 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800372 return c1, nil
Russ Cox35ace1d2009-11-01 11:15:34 -0800373}
374
Russ Cox35ace1d2009-11-01 11:15:34 -0800375// Close stops listening on the Unix address.
376// Already accepted connections are not closed.
Russ Coxc83b8382009-11-02 18:37:30 -0800377func (l *UnixListener) Close() os.Error {
Russ Cox35ace1d2009-11-01 11:15:34 -0800378 if l == nil || l.fd == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800379 return os.EINVAL
Russ Cox35ace1d2009-11-01 11:15:34 -0800380 }
381
382 // The operating system doesn't clean up
383 // the file that announcing created, so
384 // we have to clean it up ourselves.
385 // There's a race here--we can't know for
386 // sure whether someone else has come along
387 // and replaced our socket name already--
388 // but this sequence (remove then close)
389 // is at least compatible with the auto-remove
390 // sequence in ListenUnix. It's only non-Go
391 // programs that can mess us up.
Russ Coxc83b8382009-11-02 18:37:30 -0800392 if l.path[0] != '@' {
Robert Griesemer40621d52009-11-09 12:07:39 -0800393 syscall.Unlink(l.path)
Russ Cox35ace1d2009-11-01 11:15:34 -0800394 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800395 err := l.fd.Close()
396 l.fd = nil
397 return err
Russ Cox35ace1d2009-11-01 11:15:34 -0800398}
399
400// Addr returns the listener's network address.
Robert Griesemera3d10452009-12-15 15:35:38 -0800401func (l *UnixListener) Addr() Addr { return l.fd.laddr }
Russ Coxc83b8382009-11-02 18:37:30 -0800402
Keith Raricka144e3e2010-11-05 14:02:03 -0400403// File returns a copy of the underlying os.File, set to blocking mode.
404// It is the caller's responsibility to close f when finished.
405// Closing c does not affect f, and closing f does not affect c.
406func (l *UnixListener) File() (f *os.File, err os.Error) { return l.fd.dup() }
407
Russ Coxc83b8382009-11-02 18:37:30 -0800408// ListenUnixgram listens for incoming Unix datagram packets addressed to the
409// local address laddr. The returned connection c's ReadFrom
410// and WriteTo methods can be used to receive and send UDP
411// packets with per-packet addressing. The network net must be "unixgram".
412func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err os.Error) {
413 switch net {
414 case "unixgram":
415 default:
Robert Griesemer40621d52009-11-09 12:07:39 -0800416 return nil, UnknownNetworkError(net)
Russ Coxc83b8382009-11-02 18:37:30 -0800417 }
418 if laddr == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800419 return nil, &OpError{"listen", "unixgram", nil, errMissingAddress}
Russ Coxc83b8382009-11-02 18:37:30 -0800420 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800421 fd, e := unixSocket(net, laddr, nil, "listen")
Russ Coxc83b8382009-11-02 18:37:30 -0800422 if e != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -0800423 return nil, e
Russ Coxc83b8382009-11-02 18:37:30 -0800424 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800425 return newUDPConn(fd), nil
Russ Cox35ace1d2009-11-01 11:15:34 -0800426}