Source File
dial.go
Belonging Package
net
package net
import (
)
const (
defaultTCPKeepAlive = 15 * time.Second
)
Cancel <-chan struct{}
func ( *Dialer) ( context.Context, time.Time) ( time.Time) {
if .Timeout != 0 { // including negative, for historical reasons
= .Add(.Timeout)
}
if , := .Deadline(); {
= minNonzeroTime(, )
}
return minNonzeroTime(, .Deadline)
}
func ( *Dialer) () *Resolver {
if .Resolver != nil {
return .Resolver
}
return DefaultResolver
}
const = 2 * time.Second
if < {
if < {
=
} else {
=
}
}
return .Add(), nil
}
func ( *Dialer) () time.Duration {
if .FallbackDelay > 0 {
return .FallbackDelay
} else {
return 300 * time.Millisecond
}
}
func ( context.Context, string, bool) ( string, int, error) {
:= last(, ':')
if < 0 { // no colon
switch {
case "tcp", "tcp4", "tcp6":
case "udp", "udp4", "udp6":
case "ip", "ip4", "ip6":
if {
return "", 0, UnknownNetworkError()
}
case "unix", "unixgram", "unixpacket":
default:
return "", 0, UnknownNetworkError()
}
return , 0, nil
}
= [:]
switch {
case "ip", "ip4", "ip6":
:= [+1:]
, , := dtoi()
if ! || != len() {
, = lookupProtocol(, )
if != nil {
return "", 0,
}
}
return , , nil
}
return "", 0, UnknownNetworkError()
}
func ( *Resolver) ( context.Context, , , string, Addr) (addrList, error) {
, , := parseNetwork(, , true)
if != nil {
return nil,
}
if == "dial" && == "" {
return nil, errMissingAddress
}
switch {
case "unix", "unixgram", "unixpacket":
, := ResolveUnixAddr(, )
if != nil {
return nil,
}
if == "dial" && != nil && .Network() != .Network() {
return nil, &AddrError{Err: "mismatched local address type", Addr: .String()}
}
return addrList{}, nil
}
, := .internetAddrList(, , )
if != nil || != "dial" || == nil {
return ,
}
var (
*TCPAddr
*UDPAddr
*IPAddr
bool
)
switch hint := .(type) {
case *TCPAddr:
=
= .isWildcard()
case *UDPAddr:
=
= .isWildcard()
case *IPAddr:
=
= .isWildcard()
}
:= [:0]
for , := range {
if .Network() != .Network() {
return nil, &AddrError{Err: "mismatched local address type", Addr: .String()}
}
switch addr := .(type) {
case *TCPAddr:
if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
continue
}
= append(, )
case *UDPAddr:
if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
continue
}
= append(, )
case *IPAddr:
if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
continue
}
= append(, )
}
}
if len() == 0 {
return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: .String()}
}
return , nil
}
func ( *Dialer) (, string) (Conn, error) {
return .DialContext(context.Background(), , )
}
func ( *Dialer) ( context.Context, , string) (Conn, error) {
if == nil {
panic("nil context")
}
:= .deadline(, time.Now())
if !.IsZero() {
if , := .Deadline(); ! || .Before() {
, := context.WithDeadline(, )
defer ()
=
}
}
if := .Cancel; != nil {
, := context.WithCancel()
defer ()
go func() {
select {
case <-:
()
case <-.Done():
}
}()
=
}
:=
if , := .Value(nettrace.TraceKey{}).(*nettrace.Trace); != nil {
:= *
.ConnectStart = nil
.ConnectDone = nil
= context.WithValue(, nettrace.TraceKey{}, &)
}
, := .resolver().resolveAddrList(, "dial", , , .LocalAddr)
if != nil {
return nil, &OpError{Op: "dial", Net: , Source: nil, Addr: nil, Err: }
}
:= &sysDialer{
Dialer: *,
network: ,
address: ,
}
var , addrList
if .dualStack() && == "tcp" {
, = .partition(isIPv4)
} else {
=
}
var Conn
if len() > 0 {
, = .dialParallel(, , )
} else {
, = .dialSerial(, )
}
if != nil {
return nil,
}
if , := .(*TCPConn); && .KeepAlive >= 0 {
setKeepAlive(.fd, true)
:= .KeepAlive
if .KeepAlive == 0 {
= defaultTCPKeepAlive
}
setKeepAlivePeriod(.fd, )
testHookSetKeepAlive()
}
return , nil
}
func ( *sysDialer) ( context.Context, , addrList) (Conn, error) {
if len() == 0 {
return .dialSerial(, )
}
:= make(chan struct{})
defer close()
type struct {
Conn
error
bool
bool
}
:= make(chan ) // unbuffered
:= func( context.Context, bool) {
:=
if ! {
=
}
, := .dialSerial(, )
select {
case <- {: , : , : , : true}:
case <-:
if != nil {
.Close()
}
}
}
var ,
, := context.WithCancel()
defer ()
go (, true)
.Reset(0)
}
}
}
}
func ( *sysDialer) ( context.Context, addrList) (Conn, error) {
var error // The error from the first address is most relevant.
for , := range {
select {
case <-.Done():
return nil, &OpError{Op: "dial", Net: .network, Source: .LocalAddr, Addr: , Err: mapErr(.Err())}
default:
}
:=
if , := .Deadline(); {
, := partialDeadline(time.Now(), , len()-)
if == nil {
= &OpError{Op: "dial", Net: .network, Source: .LocalAddr, Addr: , Err: }
}
break
}
if .Before() {
var context.CancelFunc
, = context.WithDeadline(, )
defer ()
}
}
, := .dialSingle(, )
if == nil {
return , nil
}
if == nil {
=
}
}
if == nil {
= &OpError{Op: "dial", Net: .network, Source: nil, Addr: nil, Err: errMissingAddress}
}
return nil,
}
func ( *sysDialer) ( context.Context, Addr) ( Conn, error) {
, := .Value(nettrace.TraceKey{}).(*nettrace.Trace)
if != nil {
:= .String()
if .ConnectStart != nil {
.ConnectStart(.network, )
}
if .ConnectDone != nil {
defer func() { .ConnectDone(.network, , ) }()
}
}
:= .LocalAddr
switch ra := .(type) {
case *TCPAddr:
, := .(*TCPAddr)
, = .dialTCP(, , )
case *UDPAddr:
, := .(*UDPAddr)
, = .dialUDP(, , )
case *IPAddr:
, := .(*IPAddr)
, = .dialIP(, , )
case *UnixAddr:
, := .(*UnixAddr)
, = .dialUnix(, , )
default:
return nil, &OpError{Op: "dial", Net: .network, Source: , Addr: , Err: &AddrError{Err: "unexpected address type", Addr: .address}}
}
if != nil {
return nil, &OpError{Op: "dial", Net: .network, Source: , Addr: , Err: } // c is non-nil interface containing nil pointer
}
return , nil
}
func ( *ListenConfig) ( context.Context, , string) (Listener, error) {
, := DefaultResolver.resolveAddrList(, "listen", , , nil)
if != nil {
return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: nil, Err: }
}
:= &sysListener{
ListenConfig: *,
network: ,
address: ,
}
var Listener
:= .first(isIPv4)
switch la := .(type) {
case *TCPAddr:
, = .listenTCP(, )
case *UnixAddr:
, = .listenUnix(, )
default:
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: &AddrError{Err: "unexpected address type", Addr: }}
}
if != nil {
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: } // l is non-nil interface containing nil pointer
}
return , nil
}
func ( *ListenConfig) ( context.Context, , string) (PacketConn, error) {
, := DefaultResolver.resolveAddrList(, "listen", , , nil)
if != nil {
return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: nil, Err: }
}
:= &sysListener{
ListenConfig: *,
network: ,
address: ,
}
var PacketConn
:= .first(isIPv4)
switch la := .(type) {
case *UDPAddr:
, = .listenUDP(, )
case *IPAddr:
, = .listenIP(, )
case *UnixAddr:
, = .listenUnixgram(, )
default:
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: &AddrError{Err: "unexpected address type", Addr: }}
}
if != nil {
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: } // c is non-nil interface containing nil pointer
}
return , nil
}
type sysListener struct {
ListenConfig
network, address string
}
func (, string) (Listener, error) {
var ListenConfig
return .Listen(context.Background(), , )
}
func (, string) (PacketConn, error) {
var ListenConfig
return .ListenPacket(context.Background(), , )
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |