From b9df1323f7c117f0159e3afb26d5a3de83506f96 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Mon, 14 Sep 2015 01:42:46 +0200 Subject: [PATCH 1/2] Provide access to getsockname()/getpeername(). This patch implements procedures getLocalAddr() and getPeerAddr() that return the results of getsockname() and getpeername(), respectively, as pairs (string, Port) for both Socket and SockedHandle. --- lib/pure/net.nim | 8 +++++ lib/pure/rawsockets.nim | 66 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 141543c703..b7a40121fa 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -533,6 +533,14 @@ 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 + getLocalAddr(socket.fd, socket.domain) + +proc getPeerAddr*(socket: Socket): (string, Port) = + ## Get the socket's peer address and port number + 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``. diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 7873e7226a..0a69b580e5 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -371,6 +371,72 @@ 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. + 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. + 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. From 4da5e474148db9298ec0d730046544278d7e6827 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Tue, 15 Sep 2015 10:37:16 +0100 Subject: [PATCH 2/2] Implements getPeerAddr/getPeerName on Windows and adds IDX. --- lib/pure/net.nim | 8 ++++++-- lib/pure/rawsockets.nim | 4 ++++ lib/windows/winlean.nim | 8 +++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index b7a40121fa..0ce5b4d25d 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -534,11 +534,15 @@ proc getSockOpt*(socket: Socket, opt: SOBool, level = SOL_SOCKET): bool {. result = res != 0 proc getLocalAddr*(socket: Socket): (string, Port) = - ## Get the socket's local address and port number + ## 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 + ## 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) {. diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 0a69b580e5..f5860ef282 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -373,6 +373,8 @@ proc getSockName*(socket: SocketHandle): 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 @@ -406,6 +408,8 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) = 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 diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 24015dd3a6..84dac6d798 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -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