diff options
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/collections/LockFreeHash.nim | 2 | ||||
-rw-r--r-- | lib/pure/collections/sets.nim | 2 | ||||
-rw-r--r-- | lib/pure/colors.nim | 2 | ||||
-rw-r--r-- | lib/pure/concurrency/threadpool.nim | 6 | ||||
-rw-r--r-- | lib/pure/future.nim | 2 | ||||
-rw-r--r-- | lib/pure/json.nim | 10 | ||||
-rw-r--r-- | lib/pure/mersenne.nim | 2 | ||||
-rw-r--r-- | lib/pure/net.nim | 189 | ||||
-rw-r--r-- | lib/pure/os.nim | 8 | ||||
-rw-r--r-- | lib/pure/osproc.nim | 2 | ||||
-rw-r--r-- | lib/pure/selectors.nim | 10 |
11 files changed, 119 insertions, 116 deletions
diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim index 1d4471b21..a3ead81e3 100644 --- a/lib/pure/collections/LockFreeHash.nim +++ b/lib/pure/collections/LockFreeHash.nim @@ -1,6 +1,6 @@ #nim c -t:-march=i686 --cpu:amd64 --threads:on -d:release lockfreehash.nim -import unsigned, math, hashes +import math, hashes #------------------------------------------------------------------------------ ## Memory Utility Functions diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index abe9cf85e..9a42a21ee 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -951,7 +951,7 @@ when isMainModule and not defined(release): var b = initOrderedSet[int]() for x in [2, 4, 5]: b.incl(x) assert($a == $b) - assert(a == b) # https://github.com/Araq/Nimrod/issues/1413 + assert(a == b) # https://github.com/Araq/Nim/issues/1413 block initBlocks: var a: OrderedSet[int] diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim index 7328f7c24..f4c027576 100644 --- a/lib/pure/colors.nim +++ b/lib/pure/colors.nim @@ -6,7 +6,7 @@ # distribution, for details about the copyright. # -## This module implements color handling for Nimrod. It is used by +## This module implements color handling for Nim. It is used by ## the ``graphics`` module. import strutils diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index 2603835dd..a30d49889 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -328,10 +328,10 @@ proc distinguishedSlave(w: ptr Worker) {.thread.} = if w.q.len != 0: w.cleanFlowVars var - workers: array[MaxThreadPoolSize, TThread[ptr Worker]] + workers: array[MaxThreadPoolSize, Thread[ptr Worker]] workersData: array[MaxThreadPoolSize, Worker] - distinguished: array[MaxDistinguishedThread, TThread[ptr Worker]] + distinguished: array[MaxDistinguishedThread, Thread[ptr Worker]] distinguishedData: array[MaxDistinguishedThread, Worker] when defined(nimPinToCpu): @@ -468,7 +468,7 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} = await(gSomeReady) var - distinguishedLock: TLock + distinguishedLock: Lock initLock distinguishedLock diff --git a/lib/pure/future.nim b/lib/pure/future.nim index 4767266e5..3793edc8b 100644 --- a/lib/pure/future.nim +++ b/lib/pure/future.nim @@ -134,7 +134,7 @@ macro `[]`*(lc: ListComprehension, comp, typ: expr): expr = ## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is ## the type that will be stored inside the result seq. ## - ## .. code-block:: nimrod + ## .. code-block:: nim ## ## echo lc[x | (x <- 1..10, x mod 2 == 0), int] ## diff --git a/lib/pure/json.nim b/lib/pure/json.nim index ab7d18bd8..f672a0c1b 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -712,17 +712,21 @@ proc `%`*(elements: openArray[JsonNode]): JsonNode = proc toJson(x: NimNode): NimNode {.compiletime.} = case x.kind - of nnkBracket: + of nnkBracket: # array result = newNimNode(nnkBracket) for i in 0 .. <x.len: result.add(toJson(x[i])) - of nnkTableConstr: + of nnkTableConstr: # object result = newNimNode(nnkTableConstr) for i in 0 .. <x.len: - assert x[i].kind == nnkExprColonExpr + x[i].expectKind nnkExprColonExpr result.add(newNimNode(nnkExprColonExpr).add(x[i][0]).add(toJson(x[i][1]))) + of nnkCurly: # empty object + result = newNimNode(nnkTableConstr) + x.expectLen(0) + else: result = x diff --git a/lib/pure/mersenne.nim b/lib/pure/mersenne.nim index c8090dc6a..ae0845714 100644 --- a/lib/pure/mersenne.nim +++ b/lib/pure/mersenne.nim @@ -1,5 +1,3 @@ -import unsigned - type MersenneTwister* = object mt: array[0..623, uint32] diff --git a/lib/pure/net.nim b/lib/pure/net.nim index c3a65fef1..346b656a0 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -102,8 +102,7 @@ type ## case of IPv4 {.deprecated: [TIpAddress: IpAddress].} -proc isIpAddress*(address_str: string): bool {.tags: [].} -proc parseIpAddress*(address_str: string): IpAddress + proc socketError*(socket: Socket, err: int = -1, async = false, lastError = (-1).OSErrorCode): void @@ -548,40 +547,6 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) { var valuei = cint(if value: 1 else: 0) setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei) -proc connect*(socket: Socket, address: string, - port = Port(0)) {.tags: [ReadIOEffect].} = - ## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a - ## host name. If ``address`` is a host name, this function will try each IP - ## of that host name. ``htons`` is already performed on ``port`` so you must - ## not do it. - ## - ## If ``socket`` is an SSL socket a handshake will be automatically performed. - var aiList = getAddrInfo(address, port, socket.domain) - # try all possibilities: - var success = false - var lastError: OSErrorCode - var it = aiList - while it != nil: - if connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) == 0'i32: - success = true - break - else: lastError = osLastError() - it = it.ai_next - - dealloc(aiList) - if not success: raiseOSError(lastError) - - when defined(ssl): - if socket.isSSL: - # RFC3546 for SNI specifies that IP addresses are not allowed. - if not isIpAddress(address): - # Discard result in case OpenSSL version doesn't support SNI, or we're - # not using TLSv1+ - discard SSL_set_tlsext_host_name(socket.sslHandle, address) - - let ret = SSLConnect(socket.sslHandle) - socketError(socket, ret) - when defined(ssl): proc handshake*(socket: Socket): bool {.tags: [ReadIOEffect, WriteIOEffect].} = ## This proc needs to be called on a socket after it connects. This is @@ -971,61 +936,6 @@ proc sendTo*(socket: Socket, address: string, port: Port, ## This is the high-level version of the above ``sendTo`` function. result = socket.sendTo(address, port, cstring(data), data.len) -proc connectAsync(socket: Socket, name: string, port = Port(0), - af: Domain = AF_INET) {.tags: [ReadIOEffect].} = - ## A variant of ``connect`` for non-blocking sockets. - ## - ## This procedure will immediately return, it will not block until a connection - ## is made. It is up to the caller to make sure the connection has been established - ## by checking (using ``select``) whether the socket is writeable. - ## - ## **Note**: For SSL sockets, the ``handshake`` procedure must be called - ## whenever the socket successfully connects to a server. - var aiList = getAddrInfo(name, port, af) - # try all possibilities: - var success = false - var lastError: OSErrorCode - var it = aiList - while it != nil: - var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) - if ret == 0'i32: - success = true - break - else: - lastError = osLastError() - when useWinVersion: - # Windows EINTR doesn't behave same as POSIX. - if lastError.int32 == WSAEWOULDBLOCK: - success = true - break - else: - if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: - success = true - break - - it = it.ai_next - - dealloc(aiList) - if not success: raiseOSError(lastError) - -proc connect*(socket: Socket, address: string, port = Port(0), - timeout: int) {.tags: [ReadIOEffect, WriteIOEffect].} = - ## Connects to server as specified by ``address`` on port specified by ``port``. - ## - ## The ``timeout`` paremeter specifies the time in milliseconds to allow for - ## the connection to the server to be made. - socket.fd.setBlocking(false) - - socket.connectAsync(address, port, socket.domain) - var s = @[socket.fd] - if selectWrite(s, timeout) != 1: - raise newException(TimeoutError, "Call to 'connect' timed out.") - else: - when defined(ssl): - if socket.isSSL: - socket.fd.setBlocking(true) - doAssert socket.handshake() - socket.fd.setBlocking(true) proc isSsl*(socket: Socket): bool = ## Determines whether ``socket`` is a SSL socket. @@ -1295,7 +1205,8 @@ proc parseIPv6Address(address_str: string): IpAddress = raise newException(ValueError, "Invalid IP Address. The address consists of too many groups") -proc parseIpAddress(address_str: string): IpAddress = + +proc parseIpAddress*(address_str: string): IpAddress = ## Parses an IP address ## Raises EInvalidValue on error if address_str == nil: @@ -1305,8 +1216,7 @@ proc parseIpAddress(address_str: string): IpAddress = else: return parseIPv4Address(address_str) - -proc isIpAddress(address_str: string): bool = +proc isIpAddress*(address_str: string): bool {.tags: [].} = ## Checks if a string is an IP address ## Returns true if it is, false otherwise try: @@ -1314,3 +1224,94 @@ proc isIpAddress(address_str: string): bool = except ValueError: return false return true + + +proc connect*(socket: Socket, address: string, + port = Port(0)) {.tags: [ReadIOEffect].} = + ## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a + ## host name. If ``address`` is a host name, this function will try each IP + ## of that host name. ``htons`` is already performed on ``port`` so you must + ## not do it. + ## + ## If ``socket`` is an SSL socket a handshake will be automatically performed. + var aiList = getAddrInfo(address, port, socket.domain) + # try all possibilities: + var success = false + var lastError: OSErrorCode + var it = aiList + while it != nil: + if connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) == 0'i32: + success = true + break + else: lastError = osLastError() + it = it.ai_next + + dealloc(aiList) + if not success: raiseOSError(lastError) + + when defined(ssl): + if socket.isSSL: + # RFC3546 for SNI specifies that IP addresses are not allowed. + if not isIpAddress(address): + # Discard result in case OpenSSL version doesn't support SNI, or we're + # not using TLSv1+ + discard SSL_set_tlsext_host_name(socket.sslHandle, address) + + let ret = SSLConnect(socket.sslHandle) + socketError(socket, ret) + +proc connectAsync(socket: Socket, name: string, port = Port(0), + af: Domain = AF_INET) {.tags: [ReadIOEffect].} = + ## A variant of ``connect`` for non-blocking sockets. + ## + ## This procedure will immediately return, it will not block until a connection + ## is made. It is up to the caller to make sure the connection has been established + ## by checking (using ``select``) whether the socket is writeable. + ## + ## **Note**: For SSL sockets, the ``handshake`` procedure must be called + ## whenever the socket successfully connects to a server. + var aiList = getAddrInfo(name, port, af) + # try all possibilities: + var success = false + var lastError: OSErrorCode + var it = aiList + while it != nil: + var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.SockLen) + if ret == 0'i32: + success = true + break + else: + lastError = osLastError() + when useWinVersion: + # Windows EINTR doesn't behave same as POSIX. + if lastError.int32 == WSAEWOULDBLOCK: + success = true + break + else: + if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: + success = true + break + + it = it.ai_next + + dealloc(aiList) + if not success: raiseOSError(lastError) + +proc connect*(socket: Socket, address: string, port = Port(0), + timeout: int) {.tags: [ReadIOEffect, WriteIOEffect].} = + ## Connects to server as specified by ``address`` on port specified by ``port``. + ## + ## The ``timeout`` paremeter specifies the time in milliseconds to allow for + ## the connection to the server to be made. + socket.fd.setBlocking(false) + + socket.connectAsync(address, port, socket.domain) + var s = @[socket.fd] + if selectWrite(s, timeout) != 1: + raise newException(TimeoutError, "Call to 'connect' timed out.") + else: + when defined(ssl): + if socket.isSSL: + socket.fd.setBlocking(true) + doAssert socket.handshake() + socket.fd.setBlocking(true) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 1e00f92b1..a92b74484 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -774,6 +774,7 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = res: int res = findFirstFile(pattern, f) if res != -1: + defer: findClose(res) while true: if not skipFindData(f) and (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) == 0'i32: @@ -786,7 +787,6 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = pattern[dotPos+1] == '*': yield splitFile(pattern).dir / extractFilename(ff) if findNextFile(res, f) == 0'i32: break - findClose(res) else: # here we use glob var f: Glob @@ -795,11 +795,11 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} = f.gl_pathc = 0 f.gl_pathv = nil res = glob(pattern, 0, nil, addr(f)) + defer: globfree(addr(f)) if res == 0: for i in 0.. f.gl_pathc - 1: assert(f.gl_pathv[i] != nil) yield $f.gl_pathv[i] - globfree(addr(f)) type PathComponent* = enum ## Enumeration specifying a path component. @@ -845,6 +845,7 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: var f: WIN32_FIND_DATA var h = findFirstFile(dir / "*", f) if h != -1: + defer: findClose(h) while true: var k = pcFile if not skipFindData(f): @@ -856,10 +857,10 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: else: dir / extractFilename(getFilename(f)) yield (k, xx) if findNextFile(h, f) == 0'i32: break - findClose(h) else: var d = opendir(dir) if d != nil: + defer: discard closedir(d) while true: var x = readdir(d) if x == nil: break @@ -883,7 +884,6 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: if S_ISDIR(s.st_mode): k = pcDir if S_ISLNK(s.st_mode): k = succ(k) yield (k, y) - discard closedir(d) iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. tags: [ReadDirEffect].} = diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 34fb81520..38b0ed4a3 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -876,7 +876,7 @@ elif not defined(useNimRtl): let sizeRead = read(data.pErrorPipe[readIdx], addr error, sizeof(error)) if sizeRead == sizeof(error): raiseOSError("Could not find command: '$1'. OS error: $2" % - [$data.sysCommand, $strerror(error)]) + [$data.sysCommand, $strerror(error)]) return pid diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 832f5f4f9..89e92c133 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -9,7 +9,7 @@ # TODO: Docs. -import os, unsigned, hashes +import os, hashes when defined(linux): import posix, epoll @@ -118,7 +118,7 @@ elif defined(linux): # are therefore constantly ready. (leading to 100% CPU usage). if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0: raiseOSError(osLastError()) - s.fds.mget(fd).events = events + s.fds[fd].events = events else: var event = createEventStruct(events, fd) if s.fds[fd].events == {}: @@ -129,7 +129,7 @@ elif defined(linux): else: if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fd, addr(event)) != 0: raiseOSError(osLastError()) - s.fds.mget(fd).events = events + s.fds[fd].events = events proc unregister*(s: var Selector, fd: SocketHandle) = if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fd, nil) != 0: @@ -229,7 +229,7 @@ elif defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd): modifyKQueue(s.kqFD, fd, event, EV_ADD) for event in previousEvents-events: modifyKQueue(s.kqFD, fd, event, EV_DELETE) - s.fds.mget(fd).events = events + s.fds[fd].events = events proc unregister*(s: var Selector, fd: SocketHandle) = for event in s.fds[fd].events: @@ -298,7 +298,7 @@ elif not defined(nimdoc): proc update*(s: var Selector, fd: SocketHandle, events: set[Event]) = #if not s.fds.hasKey(fd): # raise newException(ValueError, "File descriptor not found.") - s.fds.mget(fd).events = events + s.fds[fd].events = events proc unregister*(s: var Selector, fd: SocketHandle) = s.fds.del(fd) |