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 netbsd openbsd 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
)
46 if sotype
== syscall
.SOCK_DGRAM
{
47 f
= sockaddrToUnixgram
48 } else if sotype
== syscall
.SOCK_SEQPACKET
{
49 f
= sockaddrToUnixpacket
52 fd
, err
:= socket(net
, syscall
.AF_UNIX
, sotype
, 0, false, laddr
, raddr
, deadline
, f
)
59 func sockaddrToUnix(sa syscall
.Sockaddr
) Addr
{
60 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
61 return &UnixAddr
{Name
: s
.Name
, Net
: "unix"}
66 func sockaddrToUnixgram(sa syscall
.Sockaddr
) Addr
{
67 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
68 return &UnixAddr
{Name
: s
.Name
, Net
: "unixgram"}
73 func sockaddrToUnixpacket(sa syscall
.Sockaddr
) Addr
{
74 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
75 return &UnixAddr
{Name
: s
.Name
, Net
: "unixpacket"}
80 func sotypeToNet(sotype
int) string {
82 case syscall
.SOCK_STREAM
:
84 case syscall
.SOCK_DGRAM
:
86 case syscall
.SOCK_SEQPACKET
:
89 panic("sotypeToNet unknown socket type")
93 func (a
*UnixAddr
) family() int {
94 return syscall
.AF_UNIX
97 func (a
*UnixAddr
) isWildcard() bool {
98 return a
== nil || a
.Name
== ""
101 func (a
*UnixAddr
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
105 return &syscall
.SockaddrUnix
{Name
: a
.Name
}, nil
108 // UnixConn is an implementation of the Conn interface for connections
109 // to Unix domain sockets.
110 type UnixConn
struct {
114 func newUnixConn(fd
*netFD
) *UnixConn
{ return &UnixConn
{conn
{fd
}} }
116 // ReadFromUnix reads a packet from c, copying the payload into b. It
117 // returns the number of bytes copied into b and the source address of
120 // ReadFromUnix can be made to time out and return an error with
121 // Timeout() == true after a fixed time limit; see SetDeadline and
123 func (c
*UnixConn
) ReadFromUnix(b
[]byte) (n
int, addr
*UnixAddr
, err error
) {
125 return 0, nil, syscall
.EINVAL
127 n
, sa
, err
:= c
.fd
.ReadFrom(b
)
128 switch sa
:= sa
.(type) {
129 case *syscall
.SockaddrUnix
:
131 addr
= &UnixAddr
{Name
: sa
.Name
, Net
: sotypeToNet(c
.fd
.sotype
)}
137 // ReadFrom implements the PacketConn ReadFrom method.
138 func (c
*UnixConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
140 return 0, nil, syscall
.EINVAL
142 n
, addr
, err
:= c
.ReadFromUnix(b
)
143 return n
, addr
.toAddr(), err
146 // ReadMsgUnix reads a packet from c, copying the payload into b and
147 // the associated out-of-band data into oob. It returns the number of
148 // bytes copied into b, the number of bytes copied into oob, the flags
149 // that were set on the packet, and the source address of the packet.
150 func (c
*UnixConn
) ReadMsgUnix(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UnixAddr
, err error
) {
152 return 0, 0, 0, nil, syscall
.EINVAL
154 n
, oobn
, flags
, sa
, err
:= c
.fd
.ReadMsg(b
, oob
)
155 switch sa
:= sa
.(type) {
156 case *syscall
.SockaddrUnix
:
158 addr
= &UnixAddr
{Name
: sa
.Name
, Net
: sotypeToNet(c
.fd
.sotype
)}
164 // WriteToUnix writes a packet to addr via c, copying the payload from b.
166 // WriteToUnix can be made to time out and return an error with
167 // Timeout() == true after a fixed time limit; see SetDeadline and
168 // SetWriteDeadline. On packet-oriented connections, write timeouts
170 func (c
*UnixConn
) WriteToUnix(b
[]byte, addr
*UnixAddr
) (n
int, err error
) {
172 return 0, syscall
.EINVAL
175 return 0, &OpError
{Op
: "write", Net
: c
.fd
.net
, Addr
: nil, Err
: errMissingAddress
}
177 if addr
.Net
!= sotypeToNet(c
.fd
.sotype
) {
178 return 0, syscall
.EAFNOSUPPORT
180 sa
:= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
181 return c
.fd
.WriteTo(b
, sa
)
184 // WriteTo implements the PacketConn WriteTo method.
185 func (c
*UnixConn
) WriteTo(b
[]byte, addr Addr
) (n
int, err error
) {
187 return 0, syscall
.EINVAL
189 a
, ok
:= addr
.(*UnixAddr
)
191 return 0, &OpError
{"write", c
.fd
.net
, addr
, syscall
.EINVAL
}
193 return c
.WriteToUnix(b
, a
)
196 // WriteMsgUnix writes a packet to addr via c, copying the payload
197 // from b and the associated out-of-band data from oob. It returns
198 // the number of payload and out-of-band bytes written.
199 func (c
*UnixConn
) WriteMsgUnix(b
, oob
[]byte, addr
*UnixAddr
) (n
, oobn
int, err error
) {
201 return 0, 0, syscall
.EINVAL
204 if addr
.Net
!= sotypeToNet(c
.fd
.sotype
) {
205 return 0, 0, syscall
.EAFNOSUPPORT
207 sa
:= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
208 return c
.fd
.WriteMsg(b
, oob
, sa
)
210 return c
.fd
.WriteMsg(b
, oob
, nil)
213 // CloseRead shuts down the reading side of the Unix domain connection.
214 // Most callers should just use Close.
215 func (c
*UnixConn
) CloseRead() error
{
217 return syscall
.EINVAL
219 return c
.fd
.CloseRead()
222 // CloseWrite shuts down the writing side of the Unix domain connection.
223 // Most callers should just use Close.
224 func (c
*UnixConn
) CloseWrite() error
{
226 return syscall
.EINVAL
228 return c
.fd
.CloseWrite()
231 // DialUnix connects to the remote address raddr on the network net,
232 // which must be "unix", "unixgram" or "unixpacket". If laddr is not
233 // nil, it is used as the local address for the connection.
234 func DialUnix(net
string, laddr
, raddr
*UnixAddr
) (*UnixConn
, error
) {
236 case "unix", "unixgram", "unixpacket":
238 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: raddr
, Err
: UnknownNetworkError(net
)}
240 return dialUnix(net
, laddr
, raddr
, noDeadline
)
243 func dialUnix(net
string, laddr
, raddr
*UnixAddr
, deadline time
.Time
) (*UnixConn
, error
) {
244 fd
, err
:= unixSocket(net
, laddr
, raddr
, "dial", deadline
)
246 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: raddr
, Err
: err
}
248 return newUnixConn(fd
), nil
251 // UnixListener is a Unix domain socket listener. Clients should
252 // typically use variables of type Listener instead of assuming Unix
254 type UnixListener
struct {
259 // ListenUnix announces on the Unix domain socket laddr and returns a
260 // Unix listener. The network net must be "unix" or "unixpacket".
261 func ListenUnix(net
string, laddr
*UnixAddr
) (*UnixListener
, error
) {
263 case "unix", "unixpacket":
265 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: UnknownNetworkError(net
)}
268 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: nil, Err
: errMissingAddress
}
270 fd
, err
:= unixSocket(net
, laddr
, nil, "listen", noDeadline
)
272 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: err
}
274 return &UnixListener
{fd
, fd
.laddr
.String()}, nil
277 // AcceptUnix accepts the next incoming call and returns the new
279 func (l
*UnixListener
) AcceptUnix() (*UnixConn
, error
) {
280 if l
== nil || l
.fd
== nil {
281 return nil, syscall
.EINVAL
283 fd
, err
:= l
.fd
.accept(sockaddrToUnix
)
291 // Accept implements the Accept method in the Listener interface; it
292 // waits for the next call and returns a generic Conn.
293 func (l
*UnixListener
) Accept() (c Conn
, err error
) {
294 c1
, err
:= l
.AcceptUnix()
301 // Close stops listening on the Unix address. Already accepted
302 // connections are not closed.
303 func (l
*UnixListener
) Close() error
{
304 if l
== nil || l
.fd
== nil {
305 return syscall
.EINVAL
308 // The operating system doesn't clean up
309 // the file that announcing created, so
310 // we have to clean it up ourselves.
311 // There's a race here--we can't know for
312 // sure whether someone else has come along
313 // and replaced our socket name already--
314 // but this sequence (remove then close)
315 // is at least compatible with the auto-remove
316 // sequence in ListenUnix. It's only non-Go
317 // programs that can mess us up.
318 if l
.path
[0] != '@' {
319 syscall
.Unlink(l
.path
)
324 // Addr returns the listener's network address.
325 func (l
*UnixListener
) Addr() Addr
{ return l
.fd
.laddr
}
327 // SetDeadline sets the deadline associated with the listener.
328 // A zero time value disables the deadline.
329 func (l
*UnixListener
) SetDeadline(t time
.Time
) (err error
) {
330 if l
== nil || l
.fd
== nil {
331 return syscall
.EINVAL
333 return l
.fd
.setDeadline(t
)
336 // File returns a copy of the underlying os.File, set to blocking
337 // mode. It is the caller's responsibility to close f when finished.
338 // Closing l does not affect f, and closing f does not affect l.
340 // The returned os.File's file descriptor is different from the
341 // connection's. Attempting to change properties of the original
342 // using this duplicate may or may not have the desired effect.
343 func (l
*UnixListener
) File() (f
*os
.File
, err error
) { return l
.fd
.dup() }
345 // ListenUnixgram listens for incoming Unix datagram packets addressed
346 // to the local address laddr. The network net must be "unixgram".
347 // The returned connection's ReadFrom and WriteTo methods can be used
348 // to receive and send packets with per-packet addressing.
349 func ListenUnixgram(net
string, laddr
*UnixAddr
) (*UnixConn
, error
) {
353 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: UnknownNetworkError(net
)}
356 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: nil, Err
: errMissingAddress
}
358 fd
, err
:= unixSocket(net
, laddr
, nil, "listen", noDeadline
)
360 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: laddr
, Err
: err
}
362 return newUnixConn(fd
), nil