2010-06-21 20:52:30 -06:00
|
|
|
// Copyright 2010 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package net
|
|
|
|
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2013-04-02 14:24:16 -06:00
|
|
|
// A Dialer contains options for connecting to an address.
|
2013-03-09 19:14:00 -07:00
|
|
|
//
|
2013-04-02 14:24:16 -06:00
|
|
|
// The zero value for each field is equivalent to dialing
|
|
|
|
// without that option. Dialing with the zero value of Dialer
|
|
|
|
// is therefore equivalent to just calling the Dial function.
|
|
|
|
type Dialer struct {
|
|
|
|
// Timeout is the maximum amount of time a dial will wait for
|
|
|
|
// a connect to complete. If Deadline is also set, it may fail
|
|
|
|
// earlier.
|
|
|
|
//
|
|
|
|
// The default is no timeout.
|
|
|
|
//
|
|
|
|
// With or without a timeout, the operating system may impose
|
|
|
|
// its own earlier timeout. For instance, TCP timeouts are
|
|
|
|
// often around 3 minutes.
|
|
|
|
Timeout time.Duration
|
|
|
|
|
|
|
|
// Deadline is the absolute point in time after which dials
|
|
|
|
// will fail. If Timeout is set, it may fail earlier.
|
|
|
|
// Zero means no deadline, or dependent on the operating system
|
|
|
|
// as with the Timeout option.
|
|
|
|
Deadline time.Time
|
|
|
|
|
|
|
|
// LocalAddr is the local address to use when dialing an
|
|
|
|
// address. The address must be of a compatible type for the
|
|
|
|
// network being dialed.
|
|
|
|
// If nil, a local address is automatically chosen.
|
|
|
|
LocalAddr Addr
|
net: implement TCP connection setup with fast failover
This CL adds minimal support of Happy Eyeballs-like TCP connection
setup to Dialer API. Happy Eyeballs and derivation techniques are
described in the following:
- Happy Eyeballs: Success with Dual-Stack Hosts
http://tools.ietf.org/html/rfc6555
- Analysing Dual Stack Behaviour and IPv6 Quality
http://www.potaroo.net/presentations/2012-04-17-dual-stack-quality.pdf
Usually, the techniques consist of three components below.
- DNS query racers, that run A and AAAA queries in parallel or series
- A short list of destination addresses
- TCP SYN racers, that run IPv4 and IPv6 transport in parallel or series
This CL implements only the latter two. The existing DNS query
component gathers together A and AAAA records in series, so we don't
touch it here. This CL just uses extended resolveInternetAddr and makes
it possible to run multiple Dial racers in parallel.
For example, when the given destination is a DNS name and the name has
multiple address family A and AAAA records, and it happens on the TCP
wildcard network "tcp" with DualStack=true like the following:
(&net.Dialer{DualStack: true}).Dial("tcp", "www.example.com:80")
The function will return a first established connection either TCP over
IPv4 or TCP over IPv6, and close the other connection internally.
Fixes #3610.
Fixes #5267.
Benchmark results on freebsd/amd64 virtual machine, tip vs. tip+12416043:
benchmark old ns/op new ns/op delta
BenchmarkTCP4OneShot 50696 52141 +2.85%
BenchmarkTCP4OneShotTimeout 65775 66426 +0.99%
BenchmarkTCP4Persistent 10986 10457 -4.82%
BenchmarkTCP4PersistentTimeout 11207 10445 -6.80%
BenchmarkTCP6OneShot 62009 63718 +2.76%
BenchmarkTCP6OneShotTimeout 78351 79138 +1.00%
BenchmarkTCP6Persistent 14695 14659 -0.24%
BenchmarkTCP6PersistentTimeout 15032 14646 -2.57%
BenchmarkTCP4ConcurrentReadWrite 7215 6217 -13.83%
BenchmarkTCP6ConcurrentReadWrite 7528 7493 -0.46%
benchmark old allocs new allocs delta
BenchmarkTCP4OneShot 36 36 0.00%
BenchmarkTCP4OneShotTimeout 36 36 0.00%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 37 37 0.00%
BenchmarkTCP6OneShotTimeout 37 37 0.00%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
benchmark old bytes new bytes delta
BenchmarkTCP4OneShot 2500 2503 0.12%
BenchmarkTCP4OneShotTimeout 2508 2505 -0.12%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 2713 2707 -0.22%
BenchmarkTCP6OneShotTimeout 2722 2720 -0.07%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
R=golang-dev, bradfitz, nightlyone, rsc
CC=golang-dev
https://golang.org/cl/12416043
2013-09-11 08:48:53 -06:00
|
|
|
|
|
|
|
// DualStack allows a single dial to attempt to establish
|
|
|
|
// multiple IPv4 and IPv6 connections and to return the first
|
|
|
|
// established connection when the network is "tcp" and the
|
|
|
|
// destination is a host name that has multiple address family
|
|
|
|
// DNS records.
|
|
|
|
DualStack bool
|
2014-02-24 14:14:48 -07:00
|
|
|
|
|
|
|
// KeepAlive specifies the keep-alive period for an active
|
|
|
|
// network connection.
|
|
|
|
// If zero, keep-alives are not enabled. Network protocols
|
|
|
|
// that do not support keep-alives ignore this field.
|
|
|
|
KeepAlive time.Duration
|
2013-04-02 14:24:16 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return either now+Timeout or Deadline, whichever comes first.
|
|
|
|
// Or zero, if neither is set.
|
|
|
|
func (d *Dialer) deadline() time.Time {
|
|
|
|
if d.Timeout == 0 {
|
|
|
|
return d.Deadline
|
|
|
|
}
|
|
|
|
timeoutDeadline := time.Now().Add(d.Timeout)
|
|
|
|
if d.Deadline.IsZero() || timeoutDeadline.Before(d.Deadline) {
|
|
|
|
return timeoutDeadline
|
|
|
|
} else {
|
|
|
|
return d.Deadline
|
2013-03-09 19:14:00 -07:00
|
|
|
}
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
}
|
2011-12-20 14:17:39 -07:00
|
|
|
|
2013-02-08 05:53:10 -07:00
|
|
|
func parseNetwork(net string) (afnet string, proto int, err error) {
|
2012-01-21 05:51:53 -07:00
|
|
|
i := last(net, ':')
|
|
|
|
if i < 0 { // no colon
|
|
|
|
switch net {
|
|
|
|
case "tcp", "tcp4", "tcp6":
|
|
|
|
case "udp", "udp4", "udp6":
|
2012-11-27 14:36:05 -07:00
|
|
|
case "ip", "ip4", "ip6":
|
2012-01-21 05:51:53 -07:00
|
|
|
case "unix", "unixgram", "unixpacket":
|
|
|
|
default:
|
|
|
|
return "", 0, UnknownNetworkError(net)
|
|
|
|
}
|
|
|
|
return net, 0, nil
|
2011-06-29 22:56:13 -06:00
|
|
|
}
|
2012-01-21 05:51:53 -07:00
|
|
|
afnet = net[:i]
|
|
|
|
switch afnet {
|
2011-06-29 22:56:13 -06:00
|
|
|
case "ip", "ip4", "ip6":
|
2012-01-21 05:51:53 -07:00
|
|
|
protostr := net[i+1:]
|
|
|
|
proto, i, ok := dtoi(protostr, 0)
|
|
|
|
if !ok || i != len(protostr) {
|
|
|
|
proto, err = lookupProtocol(protostr)
|
|
|
|
if err != nil {
|
|
|
|
return "", 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return afnet, proto, nil
|
2011-06-29 22:56:13 -06:00
|
|
|
}
|
2012-01-21 05:51:53 -07:00
|
|
|
return "", 0, UnknownNetworkError(net)
|
|
|
|
}
|
|
|
|
|
2013-08-29 18:09:45 -06:00
|
|
|
func resolveAddr(op, net, addr string, deadline time.Time) (netaddr, error) {
|
2013-02-08 05:53:10 -07:00
|
|
|
afnet, _, err := parseNetwork(net)
|
2011-06-29 22:56:13 -06:00
|
|
|
if err != nil {
|
2013-08-13 16:04:39 -06:00
|
|
|
return nil, err
|
2012-01-21 05:51:53 -07:00
|
|
|
}
|
|
|
|
if op == "dial" && addr == "" {
|
2013-08-13 16:04:39 -06:00
|
|
|
return nil, errMissingAddress
|
2012-11-08 09:35:16 -07:00
|
|
|
}
|
2012-01-21 05:51:53 -07:00
|
|
|
switch afnet {
|
|
|
|
case "unix", "unixgram", "unixpacket":
|
2012-11-08 09:35:16 -07:00
|
|
|
return ResolveUnixAddr(afnet, addr)
|
2011-06-29 22:56:13 -06:00
|
|
|
}
|
2013-02-08 05:53:10 -07:00
|
|
|
return resolveInternetAddr(afnet, addr, deadline)
|
2011-06-29 22:56:13 -06:00
|
|
|
}
|
|
|
|
|
2013-04-02 14:24:16 -06:00
|
|
|
// Dial connects to the address on the named network.
|
2010-06-21 20:52:30 -06:00
|
|
|
//
|
|
|
|
// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
|
|
|
|
// "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
|
2013-02-08 16:18:32 -07:00
|
|
|
// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
|
|
|
|
// "unixpacket".
|
2010-06-21 20:52:30 -06:00
|
|
|
//
|
2012-01-21 05:51:53 -07:00
|
|
|
// For TCP and UDP networks, addresses have the form host:port.
|
2014-08-01 22:35:03 -06:00
|
|
|
// If host is a literal IPv6 address it must be enclosed
|
|
|
|
// in square brackets as in "[::1]:80" or "[ipv6-host%zone]:80".
|
net: support IPv6 scoped addressing zone
This CL provides IPv6 scoped addressing zone support as defined
in RFC 4007 for internet protocol family connection setups.
Follwoing types and functions allow a literal IPv6 address with
zone identifer as theirs parameter.
pkg net, func Dial(string, string) (Conn, error)
pkg net, func DialOpt(string, ...DialOption) (Conn, error)
pkg net, func DialTimeout(string, string, time.Duration) (Conn, error)
pkg net, func Listen(string, string) (Listener, error)
pkg net, func ListenPacket(string, string) (PacketConn, error)
pkg net, func ResolveIPAddr(string, string) (*IPAddr, error)
pkg net, func ResolveTCPAddr(string, string) (*TCPAddr, error)
pkg net, func ResolveUDPAddr(string, string) (*UDPAddr, error)
pkg net, type IPAddr struct, Zone string
pkg net, type TCPAddr struct, Zone string
pkg net, type UDPAddr struct, Zone string
Also follwoing methods return a literal IPv6 address with zone
identifier string if possible.
pkg net, method (*IPAddr) String() string
pkg net, method (*TCPAddr) String() string
pkg net, method (*UDPAddr) String() string
Fixes #4234.
Fixes #4501.
Update #5081.
R=rsc, iant
CC=golang-dev
https://golang.org/cl/6816116
2013-03-22 18:57:40 -06:00
|
|
|
// The functions JoinHostPort and SplitHostPort manipulate addresses
|
|
|
|
// in this form.
|
2010-06-21 20:52:30 -06:00
|
|
|
//
|
|
|
|
// Examples:
|
2011-03-28 21:28:42 -06:00
|
|
|
// Dial("tcp", "12.34.56.78:80")
|
net: support IPv6 scoped addressing zone
This CL provides IPv6 scoped addressing zone support as defined
in RFC 4007 for internet protocol family connection setups.
Follwoing types and functions allow a literal IPv6 address with
zone identifer as theirs parameter.
pkg net, func Dial(string, string) (Conn, error)
pkg net, func DialOpt(string, ...DialOption) (Conn, error)
pkg net, func DialTimeout(string, string, time.Duration) (Conn, error)
pkg net, func Listen(string, string) (Listener, error)
pkg net, func ListenPacket(string, string) (PacketConn, error)
pkg net, func ResolveIPAddr(string, string) (*IPAddr, error)
pkg net, func ResolveTCPAddr(string, string) (*TCPAddr, error)
pkg net, func ResolveUDPAddr(string, string) (*UDPAddr, error)
pkg net, type IPAddr struct, Zone string
pkg net, type TCPAddr struct, Zone string
pkg net, type UDPAddr struct, Zone string
Also follwoing methods return a literal IPv6 address with zone
identifier string if possible.
pkg net, method (*IPAddr) String() string
pkg net, method (*TCPAddr) String() string
pkg net, method (*UDPAddr) String() string
Fixes #4234.
Fixes #4501.
Update #5081.
R=rsc, iant
CC=golang-dev
https://golang.org/cl/6816116
2013-03-22 18:57:40 -06:00
|
|
|
// Dial("tcp", "google.com:http")
|
|
|
|
// Dial("tcp", "[2001:db8::1]:http")
|
|
|
|
// Dial("tcp", "[fe80::1%lo0]:80")
|
2010-06-21 20:52:30 -06:00
|
|
|
//
|
2013-04-02 14:24:16 -06:00
|
|
|
// For IP networks, the network must be "ip", "ip4" or "ip6" followed
|
|
|
|
// by a colon and a protocol number or name and the addr must be a
|
|
|
|
// literal IP address.
|
2012-01-21 05:51:53 -07:00
|
|
|
//
|
|
|
|
// Examples:
|
|
|
|
// Dial("ip4:1", "127.0.0.1")
|
|
|
|
// Dial("ip6:ospf", "::1")
|
|
|
|
//
|
2013-04-02 14:24:16 -06:00
|
|
|
// For Unix networks, the address must be a file system path.
|
|
|
|
func Dial(network, address string) (Conn, error) {
|
|
|
|
var d Dialer
|
|
|
|
return d.Dial(network, address)
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
}
|
|
|
|
|
2013-04-02 14:24:16 -06:00
|
|
|
// DialTimeout acts like Dial but takes a timeout.
|
|
|
|
// The timeout includes name resolution, if required.
|
|
|
|
func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
|
|
|
|
d := Dialer{Timeout: timeout}
|
|
|
|
return d.Dial(network, address)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dial connects to the address on the named network.
|
|
|
|
//
|
|
|
|
// See func Dial for a description of the network and address
|
|
|
|
// parameters.
|
|
|
|
func (d *Dialer) Dial(network, address string) (Conn, error) {
|
net: implement TCP connection setup with fast failover
This CL adds minimal support of Happy Eyeballs-like TCP connection
setup to Dialer API. Happy Eyeballs and derivation techniques are
described in the following:
- Happy Eyeballs: Success with Dual-Stack Hosts
http://tools.ietf.org/html/rfc6555
- Analysing Dual Stack Behaviour and IPv6 Quality
http://www.potaroo.net/presentations/2012-04-17-dual-stack-quality.pdf
Usually, the techniques consist of three components below.
- DNS query racers, that run A and AAAA queries in parallel or series
- A short list of destination addresses
- TCP SYN racers, that run IPv4 and IPv6 transport in parallel or series
This CL implements only the latter two. The existing DNS query
component gathers together A and AAAA records in series, so we don't
touch it here. This CL just uses extended resolveInternetAddr and makes
it possible to run multiple Dial racers in parallel.
For example, when the given destination is a DNS name and the name has
multiple address family A and AAAA records, and it happens on the TCP
wildcard network "tcp" with DualStack=true like the following:
(&net.Dialer{DualStack: true}).Dial("tcp", "www.example.com:80")
The function will return a first established connection either TCP over
IPv4 or TCP over IPv6, and close the other connection internally.
Fixes #3610.
Fixes #5267.
Benchmark results on freebsd/amd64 virtual machine, tip vs. tip+12416043:
benchmark old ns/op new ns/op delta
BenchmarkTCP4OneShot 50696 52141 +2.85%
BenchmarkTCP4OneShotTimeout 65775 66426 +0.99%
BenchmarkTCP4Persistent 10986 10457 -4.82%
BenchmarkTCP4PersistentTimeout 11207 10445 -6.80%
BenchmarkTCP6OneShot 62009 63718 +2.76%
BenchmarkTCP6OneShotTimeout 78351 79138 +1.00%
BenchmarkTCP6Persistent 14695 14659 -0.24%
BenchmarkTCP6PersistentTimeout 15032 14646 -2.57%
BenchmarkTCP4ConcurrentReadWrite 7215 6217 -13.83%
BenchmarkTCP6ConcurrentReadWrite 7528 7493 -0.46%
benchmark old allocs new allocs delta
BenchmarkTCP4OneShot 36 36 0.00%
BenchmarkTCP4OneShotTimeout 36 36 0.00%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 37 37 0.00%
BenchmarkTCP6OneShotTimeout 37 37 0.00%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
benchmark old bytes new bytes delta
BenchmarkTCP4OneShot 2500 2503 0.12%
BenchmarkTCP4OneShotTimeout 2508 2505 -0.12%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 2713 2707 -0.22%
BenchmarkTCP6OneShotTimeout 2722 2720 -0.07%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
R=golang-dev, bradfitz, nightlyone, rsc
CC=golang-dev
https://golang.org/cl/12416043
2013-09-11 08:48:53 -06:00
|
|
|
ra, err := resolveAddr("dial", network, address, d.deadline())
|
|
|
|
if err != nil {
|
|
|
|
return nil, &OpError{Op: "dial", Net: network, Addr: nil, Err: err}
|
|
|
|
}
|
|
|
|
dialer := func(deadline time.Time) (Conn, error) {
|
|
|
|
return dialSingle(network, address, d.LocalAddr, ra.toAddr(), deadline)
|
|
|
|
}
|
|
|
|
if ras, ok := ra.(addrList); ok && d.DualStack && network == "tcp" {
|
|
|
|
dialer = func(deadline time.Time) (Conn, error) {
|
|
|
|
return dialMulti(network, address, d.LocalAddr, ras, deadline)
|
|
|
|
}
|
|
|
|
}
|
2014-02-24 14:14:48 -07:00
|
|
|
c, err := dial(network, ra.toAddr(), dialer, d.deadline())
|
|
|
|
if d.KeepAlive > 0 && err == nil {
|
|
|
|
if tc, ok := c.(*TCPConn); ok {
|
|
|
|
tc.SetKeepAlive(true)
|
|
|
|
tc.SetKeepAlivePeriod(d.KeepAlive)
|
|
|
|
testHookSetKeepAlive()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return c, err
|
2011-12-20 14:17:39 -07:00
|
|
|
}
|
|
|
|
|
2014-02-24 14:14:48 -07:00
|
|
|
var testHookSetKeepAlive = func() {} // changed by dial_test.go
|
|
|
|
|
net: implement TCP connection setup with fast failover
This CL adds minimal support of Happy Eyeballs-like TCP connection
setup to Dialer API. Happy Eyeballs and derivation techniques are
described in the following:
- Happy Eyeballs: Success with Dual-Stack Hosts
http://tools.ietf.org/html/rfc6555
- Analysing Dual Stack Behaviour and IPv6 Quality
http://www.potaroo.net/presentations/2012-04-17-dual-stack-quality.pdf
Usually, the techniques consist of three components below.
- DNS query racers, that run A and AAAA queries in parallel or series
- A short list of destination addresses
- TCP SYN racers, that run IPv4 and IPv6 transport in parallel or series
This CL implements only the latter two. The existing DNS query
component gathers together A and AAAA records in series, so we don't
touch it here. This CL just uses extended resolveInternetAddr and makes
it possible to run multiple Dial racers in parallel.
For example, when the given destination is a DNS name and the name has
multiple address family A and AAAA records, and it happens on the TCP
wildcard network "tcp" with DualStack=true like the following:
(&net.Dialer{DualStack: true}).Dial("tcp", "www.example.com:80")
The function will return a first established connection either TCP over
IPv4 or TCP over IPv6, and close the other connection internally.
Fixes #3610.
Fixes #5267.
Benchmark results on freebsd/amd64 virtual machine, tip vs. tip+12416043:
benchmark old ns/op new ns/op delta
BenchmarkTCP4OneShot 50696 52141 +2.85%
BenchmarkTCP4OneShotTimeout 65775 66426 +0.99%
BenchmarkTCP4Persistent 10986 10457 -4.82%
BenchmarkTCP4PersistentTimeout 11207 10445 -6.80%
BenchmarkTCP6OneShot 62009 63718 +2.76%
BenchmarkTCP6OneShotTimeout 78351 79138 +1.00%
BenchmarkTCP6Persistent 14695 14659 -0.24%
BenchmarkTCP6PersistentTimeout 15032 14646 -2.57%
BenchmarkTCP4ConcurrentReadWrite 7215 6217 -13.83%
BenchmarkTCP6ConcurrentReadWrite 7528 7493 -0.46%
benchmark old allocs new allocs delta
BenchmarkTCP4OneShot 36 36 0.00%
BenchmarkTCP4OneShotTimeout 36 36 0.00%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 37 37 0.00%
BenchmarkTCP6OneShotTimeout 37 37 0.00%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
benchmark old bytes new bytes delta
BenchmarkTCP4OneShot 2500 2503 0.12%
BenchmarkTCP4OneShotTimeout 2508 2505 -0.12%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 2713 2707 -0.22%
BenchmarkTCP6OneShotTimeout 2722 2720 -0.07%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
R=golang-dev, bradfitz, nightlyone, rsc
CC=golang-dev
https://golang.org/cl/12416043
2013-09-11 08:48:53 -06:00
|
|
|
// dialMulti attempts to establish connections to each destination of
|
|
|
|
// the list of addresses. It will return the first established
|
|
|
|
// connection and close the other connections. Otherwise it returns
|
|
|
|
// error on the last attempt.
|
|
|
|
func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Conn, error) {
|
|
|
|
type racer struct {
|
|
|
|
Conn
|
|
|
|
error
|
|
|
|
}
|
|
|
|
// Sig controls the flow of dial results on lane. It passes a
|
|
|
|
// token to the next racer and also indicates the end of flow
|
|
|
|
// by using closed channel.
|
|
|
|
sig := make(chan bool, 1)
|
|
|
|
lane := make(chan racer, 1)
|
|
|
|
for _, ra := range ras {
|
|
|
|
go func(ra Addr) {
|
|
|
|
c, err := dialSingle(net, addr, la, ra, deadline)
|
|
|
|
if _, ok := <-sig; ok {
|
2013-12-18 18:00:15 -07:00
|
|
|
lane <- racer{c, err}
|
net: implement TCP connection setup with fast failover
This CL adds minimal support of Happy Eyeballs-like TCP connection
setup to Dialer API. Happy Eyeballs and derivation techniques are
described in the following:
- Happy Eyeballs: Success with Dual-Stack Hosts
http://tools.ietf.org/html/rfc6555
- Analysing Dual Stack Behaviour and IPv6 Quality
http://www.potaroo.net/presentations/2012-04-17-dual-stack-quality.pdf
Usually, the techniques consist of three components below.
- DNS query racers, that run A and AAAA queries in parallel or series
- A short list of destination addresses
- TCP SYN racers, that run IPv4 and IPv6 transport in parallel or series
This CL implements only the latter two. The existing DNS query
component gathers together A and AAAA records in series, so we don't
touch it here. This CL just uses extended resolveInternetAddr and makes
it possible to run multiple Dial racers in parallel.
For example, when the given destination is a DNS name and the name has
multiple address family A and AAAA records, and it happens on the TCP
wildcard network "tcp" with DualStack=true like the following:
(&net.Dialer{DualStack: true}).Dial("tcp", "www.example.com:80")
The function will return a first established connection either TCP over
IPv4 or TCP over IPv6, and close the other connection internally.
Fixes #3610.
Fixes #5267.
Benchmark results on freebsd/amd64 virtual machine, tip vs. tip+12416043:
benchmark old ns/op new ns/op delta
BenchmarkTCP4OneShot 50696 52141 +2.85%
BenchmarkTCP4OneShotTimeout 65775 66426 +0.99%
BenchmarkTCP4Persistent 10986 10457 -4.82%
BenchmarkTCP4PersistentTimeout 11207 10445 -6.80%
BenchmarkTCP6OneShot 62009 63718 +2.76%
BenchmarkTCP6OneShotTimeout 78351 79138 +1.00%
BenchmarkTCP6Persistent 14695 14659 -0.24%
BenchmarkTCP6PersistentTimeout 15032 14646 -2.57%
BenchmarkTCP4ConcurrentReadWrite 7215 6217 -13.83%
BenchmarkTCP6ConcurrentReadWrite 7528 7493 -0.46%
benchmark old allocs new allocs delta
BenchmarkTCP4OneShot 36 36 0.00%
BenchmarkTCP4OneShotTimeout 36 36 0.00%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 37 37 0.00%
BenchmarkTCP6OneShotTimeout 37 37 0.00%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
benchmark old bytes new bytes delta
BenchmarkTCP4OneShot 2500 2503 0.12%
BenchmarkTCP4OneShotTimeout 2508 2505 -0.12%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 2713 2707 -0.22%
BenchmarkTCP6OneShotTimeout 2722 2720 -0.07%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
R=golang-dev, bradfitz, nightlyone, rsc
CC=golang-dev
https://golang.org/cl/12416043
2013-09-11 08:48:53 -06:00
|
|
|
} else if err == nil {
|
|
|
|
// We have to return the resources
|
|
|
|
// that belong to the other
|
|
|
|
// connections here for avoiding
|
|
|
|
// unnecessary resource starvation.
|
|
|
|
c.Close()
|
|
|
|
}
|
|
|
|
}(ra.toAddr())
|
|
|
|
}
|
|
|
|
defer close(sig)
|
|
|
|
lastErr := errTimeout
|
|
|
|
nracers := len(ras)
|
|
|
|
for nracers > 0 {
|
|
|
|
sig <- true
|
2014-06-19 23:04:37 -06:00
|
|
|
racer := <-lane
|
|
|
|
if racer.error == nil {
|
|
|
|
return racer.Conn, nil
|
net: implement TCP connection setup with fast failover
This CL adds minimal support of Happy Eyeballs-like TCP connection
setup to Dialer API. Happy Eyeballs and derivation techniques are
described in the following:
- Happy Eyeballs: Success with Dual-Stack Hosts
http://tools.ietf.org/html/rfc6555
- Analysing Dual Stack Behaviour and IPv6 Quality
http://www.potaroo.net/presentations/2012-04-17-dual-stack-quality.pdf
Usually, the techniques consist of three components below.
- DNS query racers, that run A and AAAA queries in parallel or series
- A short list of destination addresses
- TCP SYN racers, that run IPv4 and IPv6 transport in parallel or series
This CL implements only the latter two. The existing DNS query
component gathers together A and AAAA records in series, so we don't
touch it here. This CL just uses extended resolveInternetAddr and makes
it possible to run multiple Dial racers in parallel.
For example, when the given destination is a DNS name and the name has
multiple address family A and AAAA records, and it happens on the TCP
wildcard network "tcp" with DualStack=true like the following:
(&net.Dialer{DualStack: true}).Dial("tcp", "www.example.com:80")
The function will return a first established connection either TCP over
IPv4 or TCP over IPv6, and close the other connection internally.
Fixes #3610.
Fixes #5267.
Benchmark results on freebsd/amd64 virtual machine, tip vs. tip+12416043:
benchmark old ns/op new ns/op delta
BenchmarkTCP4OneShot 50696 52141 +2.85%
BenchmarkTCP4OneShotTimeout 65775 66426 +0.99%
BenchmarkTCP4Persistent 10986 10457 -4.82%
BenchmarkTCP4PersistentTimeout 11207 10445 -6.80%
BenchmarkTCP6OneShot 62009 63718 +2.76%
BenchmarkTCP6OneShotTimeout 78351 79138 +1.00%
BenchmarkTCP6Persistent 14695 14659 -0.24%
BenchmarkTCP6PersistentTimeout 15032 14646 -2.57%
BenchmarkTCP4ConcurrentReadWrite 7215 6217 -13.83%
BenchmarkTCP6ConcurrentReadWrite 7528 7493 -0.46%
benchmark old allocs new allocs delta
BenchmarkTCP4OneShot 36 36 0.00%
BenchmarkTCP4OneShotTimeout 36 36 0.00%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 37 37 0.00%
BenchmarkTCP6OneShotTimeout 37 37 0.00%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
benchmark old bytes new bytes delta
BenchmarkTCP4OneShot 2500 2503 0.12%
BenchmarkTCP4OneShotTimeout 2508 2505 -0.12%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 2713 2707 -0.22%
BenchmarkTCP6OneShotTimeout 2722 2720 -0.07%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
R=golang-dev, bradfitz, nightlyone, rsc
CC=golang-dev
https://golang.org/cl/12416043
2013-09-11 08:48:53 -06:00
|
|
|
}
|
2014-06-19 23:04:37 -06:00
|
|
|
lastErr = racer.error
|
|
|
|
nracers--
|
net: implement TCP connection setup with fast failover
This CL adds minimal support of Happy Eyeballs-like TCP connection
setup to Dialer API. Happy Eyeballs and derivation techniques are
described in the following:
- Happy Eyeballs: Success with Dual-Stack Hosts
http://tools.ietf.org/html/rfc6555
- Analysing Dual Stack Behaviour and IPv6 Quality
http://www.potaroo.net/presentations/2012-04-17-dual-stack-quality.pdf
Usually, the techniques consist of three components below.
- DNS query racers, that run A and AAAA queries in parallel or series
- A short list of destination addresses
- TCP SYN racers, that run IPv4 and IPv6 transport in parallel or series
This CL implements only the latter two. The existing DNS query
component gathers together A and AAAA records in series, so we don't
touch it here. This CL just uses extended resolveInternetAddr and makes
it possible to run multiple Dial racers in parallel.
For example, when the given destination is a DNS name and the name has
multiple address family A and AAAA records, and it happens on the TCP
wildcard network "tcp" with DualStack=true like the following:
(&net.Dialer{DualStack: true}).Dial("tcp", "www.example.com:80")
The function will return a first established connection either TCP over
IPv4 or TCP over IPv6, and close the other connection internally.
Fixes #3610.
Fixes #5267.
Benchmark results on freebsd/amd64 virtual machine, tip vs. tip+12416043:
benchmark old ns/op new ns/op delta
BenchmarkTCP4OneShot 50696 52141 +2.85%
BenchmarkTCP4OneShotTimeout 65775 66426 +0.99%
BenchmarkTCP4Persistent 10986 10457 -4.82%
BenchmarkTCP4PersistentTimeout 11207 10445 -6.80%
BenchmarkTCP6OneShot 62009 63718 +2.76%
BenchmarkTCP6OneShotTimeout 78351 79138 +1.00%
BenchmarkTCP6Persistent 14695 14659 -0.24%
BenchmarkTCP6PersistentTimeout 15032 14646 -2.57%
BenchmarkTCP4ConcurrentReadWrite 7215 6217 -13.83%
BenchmarkTCP6ConcurrentReadWrite 7528 7493 -0.46%
benchmark old allocs new allocs delta
BenchmarkTCP4OneShot 36 36 0.00%
BenchmarkTCP4OneShotTimeout 36 36 0.00%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 37 37 0.00%
BenchmarkTCP6OneShotTimeout 37 37 0.00%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
benchmark old bytes new bytes delta
BenchmarkTCP4OneShot 2500 2503 0.12%
BenchmarkTCP4OneShotTimeout 2508 2505 -0.12%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 2713 2707 -0.22%
BenchmarkTCP6OneShotTimeout 2722 2720 -0.07%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
R=golang-dev, bradfitz, nightlyone, rsc
CC=golang-dev
https://golang.org/cl/12416043
2013-09-11 08:48:53 -06:00
|
|
|
}
|
2013-12-18 18:00:15 -07:00
|
|
|
return nil, lastErr
|
net: implement TCP connection setup with fast failover
This CL adds minimal support of Happy Eyeballs-like TCP connection
setup to Dialer API. Happy Eyeballs and derivation techniques are
described in the following:
- Happy Eyeballs: Success with Dual-Stack Hosts
http://tools.ietf.org/html/rfc6555
- Analysing Dual Stack Behaviour and IPv6 Quality
http://www.potaroo.net/presentations/2012-04-17-dual-stack-quality.pdf
Usually, the techniques consist of three components below.
- DNS query racers, that run A and AAAA queries in parallel or series
- A short list of destination addresses
- TCP SYN racers, that run IPv4 and IPv6 transport in parallel or series
This CL implements only the latter two. The existing DNS query
component gathers together A and AAAA records in series, so we don't
touch it here. This CL just uses extended resolveInternetAddr and makes
it possible to run multiple Dial racers in parallel.
For example, when the given destination is a DNS name and the name has
multiple address family A and AAAA records, and it happens on the TCP
wildcard network "tcp" with DualStack=true like the following:
(&net.Dialer{DualStack: true}).Dial("tcp", "www.example.com:80")
The function will return a first established connection either TCP over
IPv4 or TCP over IPv6, and close the other connection internally.
Fixes #3610.
Fixes #5267.
Benchmark results on freebsd/amd64 virtual machine, tip vs. tip+12416043:
benchmark old ns/op new ns/op delta
BenchmarkTCP4OneShot 50696 52141 +2.85%
BenchmarkTCP4OneShotTimeout 65775 66426 +0.99%
BenchmarkTCP4Persistent 10986 10457 -4.82%
BenchmarkTCP4PersistentTimeout 11207 10445 -6.80%
BenchmarkTCP6OneShot 62009 63718 +2.76%
BenchmarkTCP6OneShotTimeout 78351 79138 +1.00%
BenchmarkTCP6Persistent 14695 14659 -0.24%
BenchmarkTCP6PersistentTimeout 15032 14646 -2.57%
BenchmarkTCP4ConcurrentReadWrite 7215 6217 -13.83%
BenchmarkTCP6ConcurrentReadWrite 7528 7493 -0.46%
benchmark old allocs new allocs delta
BenchmarkTCP4OneShot 36 36 0.00%
BenchmarkTCP4OneShotTimeout 36 36 0.00%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 37 37 0.00%
BenchmarkTCP6OneShotTimeout 37 37 0.00%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
benchmark old bytes new bytes delta
BenchmarkTCP4OneShot 2500 2503 0.12%
BenchmarkTCP4OneShotTimeout 2508 2505 -0.12%
BenchmarkTCP4Persistent 0 0 n/a%
BenchmarkTCP4PersistentTimeout 0 0 n/a%
BenchmarkTCP6OneShot 2713 2707 -0.22%
BenchmarkTCP6OneShotTimeout 2722 2720 -0.07%
BenchmarkTCP6Persistent 0 0 n/a%
BenchmarkTCP6PersistentTimeout 0 0 n/a%
BenchmarkTCP4ConcurrentReadWrite 0 0 n/a%
BenchmarkTCP6ConcurrentReadWrite 0 0 n/a%
R=golang-dev, bradfitz, nightlyone, rsc
CC=golang-dev
https://golang.org/cl/12416043
2013-09-11 08:48:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// dialSingle attempts to establish and returns a single connection to
|
|
|
|
// the destination address.
|
2013-10-18 13:35:45 -06:00
|
|
|
func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
if la != nil && la.Network() != ra.Network() {
|
2013-08-13 16:04:39 -06:00
|
|
|
return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
}
|
2013-02-08 05:53:10 -07:00
|
|
|
switch ra := ra.(type) {
|
2011-06-29 22:56:13 -06:00
|
|
|
case *TCPAddr:
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
la, _ := la.(*TCPAddr)
|
2013-10-18 13:35:45 -06:00
|
|
|
c, err = dialTCP(net, la, ra, deadline)
|
2011-06-29 22:56:13 -06:00
|
|
|
case *UDPAddr:
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
la, _ := la.(*UDPAddr)
|
2013-10-18 13:35:45 -06:00
|
|
|
c, err = dialUDP(net, la, ra, deadline)
|
2011-06-29 22:56:13 -06:00
|
|
|
case *IPAddr:
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
la, _ := la.(*IPAddr)
|
2013-10-18 13:35:45 -06:00
|
|
|
c, err = dialIP(net, la, ra, deadline)
|
2012-01-21 05:51:53 -07:00
|
|
|
case *UnixAddr:
|
net: add DialOpt, the extensible Dial w/ options dialer
Add DialOpt. So we have:
func Dial(net, addr string) (Conn, error)
func DialTimeout(net, addr string, timeout time.Duration) (Conn, error)
func DialOpt(addr string, opts ...DialOption) (Conn, error)
DialTimeout (and Dial) are regrettable in retrospect. Maybe
in a future Go we'll be back down to one Dial, with DialOpt
becoming Dial.
DialOpt looks like:
c, err := net.DialOpt("google.com:80") // tcp is default
c, err := net.DialOpt("google.com:80", net.Timeout(30 * time.Second))
c, err := net.DialOpt("google.com:80", net.TCPFastOpen())
c, err := net.DialOpt("google.com:80", net.LocalAddr(..))
c, err := net.DialOpt("google.com:53", net.Network("udp6"))
And then: (clustered in godoc)
type DialOption interface { /* private only */ }
func Deadline(time.Time) DialOption
func LocalAddr(Addr) DialOption
func Network(string) DialOption
func TCPFastOpen() DialOption
func Timeout(time.Duration) DialOption
I'm pretty confident we could add Happy Eyeballs to this too.
Fixes #3097
Update #3610
Update #4842
R=golang-dev, r, dave, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7365049
2013-02-27 12:59:36 -07:00
|
|
|
la, _ := la.(*UnixAddr)
|
2013-10-18 13:35:45 -06:00
|
|
|
c, err = dialUnix(net, la, ra, deadline)
|
2011-06-29 22:56:13 -06:00
|
|
|
default:
|
2013-08-14 14:53:53 -06:00
|
|
|
return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
|
2011-06-29 22:56:13 -06:00
|
|
|
}
|
2013-10-18 13:35:45 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err // c is non-nil interface containing nil pointer
|
|
|
|
}
|
|
|
|
return c, nil
|
2010-06-21 20:52:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Listen announces on the local network address laddr.
|
net: support IPv6 scoped addressing zone
This CL provides IPv6 scoped addressing zone support as defined
in RFC 4007 for internet protocol family connection setups.
Follwoing types and functions allow a literal IPv6 address with
zone identifer as theirs parameter.
pkg net, func Dial(string, string) (Conn, error)
pkg net, func DialOpt(string, ...DialOption) (Conn, error)
pkg net, func DialTimeout(string, string, time.Duration) (Conn, error)
pkg net, func Listen(string, string) (Listener, error)
pkg net, func ListenPacket(string, string) (PacketConn, error)
pkg net, func ResolveIPAddr(string, string) (*IPAddr, error)
pkg net, func ResolveTCPAddr(string, string) (*TCPAddr, error)
pkg net, func ResolveUDPAddr(string, string) (*UDPAddr, error)
pkg net, type IPAddr struct, Zone string
pkg net, type TCPAddr struct, Zone string
pkg net, type UDPAddr struct, Zone string
Also follwoing methods return a literal IPv6 address with zone
identifier string if possible.
pkg net, method (*IPAddr) String() string
pkg net, method (*TCPAddr) String() string
pkg net, method (*UDPAddr) String() string
Fixes #4234.
Fixes #4501.
Update #5081.
R=rsc, iant
CC=golang-dev
https://golang.org/cl/6816116
2013-03-22 18:57:40 -06:00
|
|
|
// The network net must be a stream-oriented network: "tcp", "tcp4",
|
|
|
|
// "tcp6", "unix" or "unixpacket".
|
|
|
|
// See Dial for the syntax of laddr.
|
2012-01-21 05:51:53 -07:00
|
|
|
func Listen(net, laddr string) (Listener, error) {
|
2013-02-08 05:53:10 -07:00
|
|
|
la, err := resolveAddr("listen", net, laddr, noDeadline)
|
2012-01-21 05:51:53 -07:00
|
|
|
if err != nil {
|
2013-08-13 16:04:39 -06:00
|
|
|
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
|
2012-01-21 05:51:53 -07:00
|
|
|
}
|
2013-10-18 13:35:45 -06:00
|
|
|
var l Listener
|
2013-08-29 18:09:45 -06:00
|
|
|
switch la := la.toAddr().(type) {
|
2013-02-08 05:53:10 -07:00
|
|
|
case *TCPAddr:
|
2013-10-18 13:35:45 -06:00
|
|
|
l, err = ListenTCP(net, la)
|
2013-02-08 05:53:10 -07:00
|
|
|
case *UnixAddr:
|
2013-10-18 13:35:45 -06:00
|
|
|
l, err = ListenUnix(net, la)
|
2013-08-13 16:04:39 -06:00
|
|
|
default:
|
|
|
|
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
|
2010-06-21 20:52:30 -06:00
|
|
|
}
|
2013-10-18 13:35:45 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err // l is non-nil interface containing nil pointer
|
|
|
|
}
|
|
|
|
return l, nil
|
2010-06-21 20:52:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// ListenPacket announces on the local network address laddr.
|
net: support IPv6 scoped addressing zone
This CL provides IPv6 scoped addressing zone support as defined
in RFC 4007 for internet protocol family connection setups.
Follwoing types and functions allow a literal IPv6 address with
zone identifer as theirs parameter.
pkg net, func Dial(string, string) (Conn, error)
pkg net, func DialOpt(string, ...DialOption) (Conn, error)
pkg net, func DialTimeout(string, string, time.Duration) (Conn, error)
pkg net, func Listen(string, string) (Listener, error)
pkg net, func ListenPacket(string, string) (PacketConn, error)
pkg net, func ResolveIPAddr(string, string) (*IPAddr, error)
pkg net, func ResolveTCPAddr(string, string) (*TCPAddr, error)
pkg net, func ResolveUDPAddr(string, string) (*UDPAddr, error)
pkg net, type IPAddr struct, Zone string
pkg net, type TCPAddr struct, Zone string
pkg net, type UDPAddr struct, Zone string
Also follwoing methods return a literal IPv6 address with zone
identifier string if possible.
pkg net, method (*IPAddr) String() string
pkg net, method (*TCPAddr) String() string
pkg net, method (*UDPAddr) String() string
Fixes #4234.
Fixes #4501.
Update #5081.
R=rsc, iant
CC=golang-dev
https://golang.org/cl/6816116
2013-03-22 18:57:40 -06:00
|
|
|
// The network net must be a packet-oriented network: "udp", "udp4",
|
|
|
|
// "udp6", "ip", "ip4", "ip6" or "unixgram".
|
|
|
|
// See Dial for the syntax of laddr.
|
2012-11-27 14:36:05 -07:00
|
|
|
func ListenPacket(net, laddr string) (PacketConn, error) {
|
2013-02-08 05:53:10 -07:00
|
|
|
la, err := resolveAddr("listen", net, laddr, noDeadline)
|
2012-01-21 05:51:53 -07:00
|
|
|
if err != nil {
|
2013-08-13 16:04:39 -06:00
|
|
|
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
|
2012-01-21 05:51:53 -07:00
|
|
|
}
|
2013-10-18 13:35:45 -06:00
|
|
|
var l PacketConn
|
2013-08-29 18:09:45 -06:00
|
|
|
switch la := la.toAddr().(type) {
|
2013-02-08 05:53:10 -07:00
|
|
|
case *UDPAddr:
|
2013-10-18 13:35:45 -06:00
|
|
|
l, err = ListenUDP(net, la)
|
2013-02-08 05:53:10 -07:00
|
|
|
case *IPAddr:
|
2013-10-18 13:35:45 -06:00
|
|
|
l, err = ListenIP(net, la)
|
2013-02-08 05:53:10 -07:00
|
|
|
case *UnixAddr:
|
2013-10-18 13:35:45 -06:00
|
|
|
l, err = ListenUnixgram(net, la)
|
2013-08-13 16:04:39 -06:00
|
|
|
default:
|
|
|
|
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
|
2011-02-16 13:03:47 -07:00
|
|
|
}
|
2013-10-18 13:35:45 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err // l is non-nil interface containing nil pointer
|
|
|
|
}
|
|
|
|
return l, nil
|
2010-06-21 20:52:30 -06:00
|
|
|
}
|