diff options
author | Dominik Picheta <dominikpicheta@googlemail.com> | 2015-06-25 21:14:40 +0100 |
---|---|---|
committer | Dominik Picheta <dominikpicheta@googlemail.com> | 2015-06-25 21:14:40 +0100 |
commit | 3ff5e1a1af57d12ea759b72185d56386c63549a4 (patch) | |
tree | 59e8ca12a002a165de54b58ecf1554a050ec4cee /lib/pure | |
parent | 43c64c7545e155768e117c1894bf1a78af0bf5a8 (diff) | |
parent | c4a25d23b6220cd5740b40d8c20e8dcde45310bc (diff) | |
download | Nim-3ff5e1a1af57d12ea759b72185d56386c63549a4.tar.gz |
Merge pull request #2976 from ayourtch/ipv6-devel
Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a default
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/asyncdispatch.nim | 9 | ||||
-rw-r--r-- | lib/pure/asyncnet.nim | 29 | ||||
-rw-r--r-- | lib/pure/rawsockets.nim | 31 |
3 files changed, 49 insertions, 20 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 550b82f49..5a059ec8e 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -1009,7 +1009,7 @@ else: processTimers(p) proc connect*(socket: AsyncFD, address: string, port: Port, - af = AF_INET): Future[void] = + af_unused = AF_INET): Future[void] = var retFuture = newFuture[void]("connect") proc cb(fd: AsyncFD): bool = @@ -1017,7 +1017,8 @@ else: retFuture.complete() return true - var aiList = getAddrInfo(address, port, af) + var sockDomain = getSockDomain(socket.SocketHandle) + var aiList = getAddrInfo(address, port, sockDomain) var success = false var lastError: OSErrorCode var it = aiList @@ -1135,7 +1136,7 @@ else: client: AsyncFD]]("acceptAddr") proc cb(sock: AsyncFD): bool = result = true - var sockAddress: SockAddr_in + var sockAddress: Sockaddr_storage var addrLen = sizeof(sockAddress).Socklen var client = accept(sock.SocketHandle, cast[ptr SockAddr](addr(sockAddress)), addr(addrLen)) @@ -1151,7 +1152,7 @@ else: retFuture.fail(newException(OSError, osErrorMsg(lastError))) else: register(client.AsyncFD) - retFuture.complete(($inet_ntoa(sockAddress.sin_addr), client.AsyncFD)) + retFuture.complete((getAddrString(cast[ptr SockAddr](addr sockAddress)), client.AsyncFD)) addRead(socket, cb) return retFuture diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 712bba33b..d7ac60147 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -100,7 +100,7 @@ proc newAsyncSocket*(fd: AsyncFD, buffered = true): AsyncSocket = if buffered: result.currPos = 0 -proc newAsyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, +proc newAsyncSocket*(domain: Domain = AF_INET6, typ: SockType = SOCK_STREAM, protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket = ## Creates a new asynchronous socket. ## @@ -423,24 +423,21 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {. ## Binds ``address``:``port`` to the socket. ## ## If ``address`` is "" then ADDR_ANY will be bound. + var sockDomain = getSockDomain(socket.fd) - if address == "": - var name: Sockaddr_in - when defined(Windows) or defined(nimdoc): - name.sin_family = toInt(AF_INET).int16 + var realaddr = address + if realaddr == "": + case sockDomain + of AF_INET6: realaddr = "::" + of AF_INET: realaddr = "0.0.0.0" else: - name.sin_family = toInt(AF_INET) - name.sin_port = htons(int16(port)) - name.sin_addr.s_addr = htonl(INADDR_ANY) - if bindAddr(socket.fd, cast[ptr SockAddr](addr(name)), - sizeof(name).Socklen) < 0'i32: - raiseOSError(osLastError()) - else: - var aiList = getAddrInfo(address, port, AF_INET) - if bindAddr(socket.fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32: - dealloc(aiList) - raiseOSError(osLastError()) + raiseOSError("Unknown socket address family and no address specified to bindAddr") + + var aiList = getAddrInfo(realaddr, port, sockDomain) + if bindAddr(socket.fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32: dealloc(aiList) + raiseOSError(osLastError()) + dealloc(aiList) proc close*(socket: AsyncSocket) = ## Closes the socket. diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 6d656c983..9bfe9dab5 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -29,6 +29,7 @@ else: EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen, + Sockaddr_in6, Sockaddr_storage, inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto export @@ -194,6 +195,7 @@ proc getAddrInfo*(address: string, port: Port, af: Domain = AF_INET, typ: SockTy hints.ai_family = toInt(af) hints.ai_socktype = toInt(typ) hints.ai_protocol = toInt(prot) + hints.ai_flags = posix.AI_V4MAPPED var gaiResult = getaddrinfo(address, $port, addr(hints), result) if gaiResult != 0'i32: when useWinVersion: @@ -315,6 +317,35 @@ proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = result.addrList = cstringArrayToSeq(s.h_addr_list) result.length = int(s.h_length) +proc getSockDomain*(socket: SocketHandle): Domain = + ## returns the socket's domain (AF_INET or AF_INET6). + var name: SockAddr + var namelen = sizeof(name).SockLen + if getsockname(socket, cast[ptr SockAddr](addr(name)), + addr(namelen)) == -1'i32: + raiseOSError(osLastError()) + if name.sa_family == posix.AF_INET: + result = AF_INET + elif name.sa_family == posix.AF_INET6: + result = AF_INET6 + else: + raise newException(OSError, "unknown socket family in getSockFamily") + + +proc getAddrString*(sockAddr: ptr SockAddr): string = + ## return the string representation of address within sockAddr + if sockAddr.sa_family == posix.AF_INET: + result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr) + elif sockAddr.sa_family == posix.AF_INET6: + var v6addr = cast[ptr Sockaddr_in6](sockAddr).sin6_addr + result = newString(posix.INET6_ADDRSTRLEN) + discard posix.inet_ntop(posix.AF_INET6, addr cast[ptr Sockaddr_in6](sockAddr).sin6_addr, result.cstring, result.len.int32) + if posix.IN6_IS_ADDR_V4MAPPED(addr cast[ptr Sockaddr_in6](sockAddr).sin6_addr) != 0: + result = result.substr("::ffff:".len) + else: + raise newException(OSError, "unknown socket family in getAddrString") + + proc getSockName*(socket: SocketHandle): Port = ## returns the socket's associated port number. var name: Sockaddr_in |