package net
import (
)
const (
readSyscallName = "read"
readFromSyscallName = "recvfrom"
readMsgSyscallName = "recvmsg"
writeSyscallName = "write"
writeToSyscallName = "sendto"
writeMsgSyscallName = "sendmsg"
)
func (, , int, string) (*netFD, error) {
:= &netFD{
pfd: poll.FD{
Sysfd: ,
IsStream: == syscall.SOCK_STREAM,
ZeroReadIsEOF: != syscall.SOCK_DGRAM && != syscall.SOCK_RAW,
},
family: ,
sotype: ,
net: ,
}
return , nil
}
func ( *netFD) () error {
return .pfd.Init(.net, true)
}
func ( *netFD) () string {
var , string
if .laddr != nil {
= .laddr.String()
}
if .raddr != nil {
= .raddr.String()
}
return .net + ":" + + "->" +
}
func ( *netFD) ( context.Context, , syscall.Sockaddr) ( syscall.Sockaddr, error) {
switch := connectFunc(.pfd.Sysfd, ); {
case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
case nil, syscall.EISCONN:
select {
case <-.Done():
return nil, mapErr(.Err())
default:
}
if := .pfd.Init(.net, true); != nil {
return nil,
}
runtime.KeepAlive()
return nil, nil
case syscall.EINVAL:
if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" {
return nil, nil
}
fallthrough
default:
return nil, os.NewSyscallError("connect", )
}
if := .pfd.Init(.net, true); != nil {
return nil,
}
if , := .Deadline(); {
.pfd.SetWriteDeadline()
defer .pfd.SetWriteDeadline(noDeadline)
}
if != context.Background() {
:= make(chan struct{})
:= make(chan error)
defer func() {
close()
if := <-; != nil && == nil {
= mapErr()
.Close()
}
}()
go func() {
select {
case <-.Done():
.pfd.SetWriteDeadline(aLongTimeAgo)
testHookCanceledDial()
<- .Err()
case <-:
<- nil
}
}()
}
for {
if := .pfd.WaitWrite(); != nil {
select {
case <-.Done():
return nil, mapErr(.Err())
default:
}
return nil,
}
, := getsockoptIntFunc(.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
if != nil {
return nil, os.NewSyscallError("getsockopt", )
}
switch := syscall.Errno(); {
case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
case syscall.EISCONN:
return nil, nil
case syscall.Errno(0):
if , := syscall.Getpeername(.pfd.Sysfd); == nil {
return , nil
}
default:
return nil, os.NewSyscallError("connect", )
}
runtime.KeepAlive()
}
}
func ( *netFD) () ( *netFD, error) {
, , , := .pfd.Accept()
if != nil {
if != "" {
= wrapSyscallError(, )
}
return nil,
}
if , = newFD(, .family, .sotype, .net); != nil {
poll.CloseFunc()
return nil,
}
if = .init(); != nil {
.Close()
return nil,
}
, := syscall.Getsockname(.pfd.Sysfd)
.setAddr(.addrFunc()(), .addrFunc()())
return , nil
}
func ( *netFD) () ( *os.File, error) {
, , := .pfd.Dup()
if != nil {
if != "" {
= os.NewSyscallError(, )
}
return nil,
}
return os.NewFile(uintptr(), .name()), nil
}