Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
cc1d4b7e
Commit
cc1d4b7e
authored
May 13, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Unix domain socket support, Linux and Darwin.
R=r DELTA=534 (353 added, 99 deleted, 82 changed) OCL=28783 CL=28783
parent
533dfd62
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
336 additions
and
82 deletions
+336
-82
src/lib/net/net.go
src/lib/net/net.go
+253
-71
src/lib/net/net_darwin.go
src/lib/net/net_darwin.go
+29
-1
src/lib/net/net_linux.go
src/lib/net/net_linux.go
+44
-0
src/lib/net/server_test.go
src/lib/net/server_test.go
+8
-0
src/lib/os/error.go
src/lib/os/error.go
+2
-0
src/lib/syscall/socket_darwin.go
src/lib/syscall/socket_darwin.go
+0
-5
src/lib/syscall/socket_linux.go
src/lib/syscall/socket_linux.go
+0
-5
No files found.
src/lib/net/net.go
View file @
cc1d4b7e
...
@@ -20,6 +20,83 @@ var (
...
@@ -20,6 +20,83 @@ var (
)
)
// Conn is a generic network connection.
type
Conn
interface
{
// Read blocks until data is ready from the connection
// and then reads into b. It returns the number
// of bytes read, or 0 if the connection has been closed.
Read
(
b
[]
byte
)
(
n
int
,
err
os
.
Error
);
// Write writes the data in b to the connection.
Write
(
b
[]
byte
)
(
n
int
,
err
os
.
Error
);
// Close closes the connection.
Close
()
os
.
Error
;
// For packet-based protocols such as UDP,
// ReadFrom reads the next packet from the network,
// returning the number of bytes read and the remote
// address that sent them.
ReadFrom
(
b
[]
byte
)
(
n
int
,
addr
string
,
err
os
.
Error
);
// For packet-based protocols such as UDP,
// WriteTo writes the byte buffer b to the network
// as a single payload, sending it to the target address.
WriteTo
(
addr
string
,
b
[]
byte
)
(
n
int
,
err
os
.
Error
);
// SetReadBuffer sets the size of the operating system's
// receive buffer associated with the connection.
SetReadBuffer
(
bytes
int
)
os
.
Error
;
// SetReadBuffer sets the size of the operating system's
// transmit buffer associated with the connection.
SetWriteBuffer
(
bytes
int
)
os
.
Error
;
// SetTimeout sets the read and write deadlines associated
// with the connection.
SetTimeout
(
nsec
int64
)
os
.
Error
;
// SetReadTimeout sets the time (in nanoseconds) that
// Read will wait for data before returning os.EAGAIN.
// Setting nsec == 0 (the default) disables the deadline.
SetReadTimeout
(
nsec
int64
)
os
.
Error
;
// SetWriteTimeout sets the time (in nanoseconds) that
// Write will wait to send its data before returning os.EAGAIN.
// Setting nsec == 0 (the default) disables the deadline.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
SetWriteTimeout
(
nsec
int64
)
os
.
Error
;
// SetLinger sets the behavior of Close() on a connection
// which still has data waiting to be sent or to be acknowledged.
//
// If sec < 0 (the default), Close returns immediately and
// the operating system finishes sending the data in the background.
//
// If sec == 0, Close returns immediately and the operating system
// discards any unsent or unacknowledged data.
//
// If sec > 0, Close blocks for at most sec seconds waiting for
// data to be sent and acknowledged.
SetLinger
(
sec
int
)
os
.
Error
;
// SetReuseAddr sets whether it is okay to reuse addresses
// from recent connections that were not properly closed.
SetReuseAddr
(
reuseaddr
bool
)
os
.
Error
;
// SetDontRoute sets whether outgoing messages should
// bypass the system routing tables.
SetDontRoute
(
dontroute
bool
)
os
.
Error
;
// SetKeepAlive sets whether the operating system should send
// keepalive messages on the connection.
SetKeepAlive
(
keepalive
bool
)
os
.
Error
;
// BindToDevice binds a connection to a particular network device.
BindToDevice
(
dev
string
)
os
.
Error
;
}
// Should we try to use the IPv4 socket interface if we're
// Should we try to use the IPv4 socket interface if we're
// only dealing with IPv4 sockets? As long as the host system
// only dealing with IPv4 sockets? As long as the host system
// understands IPv6, it's okay to pass IPv4 addresses to the IPv6
// understands IPv6, it's okay to pass IPv4 addresses to the IPv6
...
@@ -160,9 +237,7 @@ func boolint(b bool) int {
...
@@ -160,9 +237,7 @@ func boolint(b bool) int {
}
}
// Generic socket creation.
// Generic socket creation.
func
socket
(
net
,
laddr
,
raddr
string
,
f
,
p
,
t
int64
,
la
,
ra
*
syscall
.
Sockaddr
)
func
socket
(
net
,
laddr
,
raddr
string
,
f
,
p
,
t
int64
,
la
,
ra
*
syscall
.
Sockaddr
)
(
fd
*
netFD
,
err
os
.
Error
)
{
(
fd
*
netFD
,
err
os
.
Error
)
{
// See ../syscall/exec.go for description of ForkLock.
// See ../syscall/exec.go for description of ForkLock.
syscall
.
ForkLock
.
RLock
();
syscall
.
ForkLock
.
RLock
();
s
,
e
:=
syscall
.
Socket
(
f
,
p
,
t
);
s
,
e
:=
syscall
.
Socket
(
f
,
p
,
t
);
...
@@ -318,9 +393,7 @@ func (c *connBase) SetLinger(sec int) os.Error {
...
@@ -318,9 +393,7 @@ func (c *connBase) SetLinger(sec int) os.Error {
// Internet sockets (TCP, UDP)
// Internet sockets (TCP, UDP)
func
internetSocket
(
net
,
laddr
,
raddr
string
,
proto
int64
,
mode
string
)
func
internetSocket
(
net
,
laddr
,
raddr
string
,
proto
int64
,
mode
string
)
(
fd
*
netFD
,
err
os
.
Error
)
{
(
fd
*
netFD
,
err
os
.
Error
)
{
// Parse addresses (unless they are empty).
// Parse addresses (unless they are empty).
var
lip
,
rip
IP
;
var
lip
,
rip
IP
;
var
lport
,
rport
int
;
var
lport
,
rport
int
;
...
@@ -388,6 +461,8 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string)
...
@@ -388,6 +461,8 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string)
// TCP connections.
// TCP connections.
// ConnTCP is an implementation of the Conn interface
// for TCP network connections.
type
ConnTCP
struct
{
type
ConnTCP
struct
{
connBase
connBase
}
}
...
@@ -407,6 +482,8 @@ func newConnTCP(fd *netFD, raddr string) *ConnTCP {
...
@@ -407,6 +482,8 @@ func newConnTCP(fd *netFD, raddr string) *ConnTCP {
return
c
return
c
}
}
// DialTCP is like Dial but can only connect to TCP networks
// and returns a ConnTCP structure.
func
DialTCP
(
net
,
laddr
,
raddr
string
)
(
c
*
ConnTCP
,
err
os
.
Error
)
{
func
DialTCP
(
net
,
laddr
,
raddr
string
)
(
c
*
ConnTCP
,
err
os
.
Error
)
{
if
raddr
==
""
{
if
raddr
==
""
{
return
nil
,
MissingAddress
return
nil
,
MissingAddress
...
@@ -423,6 +500,8 @@ func DialTCP(net, laddr, raddr string) (c *ConnTCP, err os.Error) {
...
@@ -423,6 +500,8 @@ func DialTCP(net, laddr, raddr string) (c *ConnTCP, err os.Error) {
// TODO(rsc): UDP headers mode
// TODO(rsc): UDP headers mode
// ConnUDP is an implementation of the Conn interface
// for UDP network connections.
type
ConnUDP
struct
{
type
ConnUDP
struct
{
connBase
connBase
}
}
...
@@ -434,6 +513,8 @@ func newConnUDP(fd *netFD, raddr string) *ConnUDP {
...
@@ -434,6 +513,8 @@ func newConnUDP(fd *netFD, raddr string) *ConnUDP {
return
c
return
c
}
}
// DialUDP is like Dial but can only connect to UDP networks
// and returns a ConnUDP structure.
func
DialUDP
(
net
,
laddr
,
raddr
string
)
(
c
*
ConnUDP
,
err
os
.
Error
)
{
func
DialUDP
(
net
,
laddr
,
raddr
string
)
(
c
*
ConnUDP
,
err
os
.
Error
)
{
if
raddr
==
""
{
if
raddr
==
""
{
return
nil
,
MissingAddress
return
nil
,
MissingAddress
...
@@ -450,81 +531,172 @@ func DialUDP(net, laddr, raddr string) (c *ConnUDP, err os.Error) {
...
@@ -450,81 +531,172 @@ func DialUDP(net, laddr, raddr string) (c *ConnUDP, err os.Error) {
// TODO: raw ethernet connections
// TODO: raw ethernet connections
// A Conn is a generic network connection.
type
Conn
interface
{
// Read blocks until data is ready from the connection
// and then reads into b. It returns the number
// of bytes read, or 0 if the connection has been closed.
Read
(
b
[]
byte
)
(
n
int
,
err
os
.
Error
);
// Write writes the data in b to the connection.
// Unix domain sockets
Write
(
b
[]
byte
)
(
n
int
,
err
os
.
Error
);
// Close closes the connection.
func
unixSocket
(
net
,
laddr
,
raddr
string
,
mode
string
)
(
fd
*
netFD
,
err
os
.
Error
)
{
Close
()
os
.
Error
;
var
proto
int64
;
switch
net
{
default
:
return
nil
,
UnknownNetwork
;
case
"unix"
:
proto
=
syscall
.
SOCK_STREAM
;
case
"unix-dgram"
:
proto
=
syscall
.
SOCK_DGRAM
;
}
// For packet-based protocols such as UDP,
var
la
,
ra
*
syscall
.
Sockaddr
;
// ReadFrom reads the next packet from the network,
switch
mode
{
// returning the number of bytes read and the remote
case
"dial"
:
// address that sent them.
if
laddr
!=
""
{
ReadFrom
(
b
[]
byte
)
(
n
int
,
addr
string
,
err
os
.
Error
);
return
nil
,
BadAddress
;
}
if
raddr
==
""
{
return
nil
,
MissingAddress
;
}
ra
,
err
=
unixToSockaddr
(
raddr
);
if
err
!=
nil
{
return
nil
,
err
;
}
// For packet-based protocols such as UDP,
case
"listen"
:
// WriteTo writes the byte buffer b to the network
if
laddr
==
""
{
// as a single payload, sending it to the target address.
return
nil
,
MissingAddress
;
WriteTo
(
addr
string
,
b
[]
byte
)
(
n
int
,
err
os
.
Error
);
}
la
,
err
=
unixToSockaddr
(
laddr
);
if
err
!=
nil
{
return
nil
,
err
;
}
if
raddr
!=
""
{
return
nil
,
BadAddress
;
}
}
// SetReadBuffer sets the size of the operating system's
fd
,
err
=
socket
(
net
,
laddr
,
raddr
,
syscall
.
AF_UNIX
,
proto
,
0
,
la
,
ra
);
// receive buffer associated with the connection.
return
fd
,
err
SetReadBuffer
(
bytes
int
)
os
.
Error
;
}
// SetReadBuffer sets the size of the operating system's
// ConnUnix is an implementation of the Conn interface
// transmit buffer associated with the connection.
// for connections to Unix domain sockets.
SetWriteBuffer
(
bytes
int
)
os
.
Error
;
type
ConnUnix
struct
{
connBase
}
// SetTimeout sets the read and write deadlines associated
func
newConnUnix
(
fd
*
netFD
,
raddr
string
)
*
ConnUnix
{
// with the connection.
c
:=
new
(
ConnUnix
);
SetTimeout
(
nsec
int64
)
os
.
Error
;
c
.
fd
=
fd
;
c
.
raddr
=
raddr
;
return
c
;
}
// SetReadTimeout sets the time (in nanoseconds) that
// DialUnix is like Dial but can only connect to Unix domain sockets
// Read will wait for data before returning os.EAGAIN.
// and returns a ConnUnix structure. The laddr argument must be
// Setting nsec == 0 (the default) disables the deadline.
// the empty string; it is included only to match the signature of
SetReadTimeout
(
nsec
int64
)
os
.
Error
;
// the other dial routines.
func
DialUnix
(
net
,
laddr
,
raddr
string
)
(
c
*
ConnUnix
,
err
os
.
Error
)
{
fd
,
e
:=
unixSocket
(
net
,
laddr
,
raddr
,
"dial"
);
if
e
!=
nil
{
return
nil
,
e
}
return
newConnUnix
(
fd
,
raddr
),
nil
;
}
// SetWriteTimeout sets the time (in nanoseconds) that
// ListenerUnix is a Unix domain socket listener.
// Write will wait to send its data before returning os.EAGAIN.
// Clients should typically use variables of type Listener
// Setting nsec == 0 (the default) disables the deadline.
// instead of assuming Unix domain sockets.
// Even if write times out, it may return n > 0, indicating that
type
ListenerUnix
struct
{
// some of the data was successfully written.
fd
*
netFD
;
SetWriteTimeout
(
nsec
int64
)
os
.
Error
;
laddr
string
}
// SetLinger sets the behavior of Close() on a connection
// ListenUnix announces on the Unix domain socket laddr and returns a Unix listener.
// which still has data waiting to be sent or to be acknowledged.
// Net can be either "unix" (stream sockets) or "unix-dgram" (datagram sockets).
//
func
ListenUnix
(
net
,
laddr
string
)
(
l
*
ListenerUnix
,
err
os
.
Error
)
{
// If sec < 0 (the default), Close returns immediately and
fd
,
e
:=
unixSocket
(
net
,
laddr
,
""
,
"listen"
);
// the operating system finishes sending the data in the background.
if
e
!=
nil
{
//
// Check for socket ``in use'' but ``refusing connections,''
// If sec == 0, Close returns immediately and the operating system
// which means some program created it and exited
// discards any unsent or unacknowledged data.
// without unlinking it from the file system.
//
// Clean up on that program's behalf and try again.
// If sec > 0, Close blocks for at most sec seconds waiting for
// Don't do this for Linux's ``abstract'' sockets, which begin with @.
// data to be sent and acknowledged.
if
e
!=
os
.
EADDRINUSE
||
laddr
[
0
]
==
'@'
{
SetLinger
(
sec
int
)
os
.
Error
;
return
nil
,
e
;
}
fd1
,
e1
:=
unixSocket
(
net
,
""
,
laddr
,
"dial"
);
if
e1
==
nil
{
fd1
.
Close
();
}
if
e1
!=
os
.
ECONNREFUSED
{
return
nil
,
e
;
}
syscall
.
Unlink
(
laddr
);
fd1
,
e1
=
unixSocket
(
net
,
laddr
,
""
,
"listen"
);
if
e1
!=
nil
{
return
nil
,
e
;
}
fd
=
fd1
;
}
r
,
e1
:=
syscall
.
Listen
(
fd
.
fd
,
8
);
// listenBacklog());
if
e1
!=
0
{
syscall
.
Close
(
fd
.
fd
);
return
nil
,
os
.
ErrnoToError
(
e1
);
}
return
&
ListenerUnix
{
fd
,
laddr
},
nil
;
}
// SetReuseAddr sets whether it is okay to reuse addresses
// AcceptUnix accepts the next incoming call and returns the new connection
// from recent connections that were not properly closed.
// and the remote address.
SetReuseAddr
(
reuseaddr
bool
)
os
.
Error
;
func
(
l
*
ListenerUnix
)
AcceptUnix
()
(
c
*
ConnUnix
,
raddr
string
,
err
os
.
Error
)
{
if
l
==
nil
||
l
.
fd
==
nil
||
l
.
fd
.
fd
<
0
{
return
nil
,
""
,
os
.
EINVAL
}
var
sa
syscall
.
Sockaddr
;
fd
,
e
:=
l
.
fd
.
Accept
(
&
sa
);
if
e
!=
nil
{
return
nil
,
""
,
e
}
raddr
,
err
=
sockaddrToUnix
(
&
sa
);
if
err
!=
nil
{
fd
.
Close
();
return
nil
,
""
,
err
}
return
newConnUnix
(
fd
,
raddr
),
raddr
,
nil
}
// SetDontRoute sets whether outgoing messages should
// Accept implements the Accept method in the Listener interface;
// bypass the system routing tables.
// it waits for the next call and returns a generic Conn.
SetDontRoute
(
dontroute
bool
)
os
.
Error
;
func
(
l
*
ListenerUnix
)
Accept
()
(
c
Conn
,
raddr
string
,
err
os
.
Error
)
{
// TODO(rsc): 6g bug prevents saying
// c, raddr, err = l.AcceptUnix();
// return;
c1
,
r1
,
e1
:=
l
.
AcceptUnix
();
return
c1
,
r1
,
e1
;
}
// SetKeepAlive sets whether the operating system should send
// keepalive messages on the connection.
SetKeepAlive
(
keepalive
bool
)
os
.
Error
;
// BindToDevice binds a connection to a particular network device.
// Close stops listening on the Unix address.
BindToDevice
(
dev
string
)
os
.
Error
;
// Already accepted connections are not closed.
func
(
l
*
ListenerUnix
)
Close
()
os
.
Error
{
if
l
==
nil
||
l
.
fd
==
nil
{
return
os
.
EINVAL
}
// The operating system doesn't clean up
// the file that announcing created, so
// we have to clean it up ourselves.
// There's a race here--we can't know for
// sure whether someone else has come along
// and replaced our socket name already--
// but this sequence (remove then close)
// is at least compatible with the auto-remove
// sequence in ListenUnix. It's only non-Go
// programs that can mess us up.
if
l
.
laddr
[
0
]
!=
'@'
{
syscall
.
Unlink
(
l
.
laddr
);
}
err
:=
l
.
fd
.
Close
();
l
.
fd
=
nil
;
return
err
;
}
}
// Dial connects to the remote address raddr on the network net.
// Dial connects to the remote address raddr on the network net.
...
@@ -553,6 +725,9 @@ func Dial(net, laddr, raddr string) (c Conn, err os.Error) {
...
@@ -553,6 +725,9 @@ func Dial(net, laddr, raddr string) (c Conn, err os.Error) {
case
"udp"
,
"udp4"
,
"upd6"
:
case
"udp"
,
"udp4"
,
"upd6"
:
c
,
err
:=
DialUDP
(
net
,
laddr
,
raddr
);
c
,
err
:=
DialUDP
(
net
,
laddr
,
raddr
);
return
c
,
err
;
return
c
,
err
;
case
"unix"
,
"unix-dgram"
:
c
,
err
:=
DialUnix
(
net
,
laddr
,
raddr
);
return
c
,
err
;
/*
/*
case "ether":
case "ether":
c, err := DialEther(net, laddr, raddr);
c, err := DialEther(net, laddr, raddr);
...
@@ -619,7 +794,7 @@ func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err os.Error) {
...
@@ -619,7 +794,7 @@ func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err os.Error) {
return
newConnTCP
(
fd
,
raddr
),
raddr
,
nil
return
newConnTCP
(
fd
,
raddr
),
raddr
,
nil
}
}
// Accept implements the
a
ccept method in the Listener interface;
// Accept implements the
A
ccept method in the Listener interface;
// it waits for the next call and returns a generic Conn.
// it waits for the next call and returns a generic Conn.
func
(
l
*
ListenerTCP
)
Accept
()
(
c
Conn
,
raddr
string
,
err
os
.
Error
)
{
func
(
l
*
ListenerTCP
)
Accept
()
(
c
Conn
,
raddr
string
,
err
os
.
Error
)
{
c1
,
r1
,
e1
:=
l
.
AcceptTCP
();
c1
,
r1
,
e1
:=
l
.
AcceptTCP
();
...
@@ -639,15 +814,22 @@ func (l *ListenerTCP) Close() os.Error {
...
@@ -639,15 +814,22 @@ func (l *ListenerTCP) Close() os.Error {
}
}
// Listen announces on the local network address laddr.
// Listen announces on the local network address laddr.
// The network string net must be "tcp", "tcp4", or "tcp6".
// The network string net must be "tcp", "tcp4", "tcp6",
// "unix", or "unix-dgram".
func
Listen
(
net
,
laddr
string
)
(
l
Listener
,
err
os
.
Error
)
{
func
Listen
(
net
,
laddr
string
)
(
l
Listener
,
err
os
.
Error
)
{
switch
net
{
switch
net
{
case
"tcp"
,
"tcp4"
,
"tcp6"
:
case
"tcp"
,
"tcp4"
,
"tcp6"
:
l
,
err
:=
ListenTCP
(
net
,
laddr
);
l
,
err
:=
ListenTCP
(
net
,
laddr
);
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
;
}
}
return
l
,
nil
return
l
,
nil
;
case
"unix"
,
"unix-dgram"
:
l
,
err
:=
ListenUnix
(
net
,
laddr
);
if
err
!=
nil
{
return
nil
,
err
;
}
return
l
,
nil
;
/*
/*
more here
more here
*/
*/
...
...
src/lib/net/net_darwin.go
View file @
cc1d4b7e
...
@@ -43,7 +43,6 @@ func v6ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err os.Error) {
...
@@ -43,7 +43,6 @@ func v6ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err os.Error) {
return
(
*
syscall
.
Sockaddr
)(
unsafe
.
Pointer
(
sa
)),
nil
return
(
*
syscall
.
Sockaddr
)(
unsafe
.
Pointer
(
sa
)),
nil
}
}
func
sockaddrToIP
(
sa1
*
syscall
.
Sockaddr
)
(
p
IP
,
port
int
,
err
os
.
Error
)
{
func
sockaddrToIP
(
sa1
*
syscall
.
Sockaddr
)
(
p
IP
,
port
int
,
err
os
.
Error
)
{
switch
sa1
.
Family
{
switch
sa1
.
Family
{
case
syscall
.
AF_INET
:
case
syscall
.
AF_INET
:
...
@@ -70,3 +69,32 @@ func listenBacklog() int64 {
...
@@ -70,3 +69,32 @@ func listenBacklog() int64 {
return
syscall
.
SOMAXCONN
return
syscall
.
SOMAXCONN
}
}
func
unixToSockaddr
(
name
string
)
(
sa1
*
syscall
.
Sockaddr
,
err
os
.
Error
)
{
sa
:=
new
(
syscall
.
SockaddrUnix
);
n
:=
len
(
name
);
if
n
>=
len
(
sa
.
Path
)
||
n
==
0
{
return
nil
,
os
.
EINVAL
;
}
sa
.
Len
=
byte
(
3
+
n
);
// 2 for Family, Len; 1 for NUL
sa
.
Family
=
syscall
.
AF_UNIX
;
for
i
:=
0
;
i
<
len
(
name
);
i
++
{
sa
.
Path
[
i
]
=
name
[
i
];
}
return
(
*
syscall
.
Sockaddr
)(
unsafe
.
Pointer
(
sa
)),
nil
;
}
func
sockaddrToUnix
(
sa1
*
syscall
.
Sockaddr
)
(
string
,
os
.
Error
)
{
if
sa1
.
Family
!=
syscall
.
AF_UNIX
||
sa1
.
Len
<
3
||
sa1
.
Len
>
syscall
.
SizeofSockaddrUnix
{
return
""
,
os
.
EINVAL
;
}
sa
:=
(
*
syscall
.
SockaddrUnix
)(
unsafe
.
Pointer
(
sa1
));
n
:=
int
(
sa
.
Len
)
-
3
;
// subtract leading Family, Len, terminating NUL
for
i
:=
0
;
i
<
n
;
i
++
{
if
sa
.
Path
[
i
]
==
0
{
// found early NUL; assume Len is overestimating
n
=
i
;
break
;
}
}
return
string
(
sa
.
Path
[
0
:
n
]),
nil
;
}
src/lib/net/net_linux.go
View file @
cc1d4b7e
...
@@ -77,3 +77,47 @@ func listenBacklog() int64 {
...
@@ -77,3 +77,47 @@ func listenBacklog() int64 {
return
syscall
.
SOMAXCONN
return
syscall
.
SOMAXCONN
}
}
func
unixToSockaddr
(
name
string
)
(
sa1
*
syscall
.
Sockaddr
,
err
os
.
Error
)
{
sa
:=
new
(
syscall
.
SockaddrUnix
);
n
:=
len
(
name
);
if
n
>=
len
(
sa
.
Path
)
||
n
==
0
{
return
nil
,
os
.
EINVAL
;
}
sa
.
Family
=
syscall
.
AF_UNIX
;
for
i
:=
0
;
i
<
len
(
name
);
i
++
{
sa
.
Path
[
i
]
=
name
[
i
];
}
// Special case: @ in first position indicates
// an abstract socket, which has no file system
// representation and starts with a NUL byte
// when talking to the kernel about it.
if
sa
.
Path
[
0
]
==
'@'
{
sa
.
Path
[
0
]
=
0
;
}
return
(
*
syscall
.
Sockaddr
)(
unsafe
.
Pointer
(
sa
)),
nil
;
}
func
sockaddrToUnix
(
sa1
*
syscall
.
Sockaddr
)
(
string
,
os
.
Error
)
{
if
sa1
.
Family
!=
syscall
.
AF_UNIX
{
return
""
,
os
.
EINVAL
;
}
sa
:=
(
*
syscall
.
SockaddrUnix
)(
unsafe
.
Pointer
(
sa1
));
// @ special case (see comment in unixToSockaddr).
if
sa
.
Path
[
0
]
==
0
{
// Not friendly to overwrite in place but
// okay in an internal function.
// The caller doesn't care if we do.
sa
.
Path
[
0
]
=
'@'
;
}
// count length of path
n
:=
0
;
for
n
<
len
(
sa
.
Path
)
&&
sa
.
Path
[
n
]
!=
0
{
n
++
;
}
return
string
(
sa
.
Path
[
0
:
n
]),
nil
;
}
src/lib/net/
tcp
server_test.go
→
src/lib/net/server_test.go
View file @
cc1d4b7e
...
@@ -8,6 +8,7 @@ import (
...
@@ -8,6 +8,7 @@ import (
"io"
;
"io"
;
"net"
;
"net"
;
"os"
;
"os"
;
"syscall"
;
"testing"
;
"testing"
;
)
)
...
@@ -83,3 +84,10 @@ func TestTcpServer(t *testing.T) {
...
@@ -83,3 +84,10 @@ func TestTcpServer(t *testing.T) {
doTest
(
t
,
"tcp"
,
"0.0.0.0:9997"
,
"[::ffff:127.0.0.1]:9997"
);
doTest
(
t
,
"tcp"
,
"0.0.0.0:9997"
,
"[::ffff:127.0.0.1]:9997"
);
}
}
func
TestUnixServer
(
t
*
testing
.
T
)
{
doTest
(
t
,
"unix"
,
"/tmp/gotest.net"
,
"/tmp/gotest.net"
);
if
syscall
.
OS
==
"linux"
{
// Test abstract unix domain socket, a Linux-ism
doTest
(
t
,
"unix"
,
"@gotest/net"
,
"@gotest/net"
);
}
}
src/lib/os/error.go
View file @
cc1d4b7e
...
@@ -77,5 +77,7 @@ var (
...
@@ -77,5 +77,7 @@ var (
EAGAIN
Error
=
Errno
(
syscall
.
EAGAIN
);
EAGAIN
Error
=
Errno
(
syscall
.
EAGAIN
);
EDOM
Error
=
Errno
(
syscall
.
EDOM
);
EDOM
Error
=
Errno
(
syscall
.
EDOM
);
ERANGE
Error
=
Errno
(
syscall
.
ERANGE
);
ERANGE
Error
=
Errno
(
syscall
.
ERANGE
);
EADDRINUSE
Error
=
Errno
(
syscall
.
EADDRINUSE
);
ECONNREFUSED
Error
=
Errno
(
syscall
.
ECONNREFUSED
);
)
)
src/lib/syscall/socket_darwin.go
View file @
cc1d4b7e
...
@@ -16,11 +16,6 @@ import (
...
@@ -16,11 +16,6 @@ import (
// creation of IPv6 sockets to return EAFNOSUPPORT.
// creation of IPv6 sockets to return EAFNOSUPPORT.
var
SocketDisableIPv6
bool
var
SocketDisableIPv6
bool
func
SockaddrToSockaddrInet4
(
s
*
Sockaddr
)
*
SockaddrInet4
;
func
SockaddrToSockaddrInet6
(
s
*
Sockaddr
)
*
SockaddrInet6
;
func
SockaddrInet4ToSockaddr
(
s
*
SockaddrInet4
)
*
Sockaddr
;
func
SockaddrInet6ToSockaddr
(
s
*
SockaddrInet6
)
*
Sockaddr
;
func
Socket
(
domain
,
proto
,
typ
int64
)
(
ret
int64
,
err
int64
)
{
func
Socket
(
domain
,
proto
,
typ
int64
)
(
ret
int64
,
err
int64
)
{
if
domain
==
AF_INET6
&&
SocketDisableIPv6
{
if
domain
==
AF_INET6
&&
SocketDisableIPv6
{
return
-
1
,
EAFNOSUPPORT
return
-
1
,
EAFNOSUPPORT
...
...
src/lib/syscall/socket_linux.go
View file @
cc1d4b7e
...
@@ -16,11 +16,6 @@ import (
...
@@ -16,11 +16,6 @@ import (
// creation of IPv6 sockets to return EAFNOSUPPORT.
// creation of IPv6 sockets to return EAFNOSUPPORT.
var
SocketDisableIPv6
bool
var
SocketDisableIPv6
bool
func
SockaddrToSockaddrInet4
(
s
*
Sockaddr
)
*
SockaddrInet4
;
func
SockaddrToSockaddrInet6
(
s
*
Sockaddr
)
*
SockaddrInet6
;
func
SockaddrInet4ToSockaddr
(
s
*
SockaddrInet4
)
*
Sockaddr
;
func
SockaddrInet6ToSockaddr
(
s
*
SockaddrInet6
)
*
Sockaddr
;
func
saLen
(
s
*
Sockaddr
)
int64
{
func
saLen
(
s
*
Sockaddr
)
int64
{
switch
s
.
Family
{
switch
s
.
Family
{
case
AF_UNIX
:
case
AF_UNIX
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment