Merge pull request #2976 from ayourtch/ipv6-devel
Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a default
This commit is contained in:
commit
3ff5e1a1af
4 changed files with 54 additions and 22 deletions
|
|
@ -448,7 +448,7 @@ type
|
||||||
sa_family*: TSa_Family ## Address family.
|
sa_family*: TSa_Family ## Address family.
|
||||||
sa_data*: array [0..255, char] ## Socket address (variable-length data).
|
sa_data*: array [0..255, char] ## Socket address (variable-length data).
|
||||||
|
|
||||||
Tsockaddr_storage* {.importc: "struct sockaddr_storage",
|
Sockaddr_storage* {.importc: "struct sockaddr_storage",
|
||||||
header: "<sys/socket.h>",
|
header: "<sys/socket.h>",
|
||||||
pure, final.} = object ## struct sockaddr_storage
|
pure, final.} = object ## struct sockaddr_storage
|
||||||
ss_family*: TSa_Family ## Address family.
|
ss_family*: TSa_Family ## Address family.
|
||||||
|
|
@ -506,7 +506,7 @@ type
|
||||||
header: "<netinet/in.h>".} = object ## struct in6_addr
|
header: "<netinet/in.h>".} = object ## struct in6_addr
|
||||||
s6_addr*: array [0..15, char]
|
s6_addr*: array [0..15, char]
|
||||||
|
|
||||||
Tsockaddr_in6* {.importc: "struct sockaddr_in6", pure, final,
|
Sockaddr_in6* {.importc: "struct sockaddr_in6", pure, final,
|
||||||
header: "<netinet/in.h>".} = object ## struct sockaddr_in6
|
header: "<netinet/in.h>".} = object ## struct sockaddr_in6
|
||||||
sin6_family*: TSa_Family ## AF_INET6.
|
sin6_family*: TSa_Family ## AF_INET6.
|
||||||
sin6_port*: InPort ## Port number.
|
sin6_port*: InPort ## Port number.
|
||||||
|
|
@ -581,6 +581,7 @@ type
|
||||||
|
|
||||||
{.deprecated: [TSockaddr_in: Sockaddr_in, TAddrinfo: AddrInfo,
|
{.deprecated: [TSockaddr_in: Sockaddr_in, TAddrinfo: AddrInfo,
|
||||||
TSockAddr: SockAddr, TSockLen: SockLen, TTimeval: Timeval,
|
TSockAddr: SockAddr, TSockLen: SockLen, TTimeval: Timeval,
|
||||||
|
Tsockaddr_storage: Sockaddr_storage, Tsockaddr_in6: Sockaddr_in6,
|
||||||
Thostent: Hostent, TServent: Servent,
|
Thostent: Hostent, TServent: Servent,
|
||||||
TInAddr: InAddr, TIOVec: IOVec, TInPort: InPort, TInAddrT: InAddrT,
|
TInAddr: InAddr, TIOVec: IOVec, TInPort: InPort, TInAddrT: InAddrT,
|
||||||
TIn6Addr: In6Addr, TInAddrScalar: InAddrScalar, TProtoent: Protoent].}
|
TIn6Addr: In6Addr, TInAddrScalar: InAddrScalar, TProtoent: Protoent].}
|
||||||
|
|
@ -1662,6 +1663,8 @@ var
|
||||||
|
|
||||||
INET_ADDRSTRLEN* {.importc, header: "<netinet/in.h>".}: cint
|
INET_ADDRSTRLEN* {.importc, header: "<netinet/in.h>".}: cint
|
||||||
## 16. Length of the string form for IP.
|
## 16. Length of the string form for IP.
|
||||||
|
INET6_ADDRSTRLEN* {.importc, header: "<netinet/in.h>".}: cint
|
||||||
|
## Length of the string form for IPv6.
|
||||||
|
|
||||||
IPV6_JOIN_GROUP* {.importc, header: "<netinet/in.h>".}: cint
|
IPV6_JOIN_GROUP* {.importc, header: "<netinet/in.h>".}: cint
|
||||||
## Join a multicast group.
|
## Join a multicast group.
|
||||||
|
|
|
||||||
|
|
@ -1009,7 +1009,7 @@ else:
|
||||||
processTimers(p)
|
processTimers(p)
|
||||||
|
|
||||||
proc connect*(socket: AsyncFD, address: string, port: Port,
|
proc connect*(socket: AsyncFD, address: string, port: Port,
|
||||||
af = AF_INET): Future[void] =
|
af_unused = AF_INET): Future[void] =
|
||||||
var retFuture = newFuture[void]("connect")
|
var retFuture = newFuture[void]("connect")
|
||||||
|
|
||||||
proc cb(fd: AsyncFD): bool =
|
proc cb(fd: AsyncFD): bool =
|
||||||
|
|
@ -1017,7 +1017,8 @@ else:
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
var aiList = getAddrInfo(address, port, af)
|
var sockDomain = getSockDomain(socket.SocketHandle)
|
||||||
|
var aiList = getAddrInfo(address, port, sockDomain)
|
||||||
var success = false
|
var success = false
|
||||||
var lastError: OSErrorCode
|
var lastError: OSErrorCode
|
||||||
var it = aiList
|
var it = aiList
|
||||||
|
|
@ -1135,7 +1136,7 @@ else:
|
||||||
client: AsyncFD]]("acceptAddr")
|
client: AsyncFD]]("acceptAddr")
|
||||||
proc cb(sock: AsyncFD): bool =
|
proc cb(sock: AsyncFD): bool =
|
||||||
result = true
|
result = true
|
||||||
var sockAddress: SockAddr_in
|
var sockAddress: Sockaddr_storage
|
||||||
var addrLen = sizeof(sockAddress).Socklen
|
var addrLen = sizeof(sockAddress).Socklen
|
||||||
var client = accept(sock.SocketHandle,
|
var client = accept(sock.SocketHandle,
|
||||||
cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
|
cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
|
||||||
|
|
@ -1151,7 +1152,7 @@ else:
|
||||||
retFuture.fail(newException(OSError, osErrorMsg(lastError)))
|
retFuture.fail(newException(OSError, osErrorMsg(lastError)))
|
||||||
else:
|
else:
|
||||||
register(client.AsyncFD)
|
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)
|
addRead(socket, cb)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ proc newAsyncSocket*(fd: AsyncFD, buffered = true): AsyncSocket =
|
||||||
if buffered:
|
if buffered:
|
||||||
result.currPos = 0
|
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 =
|
protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket =
|
||||||
## Creates a new asynchronous socket.
|
## Creates a new asynchronous socket.
|
||||||
##
|
##
|
||||||
|
|
@ -423,24 +423,21 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.
|
||||||
## Binds ``address``:``port`` to the socket.
|
## Binds ``address``:``port`` to the socket.
|
||||||
##
|
##
|
||||||
## If ``address`` is "" then ADDR_ANY will be bound.
|
## If ``address`` is "" then ADDR_ANY will be bound.
|
||||||
|
var sockDomain = getSockDomain(socket.fd)
|
||||||
|
|
||||||
if address == "":
|
var realaddr = address
|
||||||
var name: Sockaddr_in
|
if realaddr == "":
|
||||||
when defined(Windows) or defined(nimdoc):
|
case sockDomain
|
||||||
name.sin_family = toInt(AF_INET).int16
|
of AF_INET6: realaddr = "::"
|
||||||
|
of AF_INET: realaddr = "0.0.0.0"
|
||||||
else:
|
else:
|
||||||
name.sin_family = toInt(AF_INET)
|
raiseOSError("Unknown socket address family and no address specified to bindAddr")
|
||||||
name.sin_port = htons(int16(port))
|
|
||||||
name.sin_addr.s_addr = htonl(INADDR_ANY)
|
var aiList = getAddrInfo(realaddr, port, sockDomain)
|
||||||
if bindAddr(socket.fd, cast[ptr SockAddr](addr(name)),
|
if bindAddr(socket.fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32:
|
||||||
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())
|
|
||||||
dealloc(aiList)
|
dealloc(aiList)
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
dealloc(aiList)
|
||||||
|
|
||||||
proc close*(socket: AsyncSocket) =
|
proc close*(socket: AsyncSocket) =
|
||||||
## Closes the socket.
|
## Closes the socket.
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ else:
|
||||||
EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET
|
EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET
|
||||||
|
|
||||||
export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
|
export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
|
||||||
|
Sockaddr_in6, Sockaddr_storage,
|
||||||
inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto
|
inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto
|
||||||
|
|
||||||
export
|
export
|
||||||
|
|
@ -194,6 +195,7 @@ proc getAddrInfo*(address: string, port: Port, af: Domain = AF_INET, typ: SockTy
|
||||||
hints.ai_family = toInt(af)
|
hints.ai_family = toInt(af)
|
||||||
hints.ai_socktype = toInt(typ)
|
hints.ai_socktype = toInt(typ)
|
||||||
hints.ai_protocol = toInt(prot)
|
hints.ai_protocol = toInt(prot)
|
||||||
|
hints.ai_flags = posix.AI_V4MAPPED
|
||||||
var gaiResult = getaddrinfo(address, $port, addr(hints), result)
|
var gaiResult = getaddrinfo(address, $port, addr(hints), result)
|
||||||
if gaiResult != 0'i32:
|
if gaiResult != 0'i32:
|
||||||
when useWinVersion:
|
when useWinVersion:
|
||||||
|
|
@ -315,6 +317,35 @@ proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =
|
||||||
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
||||||
result.length = int(s.h_length)
|
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 =
|
proc getSockName*(socket: SocketHandle): Port =
|
||||||
## returns the socket's associated port number.
|
## returns the socket's associated port number.
|
||||||
var name: Sockaddr_in
|
var name: Sockaddr_in
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue