Merge pull request #79 from status-im/dgramanyaddr

Fix Windows datagram's AnyAddress issue.
This commit is contained in:
Eugene Kabanov 2020-02-26 00:09:51 +02:00 committed by GitHub
commit fe1b1a6983
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 15 deletions

View File

@ -1,5 +1,5 @@
packageName = "chronos" packageName = "chronos"
version = "2.3.5" version = "2.3.6"
author = "Status Research & Development GmbH" author = "Status Research & Development GmbH"
description = "Chronos" description = "Chronos"
license = "Apache License 2.0 or MIT" license = "Apache License 2.0 or MIT"

View File

@ -448,6 +448,21 @@ proc resolveTAddress*(address: string, port: Port,
elif family == IpAddressFamily.IPv6: elif family == IpAddressFamily.IPv6:
result = resolveTAddress(address, port, AddressFamily.IPv6) result = resolveTAddress(address, port, AddressFamily.IPv6)
proc windowsAnyAddressFix*(a: TransportAddress): TransportAddress {.inline.} =
## BSD Sockets on *nix systems are able to perform connections to
## `0.0.0.0` or `::0` which are equal to `127.0.0.1` or `::1`.
when defined(windows):
if (a.family == AddressFamily.IPv4 and
a.address_v4 == AnyAddress.address_v4):
result = initTAddress("127.0.0.1", a.port)
elif (a.family == AddressFamily.IPv6 and
a.address_v6 == AnyAddress6.address_v6):
result = initTAddress("::1", a.port)
else:
result = a
else:
result = a
template checkClosed*(t: untyped) = template checkClosed*(t: untyped) =
if (ReadClosed in (t).state) or (WriteClosed in (t).state): if (ReadClosed in (t).state) or (WriteClosed in (t).state):
raise newException(TransportError, "Transport is already closed!") raise newException(TransportError, "Transport is already closed!")

View File

@ -165,7 +165,8 @@ when defined(windows):
transp.setWriterWSABuffer(vector) transp.setWriterWSABuffer(vector)
var ret: cint var ret: cint
if vector.kind == WithAddress: if vector.kind == WithAddress:
toSAddr(vector.address, transp.waddr, transp.walen) var fixedAddress = windowsAnyAddressFix(vector.address)
toSAddr(fixedAddress, transp.waddr, transp.walen)
ret = WSASendTo(fd, addr transp.wwsabuf, DWORD(1), addr bytesCount, ret = WSASendTo(fd, addr transp.wwsabuf, DWORD(1), addr bytesCount,
DWORD(0), cast[ptr SockAddr](addr transp.waddr), DWORD(0), cast[ptr SockAddr](addr transp.waddr),
cint(transp.walen), cint(transp.walen),
@ -359,16 +360,17 @@ when defined(windows):
raiseTransportOsError(err) raiseTransportOsError(err)
if remote.port != Port(0): if remote.port != Port(0):
var fixedAddress = windowsAnyAddressFix(remote)
var saddr: Sockaddr_storage var saddr: Sockaddr_storage
var slen: SockLen var slen: SockLen
toSAddr(remote, saddr, slen) toSAddr(fixedAddress, saddr, slen)
if connect(SocketHandle(localSock), cast[ptr SockAddr](addr saddr), if connect(SocketHandle(localSock), cast[ptr SockAddr](addr saddr),
slen) != 0: slen) != 0:
let err = osLastError() let err = osLastError()
if sock == asyncInvalidSocket: if sock == asyncInvalidSocket:
closeSocket(localSock) closeSocket(localSock)
raiseTransportOsError(err) raiseTransportOsError(err)
result.remote = remote result.remote = fixedAddress
result.fd = localSock result.fd = localSock
result.function = cbproc result.function = cbproc

View File

@ -685,18 +685,8 @@ when defined(windows):
sock: AsyncFD sock: AsyncFD
povl: RefCustomOverlapped povl: RefCustomOverlapped
proto: Protocol proto: Protocol
raddress: TransportAddress
## BSD Sockets on *nix systems are able to perform connections to var raddress = windowsAnyAddressFix(address)
## `0.0.0.0` or `::0` which are equal to `127.0.0.1` or `::1`.
if (address.family == AddressFamily.IPv4 and
address.address_v4 == AnyAddress.address_v4):
raddress = initTAddress("127.0.0.1", address.port)
elif (address.family == AddressFamily.IPv6 and
address.address_v6 == AnyAddress6.address_v6):
raddress = initTAddress("::1", address.port)
else:
raddress = address
toSAddr(raddress, saddr, slen) toSAddr(raddress, saddr, slen)
proto = Protocol.IPPROTO_TCP proto = Protocol.IPPROTO_TCP

View File

@ -483,6 +483,55 @@ suite "Datagram Transport test suite":
await wait(dgram1.join(), 5.seconds) await wait(dgram1.join(), 5.seconds)
result = res result = res
proc testAnyAddress(): Future[int] {.async.} =
var expectStr = "ANYADDRESS MESSAGE"
var expectSeq = cast[seq[byte]](expectStr)
let ta = initTAddress("0.0.0.0:0")
var res = 0
var event = newAsyncEvent()
proc clientMark1(transp: DatagramTransport,
raddr: TransportAddress): Future[void] {.async.} =
var bmsg = transp.getMessage()
var smsg = cast[string](bmsg)
if smsg == expectStr:
inc(res)
event.fire()
proc clientMark2(transp: DatagramTransport,
raddr: TransportAddress): Future[void] {.async.} =
discard
var dgram1 = newDatagramTransport(clientMark1, local = ta)
let la = dgram1.localAddress()
var dgram2 = newDatagramTransport(clientMark2)
var dgram3 = newDatagramTransport(clientMark2,
remote = la)
await dgram2.sendTo(la, addr expectStr[0], len(expectStr))
await event.wait()
event.clear()
await dgram2.sendTo(la, expectStr)
await event.wait()
event.clear()
await dgram2.sendTo(la, expectSeq)
await event.wait()
event.clear()
await dgram3.send(addr expectStr[0], len(expectStr))
await event.wait()
event.clear()
await dgram3.send(expectStr)
await event.wait()
event.clear()
await dgram3.send(expectSeq)
await event.wait()
event.clear()
await dgram1.closeWait()
await dgram2.closeWait()
await dgram3.closeWait()
result = res
test "close(transport) test": test "close(transport) test":
check waitFor(testTransportClose()) == true check waitFor(testTransportClose()) == true
test m1: test m1:
@ -505,5 +554,7 @@ suite "Datagram Transport test suite":
check waitFor(testConnReset()) == true check waitFor(testConnReset()) == true
test "Broadcast test": test "Broadcast test":
check waitFor(testBroadcast()) == 1 check waitFor(testBroadcast()) == 1
test "0.0.0.0/::0 (INADDR_ANY) test":
check waitFor(testAnyAddress()) == 6
test "Transports leak test": test "Transports leak test":
check getTracker("datagram.transport").isLeaked() == false check getTracker("datagram.transport").isLeaked() == false