diff options
author | Araq <rumpf_a@web.de> | 2015-09-16 11:36:49 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-09-16 11:36:49 +0200 |
commit | c9a2fa54c7055c16892e9664dd64d8fc68918c07 (patch) | |
tree | b67fca3d93765f677de696f4f8b1ed50b031b164 /lib | |
parent | 1251fc76c32bdd50a3b9540e0cd80b0c435051ce (diff) | |
parent | d24eaf084b4be17e43f262d4127a91993ae6f7cd (diff) | |
download | Nim-c9a2fa54c7055c16892e9664dd64d8fc68918c07.tar.gz |
Merge branch 'devel' into fix_bracket_expr
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/json.nim | 13 | ||||
-rw-r--r-- | lib/pure/net.nim | 12 | ||||
-rw-r--r-- | lib/pure/rawsockets.nim | 70 | ||||
-rw-r--r-- | lib/system/repr.nim | 20 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 8 |
5 files changed, 117 insertions, 6 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 540a1a8eb..abf6305f2 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1074,9 +1074,9 @@ when not defined(js): ## for nice error messages. var p: JsonParser p.open(s, filename) + defer: p.close() discard getTok(p) # read first token result = p.parseJson() - p.close() proc parseJson*(buffer: string): JsonNode = ## Parses JSON from `buffer`. @@ -1203,6 +1203,17 @@ when isMainModule: testJson{["c", "d"]} = %true assert(testJson["c"]["d"].bval) + # make sure no memory leek when parsing invalid string + let startMemory = getOccupiedMem() + for i in 0 .. 10000: + try: + discard parseJson"""{ invalid""" + except: + discard + # memory diff should less than 2M + assert(abs(getOccupiedMem() - startMemory) < 2 * 1024 * 1024) + + # test `$` let stringified = $testJson let parsedAgain = parseJson(stringified) diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 141543c70..0ce5b4d25 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -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``. diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 7873e7226..f5860ef28 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -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. diff --git a/lib/system/repr.nim b/lib/system/repr.nim index b4188527f..1f81a0813 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -21,9 +21,22 @@ proc reprPointer(x: pointer): string {.compilerproc.} = return $buf proc `$`(x: uint64): string = - var buf: array [0..59, char] - discard c_sprintf(buf, "%llu", x) - return $buf + if x == 0: + result = "0" + else: + var buf: array [60, char] + var i = 0 + var n = x + while n != 0: + let nn = n div 10'u64 + buf[i] = char(n - 10'u64 * nn + ord('0')) + inc i + n = nn + + let half = i div 2 + # Reverse + for t in 0 .. < half: swap(buf[t], buf[i-t-1]) + result = $buf proc reprStrAux(result: var string, s: string) = if cast[pointer](s) == nil: @@ -294,4 +307,3 @@ when not defined(useNimRtl): reprAux(result, addr(p), typ, cl) add result, "\n" deinitReprClosure(cl) - diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 24015dd3a..84dac6d79 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 |