diff options
author | Dominik Picheta <dominikpicheta@googlemail.com> | 2018-04-02 14:31:05 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-02 14:31:05 +0100 |
commit | 39c71d6211ff2a15755485acb4d9b13f74428c7b (patch) | |
tree | 4e98aa5a974f6d32fe61a6857ae30e70a7b20134 | |
parent | 92d2ce01d6a466ff6a98125ec729de26365c51ab (diff) | |
parent | 0770844285257b27f34b1f16a9fe4df08394a06a (diff) | |
download | Nim-39c71d6211ff2a15755485acb4d9b13f74428c7b.tar.gz |
Merge pull request #7336 from yglukhov/ipaddr-sockaddr-conversions
Conversion procs for (IpAddress, Port) <-> (SockAddr, Socklen)
-rw-r--r-- | lib/pure/nativesockets.nim | 2 | ||||
-rw-r--r-- | lib/pure/net.nim | 37 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 7 | ||||
-rw-r--r-- | tests/stdlib/tnet.nim | 32 |
4 files changed, 76 insertions, 2 deletions
diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index 280c4e927..68061853b 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -31,7 +31,7 @@ else: export Sockaddr_storage, Sockaddr_un, Sockaddr_un_path_length export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen, - Sockaddr_in6, + Sockaddr_in6, Sockaddr_storage, inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto, freeAddrInfo diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 2d1ca8a59..ccf02a1fc 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -414,6 +414,43 @@ proc isIpAddress*(address_str: string): bool {.tags: [].} = return false return true +proc toSockAddr*(address: IpAddress, port: Port, sa: var Sockaddr_storage, sl: var Socklen) = + ## Converts `IpAddress` and `Port` to `SockAddr` and `Socklen` + let port = htons(uint16(port)) + case address.family + of IpAddressFamily.IPv4: + sl = sizeof(Sockaddr_in).Socklen + let s = cast[ptr Sockaddr_in](addr sa) + s.sin_family = type(s.sin_family)(AF_INET) + s.sin_port = port + copyMem(addr s.sin_addr, unsafeAddr address.address_v4[0], sizeof(s.sin_addr)) + of IpAddressFamily.IPv6: + sl = sizeof(Sockaddr_in6).Socklen + let s = cast[ptr Sockaddr_in6](addr sa) + s.sin6_family = type(s.sin6_family)(AF_INET6) + s.sin6_port = port + copyMem(addr s.sin6_addr, unsafeAddr address.address_v6[0], sizeof(s.sin6_addr)) + +proc fromSockAddrAux(sa: ptr Sockaddr_storage, sl: Socklen, address: var IpAddress, port: var Port) = + if sa.ss_family.int == AF_INET.int and sl == sizeof(Sockaddr_in).Socklen: + address = IpAddress(family: IpAddressFamily.IPv4) + let s = cast[ptr Sockaddr_in](sa) + copyMem(addr address.address_v4[0], addr s.sin_addr, sizeof(address.address_v4)) + port = ntohs(s.sin_port).Port + elif sa.ss_family.int == AF_INET6.int and sl == sizeof(Sockaddr_in6).Socklen: + address = IpAddress(family: IpAddressFamily.IPv6) + let s = cast[ptr Sockaddr_in6](sa) + copyMem(addr address.address_v6[0], addr s.sin6_addr, sizeof(address.address_v6)) + port = ntohs(s.sin6_port).Port + else: + raise newException(ValueError, "Neither IPv4 nor IPv6") + +proc fromSockAddr*(sa: Sockaddr_storage | SockAddr | Sockaddr_in | Sockaddr_in6, + sl: Socklen, address: var IpAddress, port: var Port) {.inline.} = + ## Converts `SockAddr` and `Socklen` to `IpAddress` and `Port`. Raises + ## `ObjectConversionError` in case of invalid `sa` and `sl` arguments. + fromSockAddrAux(unsafeAddr sa, sl, address, port) + when defineSsl: CRYPTO_malloc_init() doAssert SslLibraryInit() == 1 diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index b2c1cc1f5..a0c784637 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -481,6 +481,13 @@ type sin6_flowinfo*: int32 # unsigned sin6_addr*: In6_addr + Sockaddr_storage* {.importc: "SOCKADDR_STORAGE", + header: "winsock2.h".} = object + ss_family*: int16 + ss_pad1: array[6, byte] + ss_align: int64 + ss_pad2: array[112, byte] + Servent* = object s_name*: cstring s_aliases*: cstringArray diff --git a/tests/stdlib/tnet.nim b/tests/stdlib/tnet.nim index e8ada05e7..64d690fc9 100644 --- a/tests/stdlib/tnet.nim +++ b/tests/stdlib/tnet.nim @@ -1,4 +1,4 @@ -import net +import net, nativesockets import unittest suite "isIpAddress tests": @@ -45,3 +45,33 @@ suite "parseIpAddress tests": test "invalid ipv6": expect(ValueError): discard parseIpAddress("gggg:cdba:0000:0000:0000:0000:3257:9652") + +block: # "IpAddress/Sockaddr conversion" + proc test(ipaddrstr: string) = + var ipaddr_1 = parseIpAddress(ipaddrstr) + # echo ipaddrstr, " ", $ipaddr_1 + + doAssert($ipaddrstr == $ipaddr_1) + + var sockaddr: Sockaddr_storage + var socklen: Socklen + var ipaddr_2: IpAddress + var port_2: Port + + toSockAddr(ipaddr_1, Port(0), sockaddr, socklen) + fromSockAddr(sockaddr, socklen, ipaddr_2, port_2) + + doAssert(ipaddrstr == $ipaddr_1) + + doAssert(ipaddr_1 == ipaddr_2) + doAssert($ipaddr_1 == $ipaddr_2) + + + # ipv6 address of example.com + test("2606:2800:220:1:248:1893:25c8:1946") + # ipv6 address of localhost + test("::1") + # ipv4 address of example.com + test("93.184.216.34") + # ipv4 address of localhost + test("127.0.0.1") |