diff --git a/asyncdispatch2.nimble b/asyncdispatch2.nimble
index 6dd8171..8cc818c 100644
--- a/asyncdispatch2.nimble
+++ b/asyncdispatch2.nimble
@@ -30,6 +30,10 @@ task test, "Run all tests":
exec "nim c -r tests/testsignal"
exec "nim c -r -d:release tests/testsignal"
+ exec "nim c -r -d:useSysAssert -d:useGcAssert tests/testaddress"
+ exec "nim c -r tests/testaddress"
+ exec "nim c -r -d:release tests/testaddress"
+
exec "nim c -r -d:useSysAssert -d:useGcAssert tests/testdatagram"
exec "nim c -r tests/testdatagram"
exec "nim c -r -d:release tests/testdatagram"
diff --git a/asyncdispatch2/transports/common.nim b/asyncdispatch2/transports/common.nim
index 8809830..eee81f7 100644
--- a/asyncdispatch2/transports/common.nim
+++ b/asyncdispatch2/transports/common.nim
@@ -7,7 +7,7 @@
# Apache License, version 2.0, (LICENSE-APACHEv2)
# MIT license (LICENSE-MIT)
-import net, strutils
+import net, nativesockets, strutils
import ../asyncloop, ../asyncsync
const
@@ -102,7 +102,7 @@ proc `$`*(address: TransportAddress): string =
result.add(":")
result.add($int(address.port))
-proc strAddress*(address: string): TransportAddress =
+proc initTAddress*(address: string): TransportAddress =
## Parses string representation of ``address``.
##
## IPv4 transport address format is ``a.b.c.d:port``.
@@ -110,13 +110,65 @@ proc strAddress*(address: string): TransportAddress =
var parts = address.rsplit(":", maxsplit = 1)
doAssert(len(parts) == 2, "Format is
:!")
let port = parseInt(parts[1])
- doAssert(port > 0 and port < 65536, "Illegal port number!")
+ doAssert(port >= 0 and port < 65536, "Illegal port number!")
result.port = Port(port)
if parts[0][0] == '[' and parts[0][^1] == ']':
result.address = parseIpAddress(parts[0][1..^2])
else:
result.address = parseIpAddress(parts[0])
+proc initTAddress*(address: string, port: Port): TransportAddress =
+ ## Initialize ``TransportAddress`` with IP address ``address`` and
+ ## port number ``port``.
+ result.address = parseIpAddress(address)
+ result.port = port
+
+proc initTAddress*(address: string, port: int): TransportAddress =
+ ## Initialize ``TransportAddress`` with IP address ``address`` and
+ ## port number ``port``.
+ result.address = parseIpAddress(address)
+ result.port = Port(Port(port and 0xFFFF))
+
+proc resolveTAddress*(address: string,
+ family = IpAddressFamily.IPv4): seq[TransportAddress] =
+ ## Resolve string representation of ``address``.
+ ##
+ ## Supported formats are:
+ ## IPv4 numeric address ``a.b.c.d:port``
+ ## IPv6 numeric address ``[::]:port``
+ ## Hostname address ``hostname:port``
+ ##
+ ## If hostname address is detected, then network address translation via DNS
+ ## will be performed.
+ var
+ ta: TransportAddress
+ ap: Port
+ result = newSeq[TransportAddress]()
+ var parts = address.rsplit(":", maxsplit = 1)
+ doAssert(len(parts) == 2, "Format is :!")
+ let port = parseInt(parts[1])
+ doAssert(port >= 0 and port < 65536, "Illegal port number!")
+ if parts[0][0] == '[' and parts[0][^1] == ']':
+ ta = TransportAddress(address: parseIpAddress(parts[0][1..^2]),
+ port: Port(port))
+ result.add(ta)
+ else:
+ if isIpAddress(parts[0]):
+ ta = TransportAddress(address: parseIpAddress(parts[0]),
+ port: Port(port))
+ result.add(ta)
+ else:
+ var domain = if family == IpAddressFamily.IPv4: Domain(AF_INET) else:
+ Domain(AF_INET6)
+ var aiList = getAddrInfo(parts[0], Port(port), domain)
+ var it = aiList
+ while it != nil:
+ fromSockAddr(cast[ptr Sockaddr_storage](it.ai_addr)[],
+ SockLen(it.ai_addrlen), ta.address, ta.port)
+ result.add(ta)
+ it = it.ai_next
+ freeAddrInfo(aiList)
+
template checkClosed*(t: untyped) =
if (ReadClosed in (t).state) or (WriteClosed in (t).state):
raise newException(TransportError, "Transport is already closed!")
@@ -133,3 +185,6 @@ when defined(windows):
const ERROR_SUCCESS* = 0
proc cancelIo*(hFile: HANDLE): WINBOOL
{.stdcall, dynlib: "kernel32", importc: "CancelIo".}
+
+when isMainModule:
+ echo $resolveTAddress("localhost:443", IpAddressFamily.IPv6)
\ No newline at end of file
diff --git a/asyncdispatch2/transports/datagram.nim b/asyncdispatch2/transports/datagram.nim
index f49e594..f6cad55 100644
--- a/asyncdispatch2/transports/datagram.nim
+++ b/asyncdispatch2/transports/datagram.nim
@@ -36,6 +36,11 @@ else:
writer: Future[void] # Writer vector completion Future
type
+ DatagramServer* = ref object of RootRef
+ ## Datagram server object
+ transport*: DatagramTransport ## Datagram transport
+ status*: ServerStatus ## Current server status
+
DatagramCallback* = proc(transp: DatagramTransport,
pbytes: pointer,
nbytes: int,
@@ -558,11 +563,6 @@ proc sendTo*(transp: DatagramTransport, pbytes: pointer, nbytes: int,
if WriteError in transp.state:
raise transp.getError()
-type
- DatagramServer* = ref object of RootRef
- transport*: DatagramTransport
- status*: ServerStatus
-
proc createDatagramServer*(host: TransportAddress,
cbproc: DatagramCallback,
flags: set[ServerFlags] = {},
diff --git a/tests/testaddress.nim b/tests/testaddress.nim
new file mode 100644
index 0000000..6e7c6a0
--- /dev/null
+++ b/tests/testaddress.nim
@@ -0,0 +1,59 @@
+# Asyncdispatch2 Test Suite
+# (c) Copyright 2018
+# Status Research & Development GmbH
+#
+# Licensed under either of
+# Apache License, version 2.0, (LICENSE-APACHEv2)
+# MIT license (LICENSE-MIT)
+
+import strutils, unittest
+import ../asyncdispatch2
+
+when isMainModule:
+ suite "TransportAddress test suite":
+ test "initTAddress(string)":
+ check $initTAddress("0.0.0.0:0") == "0.0.0.0:0"
+ check $initTAddress("255.255.255.255:65535") == "255.255.255.255:65535"
+ check $initTAddress("[::]:0") == "[::]:0"
+ check $initTAddress("[FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF]:65535") ==
+ "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535"
+ test "initTAddress(string, Port)":
+ check $initTAddress("0.0.0.0", Port(0)) == "0.0.0.0:0"
+ check $initTAddress("255.255.255.255", Port(65535)) ==
+ "255.255.255.255:65535"
+ check $initTAddress("::", Port(0)) == "[::]:0"
+ check $initTAddress("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF",
+ Port(65535)) ==
+ "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535"
+ test "initTAddress(string, int)":
+ check $initTAddress("0.0.0.0", 0) == "0.0.0.0:0"
+ check $initTAddress("255.255.255.255", 65535) ==
+ "255.255.255.255:65535"
+ check $initTAddress("::", 0) == "[::]:0"
+ check $initTAddress("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", 65535) ==
+ "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535"
+ test "resolveTAddress(string)":
+ var numeric = [
+ "0.0.0.0:0",
+ "255.0.0.255:54321",
+ "128.128.128.128:12345",
+ "255.255.255.255:65535",
+ "[::]:0",
+ "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535",
+ "[aaaa:bbbb:cccc:dddd:eeee:ffff::1111]:12345",
+ "[aaaa:bbbb:cccc:dddd:eeee:ffff::]:12345",
+ "[a:b:c:d:e:f::]:12345",
+ "[2222:3333:4444:5555:6666:7777:8888:9999]:56789"
+ ]
+ var hostnames = [
+ "www.google.com:443",
+ "www.github.com:443"
+ ]
+ for item in numeric:
+ var taseq = resolveTAddress(item)
+ check len(taseq) == 1
+ check $taseq[0] == item
+
+ for item in hostnames:
+ var taseq = resolveTAddress(item)
+ check len(taseq) >= 1
diff --git a/tests/testdatagram.nim b/tests/testdatagram.nim
index ed91d73..dad4d34 100644
--- a/tests/testdatagram.nim
+++ b/tests/testdatagram.nim
@@ -46,7 +46,7 @@ proc client2(transp: DatagramTransport, pbytes: pointer, nbytes: int,
if counterPtr[] == TestsCount:
transp.close()
else:
- var ta = strAddress("127.0.0.1:33336")
+ var ta = initTAddress("127.0.0.1:33336")
var req = "REQUEST" & $counterPtr[]
await transp.sendTo(addr req[0], len(req), ta)
else:
@@ -119,7 +119,7 @@ proc client5(transp: DatagramTransport, pbytes: pointer, nbytes: int,
if counterPtr[] == MessagesCount:
transp.close()
else:
- var ta = strAddress("127.0.0.1:33337")
+ var ta = initTAddress("127.0.0.1:33337")
var req = "REQUEST" & $counterPtr[]
await transp.sendTo(addr req[0], len(req), ta)
else:
@@ -133,7 +133,7 @@ proc client5(transp: DatagramTransport, pbytes: pointer, nbytes: int,
transp.close()
proc test1(): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:33336")
+ var ta = initTAddress("127.0.0.1:33336")
var counter = 0
var dgram1 = newDatagramTransport(client1, udata = addr counter, local = ta)
var dgram2 = newDatagramTransport(client2, udata = addr counter)
@@ -144,7 +144,7 @@ proc test1(): Future[int] {.async.} =
result = counter
proc test2(): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:33337")
+ var ta = initTAddress("127.0.0.1:33337")
var counter = 0
var dgram1 = newDatagramTransport(client1, udata = addr counter, local = ta)
var dgram2 = newDatagramTransport(client3, udata = addr counter, remote = ta)
@@ -166,7 +166,7 @@ proc waitAll(futs: seq[Future[void]]): Future[void] =
return retFuture
proc test3(bounded: bool): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:33337")
+ var ta = initTAddress("127.0.0.1:33337")
var counter = 0
var dgram1 = newDatagramTransport(client1, udata = addr counter, local = ta)
var clients = newSeq[Future[void]](ClientsCount)
@@ -265,7 +265,7 @@ proc serveDatagramClient(transp: DatagramTransport,
await transp.sendTo(addr answer[0], len(answer), raddr)
proc test4(): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:31346")
+ var ta = initTAddress("127.0.0.1:31346")
var counter = 0
var server = createDatagramServer(ta, serveDatagramClient, {ReuseAddr})
server.start()
diff --git a/tests/teststream.nim b/tests/teststream.nim
index 6dd5873..a1dd348 100644
--- a/tests/teststream.nim
+++ b/tests/teststream.nim
@@ -244,7 +244,7 @@ proc swarmManager4(address: TransportAddress): Future[int] {.async.} =
result += res
proc test1(): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:31344")
+ var ta = initTAddress("127.0.0.1:31344")
var server = createStreamServer(ta, serveClient1, {ReuseAddr})
server.start()
result = await swarmManager1(ta)
@@ -252,7 +252,7 @@ proc test1(): Future[int] {.async.} =
server.close()
proc test2(): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:31345")
+ var ta = initTAddress("127.0.0.1:31345")
var counter = 0
var server = createStreamServer(ta, serveClient2, {ReuseAddr})
server.start()
@@ -261,7 +261,7 @@ proc test2(): Future[int] {.async.} =
server.close()
proc test3(): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:31346")
+ var ta = initTAddress("127.0.0.1:31346")
var counter = 0
var server = createStreamServer(ta, serveClient3, {ReuseAddr})
server.start()
@@ -270,7 +270,7 @@ proc test3(): Future[int] {.async.} =
server.close()
proc test4(): Future[int] {.async.} =
- var ta = strAddress("127.0.0.1:31347")
+ var ta = initTAddress("127.0.0.1:31347")
var counter = 0
var server = createStreamServer(ta, serveClient4, {ReuseAddr})
server.start()