1 // Copyright 2010 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.
12 // A Dialer contains options for connecting to an address.
14 // The zero value for each field is equivalent to dialing
15 // without that option. Dialing with the zero value of Dialer
16 // is therefore equivalent to just calling the Dial function.
18 // Timeout is the maximum amount of time a dial will wait for
19 // a connect to complete. If Deadline is also set, it may fail
22 // The default is no timeout.
24 // With or without a timeout, the operating system may impose
25 // its own earlier timeout. For instance, TCP timeouts are
26 // often around 3 minutes.
29 // Deadline is the absolute point in time after which dials
30 // will fail. If Timeout is set, it may fail earlier.
31 // Zero means no deadline, or dependent on the operating system
32 // as with the Timeout option.
35 // LocalAddr is the local address to use when dialing an
36 // address. The address must be of a compatible type for the
37 // network being dialed.
38 // If nil, a local address is automatically chosen.
41 // DualStack allows a single dial to attempt to establish
42 // multiple IPv4 and IPv6 connections and to return the first
43 // established connection when the network is "tcp" and the
44 // destination is a host name that has multiple address family
48 // KeepAlive specifies the keep-alive period for an active
49 // network connection.
50 // If zero, keep-alives are not enabled. Network protocols
51 // that do not support keep-alives ignore this field.
52 KeepAlive time
.Duration
55 // Return either now+Timeout or Deadline, whichever comes first.
56 // Or zero, if neither is set.
57 func (d
*Dialer
) deadline() time
.Time
{
61 timeoutDeadline
:= time
.Now().Add(d
.Timeout
)
62 if d
.Deadline
.IsZero() || timeoutDeadline
.Before(d
.Deadline
) {
63 return timeoutDeadline
69 func parseNetwork(net
string) (afnet
string, proto
int, err error
) {
71 if i
< 0 { // no colon
73 case "tcp", "tcp4", "tcp6":
74 case "udp", "udp4", "udp6":
75 case "ip", "ip4", "ip6":
76 case "unix", "unixgram", "unixpacket":
78 return "", 0, UnknownNetworkError(net
)
84 case "ip", "ip4", "ip6":
86 proto
, i
, ok
:= dtoi(protostr
, 0)
87 if !ok || i
!= len(protostr
) {
88 proto
, err
= lookupProtocol(protostr
)
93 return afnet
, proto
, nil
95 return "", 0, UnknownNetworkError(net
)
98 func resolveAddr(op
, net
, addr
string, deadline time
.Time
) (netaddr
, error
) {
99 afnet
, _
, err
:= parseNetwork(net
)
103 if op
== "dial" && addr
== "" {
104 return nil, errMissingAddress
107 case "unix", "unixgram", "unixpacket":
108 return ResolveUnixAddr(afnet
, addr
)
110 return resolveInternetAddr(afnet
, addr
, deadline
)
113 // Dial connects to the address on the named network.
115 // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
116 // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
117 // (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
120 // For TCP and UDP networks, addresses have the form host:port.
121 // If host is a literal IPv6 address it must be enclosed
122 // in square brackets as in "[::1]:80" or "[ipv6-host%zone]:80".
123 // The functions JoinHostPort and SplitHostPort manipulate addresses
127 // Dial("tcp", "12.34.56.78:80")
128 // Dial("tcp", "google.com:http")
129 // Dial("tcp", "[2001:db8::1]:http")
130 // Dial("tcp", "[fe80::1%lo0]:80")
132 // For IP networks, the network must be "ip", "ip4" or "ip6" followed
133 // by a colon and a protocol number or name and the addr must be a
134 // literal IP address.
137 // Dial("ip4:1", "127.0.0.1")
138 // Dial("ip6:ospf", "::1")
140 // For Unix networks, the address must be a file system path.
141 func Dial(network
, address
string) (Conn
, error
) {
143 return d
.Dial(network
, address
)
146 // DialTimeout acts like Dial but takes a timeout.
147 // The timeout includes name resolution, if required.
148 func DialTimeout(network
, address
string, timeout time
.Duration
) (Conn
, error
) {
149 d
:= Dialer
{Timeout
: timeout
}
150 return d
.Dial(network
, address
)
153 // Dial connects to the address on the named network.
155 // See func Dial for a description of the network and address
157 func (d
*Dialer
) Dial(network
, address
string) (Conn
, error
) {
158 ra
, err
:= resolveAddr("dial", network
, address
, d
.deadline())
160 return nil, &OpError
{Op
: "dial", Net
: network
, Addr
: nil, Err
: err
}
162 dialer
:= func(deadline time
.Time
) (Conn
, error
) {
163 return dialSingle(network
, address
, d
.LocalAddr
, ra
.toAddr(), deadline
)
165 if ras
, ok
:= ra
.(addrList
); ok
&& d
.DualStack
&& network
== "tcp" {
166 dialer
= func(deadline time
.Time
) (Conn
, error
) {
167 return dialMulti(network
, address
, d
.LocalAddr
, ras
, deadline
)
170 c
, err
:= dial(network
, ra
.toAddr(), dialer
, d
.deadline())
171 if d
.KeepAlive
> 0 && err
== nil {
172 if tc
, ok
:= c
.(*TCPConn
); ok
{
173 tc
.SetKeepAlive(true)
174 tc
.SetKeepAlivePeriod(d
.KeepAlive
)
175 testHookSetKeepAlive()
181 var testHookSetKeepAlive
= func() {} // changed by dial_test.go
183 // dialMulti attempts to establish connections to each destination of
184 // the list of addresses. It will return the first established
185 // connection and close the other connections. Otherwise it returns
186 // error on the last attempt.
187 func dialMulti(net
, addr
string, la Addr
, ras addrList
, deadline time
.Time
) (Conn
, error
) {
192 // Sig controls the flow of dial results on lane. It passes a
193 // token to the next racer and also indicates the end of flow
194 // by using closed channel.
195 sig
:= make(chan bool, 1)
196 lane
:= make(chan racer
, 1)
197 for _
, ra
:= range ras
{
199 c
, err
:= dialSingle(net
, addr
, la
, ra
, deadline
)
200 if _
, ok
:= <-sig
; ok
{
201 lane
<- racer
{c
, err
}
202 } else if err
== nil {
203 // We have to return the resources
204 // that belong to the other
205 // connections here for avoiding
206 // unnecessary resource starvation.
212 lastErr
:= errTimeout
217 if racer
.error
== nil {
218 return racer
.Conn
, nil
220 lastErr
= racer
.error
226 // dialSingle attempts to establish and returns a single connection to
227 // the destination address.
228 func dialSingle(net
, addr
string, la
, ra Addr
, deadline time
.Time
) (c Conn
, err error
) {
229 if la
!= nil && la
.Network() != ra
.Network() {
230 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: ra
, Err
: errors
.New("mismatched local address type " + la
.Network())}
232 switch ra
:= ra
.(type) {
234 la
, _
:= la
.(*TCPAddr
)
235 c
, err
= dialTCP(net
, la
, ra
, deadline
)
237 la
, _
:= la
.(*UDPAddr
)
238 c
, err
= dialUDP(net
, la
, ra
, deadline
)
240 la
, _
:= la
.(*IPAddr
)
241 c
, err
= dialIP(net
, la
, ra
, deadline
)
243 la
, _
:= la
.(*UnixAddr
)
244 c
, err
= dialUnix(net
, la
, ra
, deadline
)
246 return nil, &OpError
{Op
: "dial", Net
: net
, Addr
: ra
, Err
: &AddrError
{Err
: "unexpected address type", Addr
: addr
}}
249 return nil, err
// c is non-nil interface containing nil pointer
254 // Listen announces on the local network address laddr.
255 // The network net must be a stream-oriented network: "tcp", "tcp4",
256 // "tcp6", "unix" or "unixpacket".
257 // See Dial for the syntax of laddr.
258 func Listen(net
, laddr
string) (Listener
, error
) {
259 la
, err
:= resolveAddr("listen", net
, laddr
, noDeadline
)
261 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: nil, Err
: err
}
264 switch la
:= la
.toAddr().(type) {
266 l
, err
= ListenTCP(net
, la
)
268 l
, err
= ListenUnix(net
, la
)
270 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: la
, Err
: &AddrError
{Err
: "unexpected address type", Addr
: laddr
}}
273 return nil, err
// l is non-nil interface containing nil pointer
278 // ListenPacket announces on the local network address laddr.
279 // The network net must be a packet-oriented network: "udp", "udp4",
280 // "udp6", "ip", "ip4", "ip6" or "unixgram".
281 // See Dial for the syntax of laddr.
282 func ListenPacket(net
, laddr
string) (PacketConn
, error
) {
283 la
, err
:= resolveAddr("listen", net
, laddr
, noDeadline
)
285 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: nil, Err
: err
}
288 switch la
:= la
.toAddr().(type) {
290 l
, err
= ListenUDP(net
, la
)
292 l
, err
= ListenIP(net
, la
)
294 l
, err
= ListenUnixgram(net
, la
)
296 return nil, &OpError
{Op
: "listen", Net
: net
, Addr
: la
, Err
: &AddrError
{Err
: "unexpected address type", Addr
: laddr
}}
299 return nil, err
// l is non-nil interface containing nil pointer