Implement dial, support IPv6 in httpclient (#5763)

* Implement dial, support IPv6 in httpclient

Added ``dial`` procedure to networking modules: ``net``, ``asyncdispatch``,
``asyncnet``. It merges socket creation, address resolution, and connection
into single step. When using ``dial``, you don't have to worry about
IPv4 vs IPv6 problem.

Fixed addrInfo loop in connect to behave properly.
Previously it would stop on first non-immediate failure, instead of
continuing and trying the remaining addresses.

Fixed newAsyncNativeSocket to raise proper error if socket creation
fails.

Fixes: #3811

* Check domain during connect() only on non-Windows

This is how it was in the previous implementation of connect().

* Call 'osLastError' before 'close' in net.dial

* Record osLastError before freeAddrInfo in net.dial

* Add missing docs for 'dial' proc

* Optimize dial to create one FD per domain, add tests

And make async IPv6 servers work on Windows.

* Add IPv6 test to uri module

* Fix getAddrString error handling
This commit is contained in:
Ruslan Mustakov 2017-05-02 14:25:50 +07:00 • committed by Andreas Rumpf
commit ecf278c467
13 changed files with 559 additions and 334 deletions

View file

@ -50,6 +50,7 @@ proc add*(url: var Url, a: Url) {.deprecated.} =
proc parseAuthority(authority: string, result: var Uri) =
var i = 0
var inPort = false
var inIPv6 = false
while true:
case authority[i]
of '@':
@ -59,7 +60,14 @@ proc parseAuthority(authority: string, result: var Uri) =
result.hostname.setLen(0)
inPort = false
of ':':
inPort = true
if inIPv6:
result.hostname.add(authority[i])
else:
inPort = true
of '[':
inIPv6 = true
of ']':
inIPv6 = false
of '\0': break
else:
if inPort:
@ -345,6 +353,17 @@ when isMainModule:
doAssert test.anchor == "nose"
doAssert($test == str)
block:
# IPv6 address
let str = "foo://[::1]:1234/bar?baz=true&qux#quux"
let uri = parseUri(str)
doAssert uri.scheme == "foo"
doAssert uri.hostname == "::1"
doAssert uri.port == "1234"
doAssert uri.path == "/bar"
doAssert uri.query == "baz=true&qux"
doAssert uri.anchor == "quux"
block:
let str = "urn:example:animal:ferret:nose"
let test = parseUri(str)