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.
14 func unixSocket(net
string, laddr
, raddr
*UnixAddr
, mode
string) (fd
*netFD
, err os
.Error
) {
18 return nil, UnknownNetworkError(net
)
20 proto
= syscall
.SOCK_STREAM
22 proto
= syscall
.SOCK_DGRAM
24 proto
= syscall
.SOCK_SEQPACKET
27 var la
, ra syscall
.Sockaddr
30 panic("unixSocket mode " + mode
)
34 la
= &syscall
.SockaddrUnix
{Name
: laddr
.Name
}
37 ra
= &syscall
.SockaddrUnix
{Name
: raddr
.Name
}
38 } else if proto
!= syscall
.SOCK_DGRAM || laddr
== nil {
39 return nil, &OpError
{Op
: mode
, Net
: net
, Error
: errMissingAddress
}
44 return nil, &OpError
{mode
, net
, nil, errMissingAddress
}
46 la
= &syscall
.SockaddrUnix
{Name
: laddr
.Name
}
48 return nil, &OpError
{Op
: mode
, Net
: net
, Addr
: raddr
, Error
: &AddrError
{Error
: "unexpected remote address", Addr
: raddr
.String()}}
53 if proto
== syscall
.SOCK_DGRAM
{
54 f
= sockaddrToUnixgram
55 } else if proto
== syscall
.SOCK_SEQPACKET
{
56 f
= sockaddrToUnixpacket
59 fd
, oserr
:= socket(net
, syscall
.AF_UNIX
, proto
, 0, la
, ra
, f
)
70 return nil, &OpError
{Op
: mode
, Net
: net
, Addr
: addr
, Error
: oserr
}
73 // UnixAddr represents the address of a Unix domain socket end point.
74 type UnixAddr
struct {
79 func sockaddrToUnix(sa syscall
.Sockaddr
) Addr
{
80 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
81 return &UnixAddr
{s
.Name
, "unix"}
86 func sockaddrToUnixgram(sa syscall
.Sockaddr
) Addr
{
87 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
88 return &UnixAddr
{s
.Name
, "unixgram"}
93 func sockaddrToUnixpacket(sa syscall
.Sockaddr
) Addr
{
94 if s
, ok
:= sa
.(*syscall
.SockaddrUnix
); ok
{
95 return &UnixAddr
{s
.Name
, "unixpacket"}
100 func protoToNet(proto
int) string {
102 case syscall
.SOCK_STREAM
:
104 case syscall
.SOCK_SEQPACKET
:
106 case syscall
.SOCK_DGRAM
:
109 panic("protoToNet unknown protocol")
114 // Network returns the address's network name, "unix" or "unixgram".
115 func (a
*UnixAddr
) Network() string {
119 func (a
*UnixAddr
) String() string {
126 func (a
*UnixAddr
) toAddr() Addr
{
127 if a
== nil { // nil *UnixAddr
128 return nil // nil interface
133 // ResolveUnixAddr parses addr as a Unix domain socket address.
134 // The string net gives the network name, "unix", "unixgram" or
136 func ResolveUnixAddr(net
, addr
string) (*UnixAddr
, os
.Error
) {
142 return nil, UnknownNetworkError(net
)
144 return &UnixAddr
{addr
, net
}, nil
147 // UnixConn is an implementation of the Conn interface
148 // for connections to Unix domain sockets.
149 type UnixConn
struct {
153 func newUnixConn(fd
*netFD
) *UnixConn
{ return &UnixConn
{fd
} }
155 func (c
*UnixConn
) ok() bool { return c
!= nil && c
.fd
!= nil }
157 // Implementation of the Conn interface - see Conn for documentation.
159 // Read implements the net.Conn Read method.
160 func (c
*UnixConn
) Read(b
[]byte) (n
int, err os
.Error
) {
167 // Write implements the net.Conn Write method.
168 func (c
*UnixConn
) Write(b
[]byte) (n
int, err os
.Error
) {
175 // Close closes the Unix domain connection.
176 func (c
*UnixConn
) Close() os
.Error
{
185 // LocalAddr returns the local network address, a *UnixAddr.
186 // Unlike in other protocols, LocalAddr is usually nil for dialed connections.
187 func (c
*UnixConn
) LocalAddr() Addr
{
194 // RemoteAddr returns the remote network address, a *UnixAddr.
195 // Unlike in other protocols, RemoteAddr is usually nil for connections
196 // accepted by a listener.
197 func (c
*UnixConn
) RemoteAddr() Addr
{
204 // SetTimeout implements the net.Conn SetTimeout method.
205 func (c
*UnixConn
) SetTimeout(nsec
int64) os
.Error
{
209 return setTimeout(c
.fd
, nsec
)
212 // SetReadTimeout implements the net.Conn SetReadTimeout method.
213 func (c
*UnixConn
) SetReadTimeout(nsec
int64) os
.Error
{
217 return setReadTimeout(c
.fd
, nsec
)
220 // SetWriteTimeout implements the net.Conn SetWriteTimeout method.
221 func (c
*UnixConn
) SetWriteTimeout(nsec
int64) os
.Error
{
225 return setWriteTimeout(c
.fd
, nsec
)
228 // SetReadBuffer sets the size of the operating system's
229 // receive buffer associated with the connection.
230 func (c
*UnixConn
) SetReadBuffer(bytes
int) os
.Error
{
234 return setReadBuffer(c
.fd
, bytes
)
237 // SetWriteBuffer sets the size of the operating system's
238 // transmit buffer associated with the connection.
239 func (c
*UnixConn
) SetWriteBuffer(bytes
int) os
.Error
{
243 return setWriteBuffer(c
.fd
, bytes
)
246 // ReadFromUnix reads a packet from c, copying the payload into b.
247 // It returns the number of bytes copied into b and the return address
248 // that was on the packet.
250 // ReadFromUnix can be made to time out and return
251 // an error with Timeout() == true after a fixed time limit;
252 // see SetTimeout and SetReadTimeout.
253 func (c
*UnixConn
) ReadFromUnix(b
[]byte) (n
int, addr
*UnixAddr
, err os
.Error
) {
255 return 0, nil, os
.EINVAL
257 n
, sa
, err
:= c
.fd
.ReadFrom(b
)
258 switch sa
:= sa
.(type) {
259 case *syscall
.SockaddrUnix
:
260 addr
= &UnixAddr
{sa
.Name
, protoToNet(c
.fd
.proto
)}
265 // ReadFrom implements the net.PacketConn ReadFrom method.
266 func (c
*UnixConn
) ReadFrom(b
[]byte) (n
int, addr Addr
, err os
.Error
) {
268 return 0, nil, os
.EINVAL
270 n
, uaddr
, err
:= c
.ReadFromUnix(b
)
271 return n
, uaddr
.toAddr(), err
274 // WriteToUnix writes a packet to addr via c, copying the payload from b.
276 // WriteToUnix can be made to time out and return
277 // an error with Timeout() == true after a fixed time limit;
278 // see SetTimeout and SetWriteTimeout.
279 // On packet-oriented connections, write timeouts are rare.
280 func (c
*UnixConn
) WriteToUnix(b
[]byte, addr
*UnixAddr
) (n
int, err os
.Error
) {
284 if addr
.Net
!= protoToNet(c
.fd
.proto
) {
285 return 0, os
.EAFNOSUPPORT
287 sa
:= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
288 return c
.fd
.WriteTo(b
, sa
)
291 // WriteTo implements the net.PacketConn WriteTo method.
292 func (c
*UnixConn
) WriteTo(b
[]byte, addr Addr
) (n
int, err os
.Error
) {
296 a
, ok
:= addr
.(*UnixAddr
)
298 return 0, &OpError
{"writeto", "unix", addr
, os
.EINVAL
}
300 return c
.WriteToUnix(b
, a
)
303 func (c
*UnixConn
) ReadMsgUnix(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UnixAddr
, err os
.Error
) {
305 return 0, 0, 0, nil, os
.EINVAL
307 n
, oobn
, flags
, sa
, err
:= c
.fd
.ReadMsg(b
, oob
)
308 switch sa
:= sa
.(type) {
309 case *syscall
.SockaddrUnix
:
310 addr
= &UnixAddr
{sa
.Name
, protoToNet(c
.fd
.proto
)}
315 func (c
*UnixConn
) WriteMsgUnix(b
, oob
[]byte, addr
*UnixAddr
) (n
, oobn
int, err os
.Error
) {
317 return 0, 0, os
.EINVAL
320 if addr
.Net
!= protoToNet(c
.fd
.proto
) {
321 return 0, 0, os
.EAFNOSUPPORT
323 sa
:= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
324 return c
.fd
.WriteMsg(b
, oob
, sa
)
326 return c
.fd
.WriteMsg(b
, oob
, nil)
329 // File returns a copy of the underlying os.File, set to blocking mode.
330 // It is the caller's responsibility to close f when finished.
331 // Closing c does not affect f, and closing f does not affect c.
332 func (c
*UnixConn
) File() (f
*os
.File
, err os
.Error
) { return c
.fd
.dup() }
334 // DialUnix connects to the remote address raddr on the network net,
335 // which must be "unix" or "unixgram". If laddr is not nil, it is used
336 // as the local address for the connection.
337 func DialUnix(net
string, laddr
, raddr
*UnixAddr
) (c
*UnixConn
, err os
.Error
) {
338 fd
, e
:= unixSocket(net
, laddr
, raddr
, "dial")
342 return newUnixConn(fd
), nil
345 // UnixListener is a Unix domain socket listener.
346 // Clients should typically use variables of type Listener
347 // instead of assuming Unix domain sockets.
348 type UnixListener
struct {
353 // ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
354 // Net must be "unix" (stream sockets).
355 func ListenUnix(net
string, laddr
*UnixAddr
) (l
*UnixListener
, err os
.Error
) {
356 if net
!= "unix" && net
!= "unixgram" && net
!= "unixpacket" {
357 return nil, UnknownNetworkError(net
)
360 laddr
= &UnixAddr
{laddr
.Name
, net
} // make our own copy
362 fd
, err
:= unixSocket(net
, laddr
, nil, "listen")
366 e1
:= syscall
.Listen(fd
.sysfd
, 8) // listenBacklog());
368 closesocket(fd
.sysfd
)
369 return nil, &OpError
{Op
: "listen", Net
: "unix", Addr
: laddr
, Error
: os
.Errno(e1
)}
371 return &UnixListener
{fd
, laddr
.Name
}, nil
374 // AcceptUnix accepts the next incoming call and returns the new connection
375 // and the remote address.
376 func (l
*UnixListener
) AcceptUnix() (c
*UnixConn
, err os
.Error
) {
377 if l
== nil || l
.fd
== nil {
378 return nil, os
.EINVAL
380 fd
, e
:= l
.fd
.accept(sockaddrToUnix
)
388 // Accept implements the Accept method in the Listener interface;
389 // it waits for the next call and returns a generic Conn.
390 func (l
*UnixListener
) Accept() (c Conn
, err os
.Error
) {
391 c1
, err
:= l
.AcceptUnix()
398 // Close stops listening on the Unix address.
399 // Already accepted connections are not closed.
400 func (l
*UnixListener
) Close() os
.Error
{
401 if l
== nil || l
.fd
== nil {
405 // The operating system doesn't clean up
406 // the file that announcing created, so
407 // we have to clean it up ourselves.
408 // There's a race here--we can't know for
409 // sure whether someone else has come along
410 // and replaced our socket name already--
411 // but this sequence (remove then close)
412 // is at least compatible with the auto-remove
413 // sequence in ListenUnix. It's only non-Go
414 // programs that can mess us up.
415 if l
.path
[0] != '@' {
416 syscall
.Unlink(l
.path
)
423 // Addr returns the listener's network address.
424 func (l
*UnixListener
) Addr() Addr
{ return l
.fd
.laddr
}
426 // File returns a copy of the underlying os.File, set to blocking mode.
427 // It is the caller's responsibility to close f when finished.
428 // Closing c does not affect f, and closing f does not affect c.
429 func (l
*UnixListener
) File() (f
*os
.File
, err os
.Error
) { return l
.fd
.dup() }
431 // ListenUnixgram listens for incoming Unix datagram packets addressed to the
432 // local address laddr. The returned connection c's ReadFrom
433 // and WriteTo methods can be used to receive and send UDP
434 // packets with per-packet addressing. The network net must be "unixgram".
435 func ListenUnixgram(net
string, laddr
*UnixAddr
) (c
*UDPConn
, err os
.Error
) {
439 return nil, UnknownNetworkError(net
)
442 return nil, &OpError
{"listen", "unixgram", nil, errMissingAddress
}
444 fd
, e
:= unixSocket(net
, laddr
, nil, "listen")
448 return newUDPConn(fd
), nil