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 aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
16 func unixSocket(ctx context
.Context
, net
string, laddr
, raddr sockaddr
, mode
string) (*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(ctx
, net
, syscall
.AF_UNIX
, sotype
, 0, false, laddr
, raddr
)
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
) sockaddr(family
int) (syscall
.Sockaddr
, error
) {
94 return &syscall
.SockaddrUnix
{Name
: a
.Name
}, nil
97 func (a
*UnixAddr
) toLocal(net
string) sockaddr
{
101 func (c
*UnixConn
) readFrom(b
[]byte) (int, *UnixAddr
, error
) {
103 n
, sa
, err
:= c
.fd
.readFrom(b
)
104 switch sa
:= sa
.(type) {
105 case *syscall
.SockaddrUnix
:
107 addr
= &UnixAddr
{Name
: sa
.Name
, Net
: sotypeToNet(c
.fd
.sotype
)}
113 func (c
*UnixConn
) readMsg(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UnixAddr
, err error
) {
114 var sa syscall
.Sockaddr
115 n
, oobn
, flags
, sa
, err
= c
.fd
.readMsg(b
, oob
)
116 switch sa
:= sa
.(type) {
117 case *syscall
.SockaddrUnix
:
119 addr
= &UnixAddr
{Name
: sa
.Name
, Net
: sotypeToNet(c
.fd
.sotype
)}
125 func (c
*UnixConn
) writeTo(b
[]byte, addr
*UnixAddr
) (int, error
) {
126 if c
.fd
.isConnected
{
127 return 0, ErrWriteToConnected
130 return 0, errMissingAddress
132 if addr
.Net
!= sotypeToNet(c
.fd
.sotype
) {
133 return 0, syscall
.EAFNOSUPPORT
135 sa
:= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
136 return c
.fd
.writeTo(b
, sa
)
139 func (c
*UnixConn
) writeMsg(b
, oob
[]byte, addr
*UnixAddr
) (n
, oobn
int, err error
) {
140 if c
.fd
.sotype
== syscall
.SOCK_DGRAM
&& c
.fd
.isConnected
{
141 return 0, 0, ErrWriteToConnected
143 var sa syscall
.Sockaddr
145 if addr
.Net
!= sotypeToNet(c
.fd
.sotype
) {
146 return 0, 0, syscall
.EAFNOSUPPORT
148 sa
= &syscall
.SockaddrUnix
{Name
: addr
.Name
}
150 return c
.fd
.writeMsg(b
, oob
, sa
)
153 func dialUnix(ctx context
.Context
, net
string, laddr
, raddr
*UnixAddr
) (*UnixConn
, error
) {
154 fd
, err
:= unixSocket(ctx
, net
, laddr
, raddr
, "dial")
158 return newUnixConn(fd
), nil
161 func (ln
*UnixListener
) accept() (*UnixConn
, error
) {
162 fd
, err
:= ln
.fd
.accept()
166 return newUnixConn(fd
), nil
169 func (ln
*UnixListener
) close() error
{
170 // The operating system doesn't clean up
171 // the file that announcing created, so
172 // we have to clean it up ourselves.
173 // There's a race here--we can't know for
174 // sure whether someone else has come along
175 // and replaced our socket name already--
176 // but this sequence (remove then close)
177 // is at least compatible with the auto-remove
178 // sequence in ListenUnix. It's only non-Go
179 // programs that can mess us up.
180 // Even if there are racy calls to Close, we want to unlink only for the first one.
181 ln
.unlinkOnce
.Do(func() {
182 if ln
.path
[0] != '@' && ln
.unlink
{
183 syscall
.Unlink(ln
.path
)
189 func (ln
*UnixListener
) file() (*os
.File
, error
) {
190 f
, err
:= ln
.fd
.dup()
197 // SetUnlinkOnClose sets whether the underlying socket file should be removed
198 // from the file system when the listener is closed.
200 // The default behavior is to unlink the socket file only when package net created it.
201 // That is, when the listener and the underlying socket file were created by a call to
202 // Listen or ListenUnix, then by default closing the listener will remove the socket file.
203 // but if the listener was created by a call to FileListener to use an already existing
204 // socket file, then by default closing the listener will not remove the socket file.
205 func (l
*UnixListener
) SetUnlinkOnClose(unlink
bool) {
209 func listenUnix(ctx context
.Context
, network
string, laddr
*UnixAddr
) (*UnixListener
, error
) {
210 fd
, err
:= unixSocket(ctx
, network
, laddr
, nil, "listen")
214 return &UnixListener
{fd
: fd
, path
: fd
.laddr
.String(), unlink
: true}, nil
217 func listenUnixgram(ctx context
.Context
, network
string, laddr
*UnixAddr
) (*UnixConn
, error
) {
218 fd
, err
:= unixSocket(ctx
, network
, laddr
, nil, "listen")
222 return newUnixConn(fd
), nil