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.
5 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
16 func unixSocket(net
string, laddr
, raddr sockaddr
, mode
string, deadline time
.Time
) (*netFD
, error
) {
20 sotype
= syscall
.SOCK_STREAM
22 sotype
= syscall
.SOCK_DGRAM
24 sotype
= syscall
.SOCK_SEQPACKET
26 return nil, UnknownNetworkError(net
)
31 if laddr
!= nil && laddr
.isWildcard() {
34 if raddr
!= nil && raddr
.isWildcard() {
37 if raddr
== nil && (sotype
!= syscall
.SOCK_DGRAM || laddr
== nil) {
38 return nil, errMissingAddress
42 return nil, errors
.New("unknown mode: " + mode
)
45 fd
, err
:= socket(net
, syscall
.AF_UNIX
, sotype
, 0, false, laddr
, raddr
, deadline
)
52 func sockaddrToUnix(sa syscall
.Sockaddr
) Addr
{
53 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
54 return &UnixAddr
{Name
: s
.Name
, Net
: "unix"}
59 func sockaddrToUnixgram(sa syscall
.Sockaddr
) Addr
{
60 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
61 return &UnixAddr
{Name
: s
.Name
, Net
: "unixgram"}
66 func sockaddrToUnixpacket(sa syscall
.Sockaddr
) Addr
{
67 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
68 return &UnixAddr
{Name
: s
.Name
, Net
: "unixpacket"}
73 func sotypeToNet(sotype
int) string {
75 case syscall
.SOCK_STREAM
:
77 case syscall
.SOCK_DGRAM
:
79 case syscall
.SOCK_SEQPACKET
:
82 panic("sotypeToNet unknown socket type")
86 func (a
*UnixAddr
) family() int {
87 return syscall
.AF_UNIX
90 func (a
*UnixAddr
) isWildcard() bool {
91 return a
== nil || a
.Name
== ""
94 func (a
*UnixAddr
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
98 return &syscall
.SockaddrUnix
{Name
: a
.Name
}, nil
101 // UnixConn is an implementation of the Conn interface for connections
102 // to Unix domain sockets.
103 type UnixConn
struct {
107 func newUnixConn(fd
*netFD
) *UnixConn
{ return &UnixConn
{conn
{fd
}} }
109 // ReadFromUnix reads a packet from c, copying the payload into b. It
110 // returns the number of bytes copied into b and the source address of
113 // ReadFromUnix can be made to time out and return an error with
114 // Timeout() == true after a fixed time limit; see SetDeadline and
116 func (c
*UnixConn
) ReadFromUnix(b
[]byte) (n
int, addr
*UnixAddr
, err error
) {
118 return 0, nil, syscall
.EINVAL
120 n
, sa
, err
:= c
.fd
.readFrom(b
)
121 switch sa
:= sa
.(type) {
122 case *syscall
.SockaddrUnix
:
124 addr
= &UnixAddr
{Name
: sa
.Name
, Net
: sotypeToNet(c
.fd
.sotype
)}
130 // ReadFrom implements the PacketConn ReadFrom method.
131 func (c
*UnixConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
133 return 0, nil, syscall
.EINVAL
135 n
, addr
, err
:= c
.ReadFromUnix(b
)
136 return n
, addr
.toAddr(), err
139 // ReadMsgUnix reads a packet from c, copying the payload into b and
140 // the associated out-of-band data into oob. It returns the number of
141 // bytes copied into b, the number of bytes copied into oob, the flags
142 // that were set on the packet, and the source address of the packet.
143 func (c
*UnixConn
) ReadMsgUnix(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UnixAddr
, err error
) {
145 return 0, 0, 0, nil, syscall
.EINVAL
147 n
, oobn
, flags
, sa
, err
:= c
.fd
.readMsg(b
, oob
)
148 switch sa
:= sa
.(type) {
149 case *syscall
.SockaddrUnix
:
151 addr
= &UnixAddr
{Name
: sa
.Name
, Net
: sotypeToNet(c
.fd
.sotype
)}
157 // WriteToUnix writes a packet to addr via c, copying the payload from b.
159 // WriteToUnix can be made to time out and return an error with
160 // Timeout() == true after a fixed time limit; see SetDeadline and
161 // SetWriteDeadline. On packet-oriented connections, write timeouts
163 func (c
*UnixConn
) WriteToUnix(b
[]byte, addr
*UnixAddr
) (n
int, err error
) {
165 return 0, syscall
.EINVAL
167 if c
.fd
.isConnected
{
168 return 0, &OpError
{Op
: "write", Net
: c
.fd
.net
, Addr
: addr
, Err
: ErrWriteToConnected
}
171 return 0, &OpError
{Op
: "write", Net
: c
.fd
.net
, Addr
: nil, Err
: errMissingAddress
}
173 if addr
.Net
!= sotypeToNet(c
.fd
.sotype
) {
174 return 0, syscall
.EAFNOSUPPORT
176 sa
:= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
177 return c
.fd
.writeTo(b
, sa
)
180 // WriteTo implements the PacketConn WriteTo method.
181 func (c
*UnixConn
) WriteTo(b
[]byte, addr Addr
) (n
int, err error
) {
183 return 0, syscall
.EINVAL
185 a
, ok
:= addr
.(*UnixAddr
)
187 return 0, &OpError
{"write", c
.fd
.net
, addr
, syscall
.EINVAL
}
189 return c
.WriteToUnix(b
, a
)
192 // WriteMsgUnix writes a packet to addr via c, copying the payload
193 // from b and the associated out-of-band data from oob. It returns
194 // the number of payload and out-of-band bytes written.
195 func (c
*UnixConn
) WriteMsgUnix(b
, oob
[]byte, addr
*UnixAddr
) (n
, oobn
int, err error
) {
197 return 0, 0, syscall
.EINVAL
199 if c
.fd
.sotype
== syscall
.SOCK_DGRAM
&& c
.fd
.isConnected
{
200 return 0, 0, &OpError
{Op
: "write", Net
: c
.fd
.net
, Addr
: addr
, Err
: ErrWriteToConnected
}
203 if addr
.Net
!= sotypeToNet(c
.fd
.sotype
) {
204 return 0, 0, syscall
.EAFNOSUPPORT
206 sa
:= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
207 return c
.fd
.writeMsg(b
, oob
, sa
)
209 return c
.fd
.writeMsg(b
, oob
, nil)
212 // CloseRead shuts down the reading side of the Unix domain connection.
213 // Most callers should just use Close.
214 func (c
*UnixConn
) CloseRead() error
{
216 return syscall
.EINVAL
218 return c
.fd
.closeRead()
221 // CloseWrite shuts down the writing side of the Unix domain connection.
222 // Most callers should just use Close.
223 func (c
*UnixConn
) CloseWrite() error
{
225 return syscall
.EINVAL
227 return c
.fd
.closeWrite()
230 // DialUnix connects to the remote address raddr on the network net,
231 // which must be "unix", "unixgram" or "unixpacket". If laddr is not
232 // nil, it is used as the local address for the connection.
233 func DialUnix(net
string, laddr
, raddr
*UnixAddr
) (*UnixConn
, error
) {
235 case "unix", "unixgram", "unixpacket":
237 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: raddr
, Err
: UnknownNetworkError(net
)}
239 return dialUnix(net
, laddr
, raddr
, noDeadline
)
242 func dialUnix(net
string, laddr
, raddr
*UnixAddr
, deadline time
.Time
) (*UnixConn
, error
) {
243 fd
, err
:= unixSocket(net
, laddr
, raddr
, "dial", deadline
)
245 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: raddr
, Err
: err
}
247 return newUnixConn(fd
), nil
250 // UnixListener is a Unix domain socket listener. Clients should
251 // typically use variables of type Listener instead of assuming Unix
253 type UnixListener
struct {
258 // ListenUnix announces on the Unix domain socket laddr and returns a
259 // Unix listener. The network net must be "unix" or "unixpacket".
260 func ListenUnix(net
string, laddr
*UnixAddr
) (*UnixListener
, error
) {
262 case "unix", "unixpacket":
264 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: UnknownNetworkError(net
)}
267 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: nil, Err
: errMissingAddress
}
269 fd
, err
:= unixSocket(net
, laddr
, nil, "listen", noDeadline
)
271 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: err
}
273 return &UnixListener
{fd
, fd
.laddr
.String()}, nil
276 // AcceptUnix accepts the next incoming call and returns the new
278 func (l
*UnixListener
) AcceptUnix() (*UnixConn
, error
) {
279 if l
== nil || l
.fd
== nil {
280 return nil, syscall
.EINVAL
282 fd
, err
:= l
.fd
.accept()
290 // Accept implements the Accept method in the Listener interface; it
291 // waits for the next call and returns a generic Conn.
292 func (l
*UnixListener
) Accept() (c Conn
, err error
) {
293 c1
, err
:= l
.AcceptUnix()
300 // Close stops listening on the Unix address. Already accepted
301 // connections are not closed.
302 func (l
*UnixListener
) Close() error
{
303 if l
== nil || l
.fd
== nil {
304 return syscall
.EINVAL
307 // The operating system doesn't clean up
308 // the file that announcing created, so
309 // we have to clean it up ourselves.
310 // There's a race here--we can't know for
311 // sure whether someone else has come along
312 // and replaced our socket name already--
313 // but this sequence (remove then close)
314 // is at least compatible with the auto-remove
315 // sequence in ListenUnix. It's only non-Go
316 // programs that can mess us up.
317 if l
.path
[0] != '@' {
318 syscall
.Unlink(l
.path
)
323 // Addr returns the listener's network address.
324 func (l
*UnixListener
) Addr() Addr
{ return l
.fd
.laddr
}
326 // SetDeadline sets the deadline associated with the listener.
327 // A zero time value disables the deadline.
328 func (l
*UnixListener
) SetDeadline(t time
.Time
) (err error
) {
329 if l
== nil || l
.fd
== nil {
330 return syscall
.EINVAL
332 return l
.fd
.setDeadline(t
)
335 // File returns a copy of the underlying os.File, set to blocking
336 // mode. It is the caller's responsibility to close f when finished.
337 // Closing l does not affect f, and closing f does not affect l.
339 // The returned os.File's file descriptor is different from the
340 // connection's. Attempting to change properties of the original
341 // using this duplicate may or may not have the desired effect.
342 func (l
*UnixListener
) File() (f
*os
.File
, err error
) { return l
.fd
.dup() }
344 // ListenUnixgram listens for incoming Unix datagram packets addressed
345 // to the local address laddr. The network net must be "unixgram".
346 // The returned connection's ReadFrom and WriteTo methods can be used
347 // to receive and send packets with per-packet addressing.
348 func ListenUnixgram(net
string, laddr
*UnixAddr
) (*UnixConn
, error
) {
352 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: UnknownNetworkError(net
)}
355 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: nil, Err
: errMissingAddress
}
357 fd
, err
:= unixSocket(net
, laddr
, nil, "listen", noDeadline
)
359 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: err
}
361 return newUnixConn(fd
), nil