2019-11-11 10:37:46 +00:00
|
|
|
// +build !windows
|
|
|
|
|
2019-01-31 07:27:44 +00:00
|
|
|
package tcp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"runtime"
|
2019-11-10 11:42:55 +00:00
|
|
|
|
|
|
|
"golang.org/x/sys/unix"
|
2019-01-31 07:27:44 +00:00
|
|
|
)
|
|
|
|
|
2019-11-10 11:42:55 +00:00
|
|
|
// parseSockAddr resolves given addr to unix.Sockaddr
|
|
|
|
func parseSockAddr(addr string) (unix.Sockaddr, error) {
|
2019-01-31 07:27:44 +00:00
|
|
|
tAddr, err := net.ResolveTCPAddr("tcp", addr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
var addr4 [4]byte
|
|
|
|
if tAddr.IP != nil {
|
|
|
|
copy(addr4[:], tAddr.IP.To4()) // copy last 4 bytes of slice to array
|
|
|
|
}
|
2019-11-10 11:42:55 +00:00
|
|
|
return &unix.SockaddrInet4{Port: tAddr.Port, Addr: addr4}, nil
|
2019-01-31 07:27:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// connect calls the connect syscall with error handled.
|
2019-11-10 11:42:55 +00:00
|
|
|
func connect(fd int, addr unix.Sockaddr) (success bool, err error) {
|
2019-11-11 10:37:46 +00:00
|
|
|
// Connect() sends the actual SYN
|
2019-11-10 11:42:55 +00:00
|
|
|
switch serr := unix.Connect(fd, addr); serr {
|
|
|
|
case unix.EALREADY, unix.EINPROGRESS, unix.EINTR:
|
2019-01-31 07:27:44 +00:00
|
|
|
// Connection could not be made immediately but asynchronously.
|
|
|
|
success = false
|
|
|
|
err = nil
|
2019-11-10 11:42:55 +00:00
|
|
|
case nil, unix.EISCONN:
|
2019-01-31 07:27:44 +00:00
|
|
|
// The specified socket is already connected.
|
|
|
|
success = true
|
|
|
|
err = nil
|
2019-11-10 11:42:55 +00:00
|
|
|
case unix.EINVAL:
|
2019-01-31 07:27:44 +00:00
|
|
|
// On Solaris we can see EINVAL if the socket has
|
|
|
|
// already been accepted and closed by the server.
|
|
|
|
// Treat this as a successful connection--writes to
|
|
|
|
// the socket will see EOF. For details and a test
|
|
|
|
// case in C see https://golang.org/issue/6828.
|
|
|
|
if runtime.GOOS == "solaris" {
|
|
|
|
success = true
|
|
|
|
err = nil
|
|
|
|
} else {
|
|
|
|
// error must be reported
|
|
|
|
success = false
|
|
|
|
err = serr
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
// Connect error.
|
|
|
|
success = false
|
|
|
|
err = serr
|
|
|
|
}
|
|
|
|
return success, err
|
|
|
|
}
|