PageRenderTime 70ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/gofrontend/libgo/go/net/dial.go

http://github.com/axw/llgo
Go | 431 lines | 283 code | 35 blank | 113 comment | 85 complexity | 138a11b1a21dd5ade75cc7d3d38ef7be MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  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.
  4. package net
  5. import (
  6. "errors"
  7. "time"
  8. )
  9. // A Dialer contains options for connecting to an address.
  10. //
  11. // The zero value for each field is equivalent to dialing
  12. // without that option. Dialing with the zero value of Dialer
  13. // is therefore equivalent to just calling the Dial function.
  14. type Dialer struct {
  15. // Timeout is the maximum amount of time a dial will wait for
  16. // a connect to complete. If Deadline is also set, it may fail
  17. // earlier.
  18. //
  19. // The default is no timeout.
  20. //
  21. // When dialing a name with multiple IP addresses, the timeout
  22. // may be divided between them.
  23. //
  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.
  27. Timeout time.Duration
  28. // Deadline is the absolute point in time after which dials
  29. // will fail. If Timeout is set, it may fail earlier.
  30. // Zero means no deadline, or dependent on the operating system
  31. // as with the Timeout option.
  32. Deadline time.Time
  33. // LocalAddr is the local address to use when dialing an
  34. // address. The address must be of a compatible type for the
  35. // network being dialed.
  36. // If nil, a local address is automatically chosen.
  37. LocalAddr Addr
  38. // DualStack enables RFC 6555-compliant "Happy Eyeballs" dialing
  39. // when the network is "tcp" and the destination is a host name
  40. // with both IPv4 and IPv6 addresses. This allows a client to
  41. // tolerate networks where one address family is silently broken.
  42. DualStack bool
  43. // FallbackDelay specifies the length of time to wait before
  44. // spawning a fallback connection, when DualStack is enabled.
  45. // If zero, a default delay of 300ms is used.
  46. FallbackDelay time.Duration
  47. // KeepAlive specifies the keep-alive period for an active
  48. // network connection.
  49. // If zero, keep-alives are not enabled. Network protocols
  50. // that do not support keep-alives ignore this field.
  51. KeepAlive time.Duration
  52. }
  53. // Return either now+Timeout or Deadline, whichever comes first.
  54. // Or zero, if neither is set.
  55. func (d *Dialer) deadline(now time.Time) time.Time {
  56. if d.Timeout == 0 {
  57. return d.Deadline
  58. }
  59. timeoutDeadline := now.Add(d.Timeout)
  60. if d.Deadline.IsZero() || timeoutDeadline.Before(d.Deadline) {
  61. return timeoutDeadline
  62. } else {
  63. return d.Deadline
  64. }
  65. }
  66. // partialDeadline returns the deadline to use for a single address,
  67. // when multiple addresses are pending.
  68. func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) {
  69. if deadline.IsZero() {
  70. return deadline, nil
  71. }
  72. timeRemaining := deadline.Sub(now)
  73. if timeRemaining <= 0 {
  74. return time.Time{}, errTimeout
  75. }
  76. // Tentatively allocate equal time to each remaining address.
  77. timeout := timeRemaining / time.Duration(addrsRemaining)
  78. // If the time per address is too short, steal from the end of the list.
  79. const saneMinimum = 2 * time.Second
  80. if timeout < saneMinimum {
  81. if timeRemaining < saneMinimum {
  82. timeout = timeRemaining
  83. } else {
  84. timeout = saneMinimum
  85. }
  86. }
  87. return now.Add(timeout), nil
  88. }
  89. func (d *Dialer) fallbackDelay() time.Duration {
  90. if d.FallbackDelay > 0 {
  91. return d.FallbackDelay
  92. } else {
  93. return 300 * time.Millisecond
  94. }
  95. }
  96. func parseNetwork(net string) (afnet string, proto int, err error) {
  97. i := last(net, ':')
  98. if i < 0 { // no colon
  99. switch net {
  100. case "tcp", "tcp4", "tcp6":
  101. case "udp", "udp4", "udp6":
  102. case "ip", "ip4", "ip6":
  103. case "unix", "unixgram", "unixpacket":
  104. default:
  105. return "", 0, UnknownNetworkError(net)
  106. }
  107. return net, 0, nil
  108. }
  109. afnet = net[:i]
  110. switch afnet {
  111. case "ip", "ip4", "ip6":
  112. protostr := net[i+1:]
  113. proto, i, ok := dtoi(protostr, 0)
  114. if !ok || i != len(protostr) {
  115. proto, err = lookupProtocol(protostr)
  116. if err != nil {
  117. return "", 0, err
  118. }
  119. }
  120. return afnet, proto, nil
  121. }
  122. return "", 0, UnknownNetworkError(net)
  123. }
  124. func resolveAddrList(op, net, addr string, deadline time.Time) (addrList, error) {
  125. afnet, _, err := parseNetwork(net)
  126. if err != nil {
  127. return nil, err
  128. }
  129. if op == "dial" && addr == "" {
  130. return nil, errMissingAddress
  131. }
  132. switch afnet {
  133. case "unix", "unixgram", "unixpacket":
  134. addr, err := ResolveUnixAddr(afnet, addr)
  135. if err != nil {
  136. return nil, err
  137. }
  138. return addrList{addr}, nil
  139. }
  140. return internetAddrList(afnet, addr, deadline)
  141. }
  142. // Dial connects to the address on the named network.
  143. //
  144. // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
  145. // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
  146. // (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
  147. // "unixpacket".
  148. //
  149. // For TCP and UDP networks, addresses have the form host:port.
  150. // If host is a literal IPv6 address it must be enclosed
  151. // in square brackets as in "[::1]:80" or "[ipv6-host%zone]:80".
  152. // The functions JoinHostPort and SplitHostPort manipulate addresses
  153. // in this form.
  154. //
  155. // Examples:
  156. // Dial("tcp", "12.34.56.78:80")
  157. // Dial("tcp", "google.com:http")
  158. // Dial("tcp", "[2001:db8::1]:http")
  159. // Dial("tcp", "[fe80::1%lo0]:80")
  160. //
  161. // For IP networks, the network must be "ip", "ip4" or "ip6" followed
  162. // by a colon and a protocol number or name and the addr must be a
  163. // literal IP address.
  164. //
  165. // Examples:
  166. // Dial("ip4:1", "127.0.0.1")
  167. // Dial("ip6:ospf", "::1")
  168. //
  169. // For Unix networks, the address must be a file system path.
  170. func Dial(network, address string) (Conn, error) {
  171. var d Dialer
  172. return d.Dial(network, address)
  173. }
  174. // DialTimeout acts like Dial but takes a timeout.
  175. // The timeout includes name resolution, if required.
  176. func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
  177. d := Dialer{Timeout: timeout}
  178. return d.Dial(network, address)
  179. }
  180. // dialContext holds common state for all dial operations.
  181. type dialContext struct {
  182. Dialer
  183. network, address string
  184. finalDeadline time.Time
  185. }
  186. // Dial connects to the address on the named network.
  187. //
  188. // See func Dial for a description of the network and address
  189. // parameters.
  190. func (d *Dialer) Dial(network, address string) (Conn, error) {
  191. finalDeadline := d.deadline(time.Now())
  192. addrs, err := resolveAddrList("dial", network, address, finalDeadline)
  193. if err != nil {
  194. return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}
  195. }
  196. ctx := &dialContext{
  197. Dialer: *d,
  198. network: network,
  199. address: address,
  200. finalDeadline: finalDeadline,
  201. }
  202. var primaries, fallbacks addrList
  203. if d.DualStack && network == "tcp" {
  204. primaries, fallbacks = addrs.partition(isIPv4)
  205. } else {
  206. primaries = addrs
  207. }
  208. var c Conn
  209. if len(fallbacks) == 0 {
  210. // dialParallel can accept an empty fallbacks list,
  211. // but this shortcut avoids the goroutine/channel overhead.
  212. c, err = dialSerial(ctx, primaries, nil)
  213. } else {
  214. c, err = dialParallel(ctx, primaries, fallbacks)
  215. }
  216. if d.KeepAlive > 0 && err == nil {
  217. if tc, ok := c.(*TCPConn); ok {
  218. setKeepAlive(tc.fd, true)
  219. setKeepAlivePeriod(tc.fd, d.KeepAlive)
  220. testHookSetKeepAlive()
  221. }
  222. }
  223. return c, err
  224. }
  225. // dialParallel races two copies of dialSerial, giving the first a
  226. // head start. It returns the first established connection and
  227. // closes the others. Otherwise it returns an error from the first
  228. // primary address.
  229. func dialParallel(ctx *dialContext, primaries, fallbacks addrList) (Conn, error) {
  230. results := make(chan dialResult) // unbuffered, so dialSerialAsync can detect race loss & cleanup
  231. cancel := make(chan struct{})
  232. defer close(cancel)
  233. // Spawn the primary racer.
  234. go dialSerialAsync(ctx, primaries, nil, cancel, results)
  235. // Spawn the fallback racer.
  236. fallbackTimer := time.NewTimer(ctx.fallbackDelay())
  237. go dialSerialAsync(ctx, fallbacks, fallbackTimer, cancel, results)
  238. var primaryErr error
  239. for nracers := 2; nracers > 0; nracers-- {
  240. res := <-results
  241. // If we're still waiting for a connection, then hasten the delay.
  242. // Otherwise, disable the Timer and let cancel take over.
  243. if fallbackTimer.Stop() && res.error != nil {
  244. fallbackTimer.Reset(0)
  245. }
  246. if res.error == nil {
  247. return res.Conn, nil
  248. }
  249. if res.primary {
  250. primaryErr = res.error
  251. }
  252. }
  253. return nil, primaryErr
  254. }
  255. type dialResult struct {
  256. Conn
  257. error
  258. primary bool
  259. }
  260. // dialSerialAsync runs dialSerial after some delay, and returns the
  261. // resulting connection through a channel. When racing two connections,
  262. // the primary goroutine uses a nil timer to omit the delay.
  263. func dialSerialAsync(ctx *dialContext, ras addrList, timer *time.Timer, cancel <-chan struct{}, results chan<- dialResult) {
  264. if timer != nil {
  265. // We're in the fallback goroutine; sleep before connecting.
  266. select {
  267. case <-timer.C:
  268. case <-cancel:
  269. return
  270. }
  271. }
  272. c, err := dialSerial(ctx, ras, cancel)
  273. select {
  274. case results <- dialResult{c, err, timer == nil}:
  275. // We won the race.
  276. case <-cancel:
  277. // The other goroutine won the race.
  278. if c != nil {
  279. c.Close()
  280. }
  281. }
  282. }
  283. // dialSerial connects to a list of addresses in sequence, returning
  284. // either the first successful connection, or the first error.
  285. func dialSerial(ctx *dialContext, ras addrList, cancel <-chan struct{}) (Conn, error) {
  286. var firstErr error // The error from the first address is most relevant.
  287. for i, ra := range ras {
  288. select {
  289. case <-cancel:
  290. return nil, &OpError{Op: "dial", Net: ctx.network, Source: ctx.LocalAddr, Addr: ra, Err: errCanceled}
  291. default:
  292. }
  293. partialDeadline, err := partialDeadline(time.Now(), ctx.finalDeadline, len(ras)-i)
  294. if err != nil {
  295. // Ran out of time.
  296. if firstErr == nil {
  297. firstErr = &OpError{Op: "dial", Net: ctx.network, Source: ctx.LocalAddr, Addr: ra, Err: err}
  298. }
  299. break
  300. }
  301. // dialTCP does not support cancelation (see golang.org/issue/11225),
  302. // so if cancel fires, we'll continue trying to connect until the next
  303. // timeout, or return a spurious connection for the caller to close.
  304. dialer := func(d time.Time) (Conn, error) {
  305. return dialSingle(ctx, ra, d)
  306. }
  307. c, err := dial(ctx.network, ra, dialer, partialDeadline)
  308. if err == nil {
  309. return c, nil
  310. }
  311. if firstErr == nil {
  312. firstErr = err
  313. }
  314. }
  315. if firstErr == nil {
  316. firstErr = &OpError{Op: "dial", Net: ctx.network, Source: nil, Addr: nil, Err: errMissingAddress}
  317. }
  318. return nil, firstErr
  319. }
  320. // dialSingle attempts to establish and returns a single connection to
  321. // the destination address. This must be called through the OS-specific
  322. // dial function, because some OSes don't implement the deadline feature.
  323. func dialSingle(ctx *dialContext, ra Addr, deadline time.Time) (c Conn, err error) {
  324. la := ctx.LocalAddr
  325. if la != nil && la.Network() != ra.Network() {
  326. return nil, &OpError{Op: "dial", Net: ctx.network, Source: la, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
  327. }
  328. switch ra := ra.(type) {
  329. case *TCPAddr:
  330. la, _ := la.(*TCPAddr)
  331. c, err = testHookDialTCP(ctx.network, la, ra, deadline)
  332. case *UDPAddr:
  333. la, _ := la.(*UDPAddr)
  334. c, err = dialUDP(ctx.network, la, ra, deadline)
  335. case *IPAddr:
  336. la, _ := la.(*IPAddr)
  337. c, err = dialIP(ctx.network, la, ra, deadline)
  338. case *UnixAddr:
  339. la, _ := la.(*UnixAddr)
  340. c, err = dialUnix(ctx.network, la, ra, deadline)
  341. default:
  342. return nil, &OpError{Op: "dial", Net: ctx.network, Source: la, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: ctx.address}}
  343. }
  344. if err != nil {
  345. return nil, err // c is non-nil interface containing nil pointer
  346. }
  347. return c, nil
  348. }
  349. // Listen announces on the local network address laddr.
  350. // The network net must be a stream-oriented network: "tcp", "tcp4",
  351. // "tcp6", "unix" or "unixpacket".
  352. // See Dial for the syntax of laddr.
  353. func Listen(net, laddr string) (Listener, error) {
  354. addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
  355. if err != nil {
  356. return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
  357. }
  358. var l Listener
  359. switch la := addrs.first(isIPv4).(type) {
  360. case *TCPAddr:
  361. l, err = ListenTCP(net, la)
  362. case *UnixAddr:
  363. l, err = ListenUnix(net, la)
  364. default:
  365. return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
  366. }
  367. if err != nil {
  368. return nil, err // l is non-nil interface containing nil pointer
  369. }
  370. return l, nil
  371. }
  372. // ListenPacket announces on the local network address laddr.
  373. // The network net must be a packet-oriented network: "udp", "udp4",
  374. // "udp6", "ip", "ip4", "ip6" or "unixgram".
  375. // See Dial for the syntax of laddr.
  376. func ListenPacket(net, laddr string) (PacketConn, error) {
  377. addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
  378. if err != nil {
  379. return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
  380. }
  381. var l PacketConn
  382. switch la := addrs.first(isIPv4).(type) {
  383. case *UDPAddr:
  384. l, err = ListenUDP(net, la)
  385. case *IPAddr:
  386. l, err = ListenIP(net, la)
  387. case *UnixAddr:
  388. l, err = ListenUnixgram(net, la)
  389. default:
  390. return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
  391. }
  392. if err != nil {
  393. return nil, err // l is non-nil interface containing nil pointer
  394. }
  395. return l, nil
  396. }