Merge branch 'rbehrends-socket-address' into devel

This commit is contained in:
Dominik Picheta
2015-09-15 10:37:58 +01:00
3 changed files with 89 additions and 1 deletions

View File

@@ -533,6 +533,18 @@ proc getSockOpt*(socket: Socket, opt: SOBool, level = SOL_SOCKET): bool {.
var res = getSockOptInt(socket.fd, cint(level), toCInt(opt))
result = res != 0
proc getLocalAddr*(socket: Socket): (string, Port) =
## Get the socket's local address and port number.
##
## This is high-level interface for `getsockname`:idx:.
getLocalAddr(socket.fd, socket.domain)
proc getPeerAddr*(socket: Socket): (string, Port) =
## Get the socket's peer address and port number.
##
## This is high-level interface for `getpeername`:idx:.
getPeerAddr(socket.fd, socket.domain)
proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {.
tags: [WriteIOEffect].} =
## Sets option ``opt`` to a boolean value specified by ``value``.

View File

@@ -371,6 +371,76 @@ proc getSockName*(socket: SocketHandle): Port =
raiseOSError(osLastError())
result = Port(rawsockets.ntohs(name.sin_port))
proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
## returns the socket's local address and port number.
##
## Similar to POSIX's `getsockname`:idx:.
case domain
of AF_INET:
var name: Sockaddr_in
when useWinVersion:
name.sin_family = int16(ord(AF_INET))
else:
name.sin_family = posix.AF_INET
var namelen = sizeof(name).SockLen
if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port)))
of AF_INET6:
var name: Sockaddr_in6
when useWinVersion:
name.sin6_family = int16(ord(AF_INET6))
else:
name.sin6_family = posix.AF_INET6
var namelen = sizeof(name).SockLen
if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
var buf: array[64, char]
if inet_ntop(name.sin6_family.cint,
addr name, buf.cstring, sizeof(buf).int32).isNil:
raiseOSError(osLastError())
result = ($buf, Port(rawsockets.ntohs(name.sin6_port)))
else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
## returns the socket's peer address and port number.
##
## Similar to POSIX's `getpeername`:idx:
case domain
of AF_INET:
var name: Sockaddr_in
when useWinVersion:
name.sin_family = int16(ord(AF_INET))
else:
name.sin_family = posix.AF_INET
var namelen = sizeof(name).SockLen
if getpeername(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port)))
of AF_INET6:
var name: Sockaddr_in6
when useWinVersion:
name.sin6_family = int16(ord(AF_INET6))
else:
name.sin6_family = posix.AF_INET6
var namelen = sizeof(name).SockLen
if getpeername(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
var buf: array[64, char]
if inet_ntop(name.sin6_family.cint,
addr name, buf.cstring, sizeof(buf).int32).isNil:
raiseOSError(osLastError())
result = ($buf, Port(rawsockets.ntohs(name.sin6_port)))
else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
tags: [ReadIOEffect].} =
## getsockopt for integer options.

View File

@@ -409,7 +409,7 @@ type
bytes*: array[0..15, char]
Sockaddr_in6* {.importc: "SOCKADDR_IN6",
header: "winsock2.h".} = object
header: "ws2tcpip.h".} = object
sin6_family*: int16
sin6_port*: int16 # unsigned
sin6_flowinfo*: int32 # unsigned
@@ -511,6 +511,9 @@ proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
proc getsockname*(s: SocketHandle, name: ptr SockAddr,
namelen: ptr SockLen): cint {.
stdcall, importc: "getsockname", dynlib: ws2dll.}
proc getpeername*(s: SocketHandle, name: ptr SockAddr,
namelen: ptr SockLen): cint {.
stdcall, importc, dynlib: ws2dll.}
proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
optlen: ptr SockLen): cint {.
stdcall, importc: "getsockopt", dynlib: ws2dll.}
@@ -572,6 +575,9 @@ proc freeaddrinfo*(ai: ptr AddrInfo) {.
proc inet_ntoa*(i: InAddr): cstring {.
stdcall, importc, dynlib: ws2dll.}
proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
stringBufSize: int32): cstring {.stdcall, importc, dynlib: ws2dll.}
const
MAXIMUM_WAIT_OBJECTS* = 0x00000040