Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
commit
8b0ea4b501
12 changed files with 122 additions and 12 deletions
|
|
@ -433,6 +433,9 @@ const POSIX_MADV_WILLNEED* = cint(3)
|
||||||
const POSIX_MADV_DONTNEED* = cint(4)
|
const POSIX_MADV_DONTNEED* = cint(4)
|
||||||
const MAP_POPULATE* = cint(32768)
|
const MAP_POPULATE* = cint(32768)
|
||||||
|
|
||||||
|
# <sys/resource.h>
|
||||||
|
const RLIMIT_NOFILE* = cint(7)
|
||||||
|
|
||||||
# <sys/select.h>
|
# <sys/select.h>
|
||||||
const FD_SETSIZE* = cint(1024)
|
const FD_SETSIZE* = cint(1024)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -451,6 +451,9 @@ var POSIX_TYPED_MEM_ALLOCATE* {.importc: "POSIX_TYPED_MEM_ALLOCATE", header: "<s
|
||||||
var POSIX_TYPED_MEM_ALLOCATE_CONTIG* {.importc: "POSIX_TYPED_MEM_ALLOCATE_CONTIG", header: "<sys/mman.h>".}: cint
|
var POSIX_TYPED_MEM_ALLOCATE_CONTIG* {.importc: "POSIX_TYPED_MEM_ALLOCATE_CONTIG", header: "<sys/mman.h>".}: cint
|
||||||
var POSIX_TYPED_MEM_MAP_ALLOCATABLE* {.importc: "POSIX_TYPED_MEM_MAP_ALLOCATABLE", header: "<sys/mman.h>".}: cint
|
var POSIX_TYPED_MEM_MAP_ALLOCATABLE* {.importc: "POSIX_TYPED_MEM_MAP_ALLOCATABLE", header: "<sys/mman.h>".}: cint
|
||||||
|
|
||||||
|
# <sys/resource.h>
|
||||||
|
var RLIMIT_NOFILE* {.importc: "RLIMIT_NOFILE", header: "<sys/resource.h>".}: cint
|
||||||
|
|
||||||
# <sys/select.h>
|
# <sys/select.h>
|
||||||
var FD_SETSIZE* {.importc: "FD_SETSIZE", header: "<sys/select.h>".}: cint
|
var FD_SETSIZE* {.importc: "FD_SETSIZE", header: "<sys/select.h>".}: cint
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,6 @@ when not defined(android):
|
||||||
proc signalfd(fd: cint, mask: var Sigset, flags: cint): cint
|
proc signalfd(fd: cint, mask: var Sigset, flags: cint): cint
|
||||||
{.cdecl, importc: "signalfd", header: "<sys/signalfd.h>".}
|
{.cdecl, importc: "signalfd", header: "<sys/signalfd.h>".}
|
||||||
|
|
||||||
var RLIMIT_NOFILE {.importc: "RLIMIT_NOFILE",
|
|
||||||
header: "<sys/resource.h>".}: cint
|
|
||||||
type
|
type
|
||||||
RLimit {.importc: "struct rlimit",
|
RLimit {.importc: "struct rlimit",
|
||||||
header: "<sys/resource.h>", pure, final.} = object
|
header: "<sys/resource.h>", pure, final.} = object
|
||||||
|
|
@ -82,7 +80,7 @@ type
|
||||||
proc newSelector*[T](): Selector[T] =
|
proc newSelector*[T](): Selector[T] =
|
||||||
# Retrieve the maximum fd count (for current OS) via getrlimit()
|
# Retrieve the maximum fd count (for current OS) via getrlimit()
|
||||||
var a = RLimit()
|
var a = RLimit()
|
||||||
if getrlimit(RLIMIT_NOFILE, a) != 0:
|
if getrlimit(posix.RLIMIT_NOFILE, a) != 0:
|
||||||
raiseOsError(osLastError())
|
raiseOsError(osLastError())
|
||||||
var maxFD = int(a.rlim_max)
|
var maxFD = int(a.rlim_max)
|
||||||
doAssert(maxFD > 0)
|
doAssert(maxFD > 0)
|
||||||
|
|
@ -528,4 +526,4 @@ template withData*[T](s: Selector[T], fd: SocketHandle|int, value, body1,
|
||||||
body2
|
body2
|
||||||
|
|
||||||
proc getFd*[T](s: Selector[T]): int =
|
proc getFd*[T](s: Selector[T]): int =
|
||||||
return s.epollFd.int
|
return s.epollFd.int
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,6 @@ type
|
||||||
wfd: cint
|
wfd: cint
|
||||||
SelectEvent* = ptr SelectEventImpl
|
SelectEvent* = ptr SelectEventImpl
|
||||||
|
|
||||||
var RLIMIT_NOFILE {.importc: "RLIMIT_NOFILE",
|
|
||||||
header: "<sys/resource.h>".}: cint
|
|
||||||
type
|
type
|
||||||
rlimit {.importc: "struct rlimit",
|
rlimit {.importc: "struct rlimit",
|
||||||
header: "<sys/resource.h>", pure, final.} = object
|
header: "<sys/resource.h>", pure, final.} = object
|
||||||
|
|
@ -64,7 +62,7 @@ else:
|
||||||
|
|
||||||
proc newSelector*[T](): Selector[T] =
|
proc newSelector*[T](): Selector[T] =
|
||||||
var a = rlimit()
|
var a = rlimit()
|
||||||
if getrlimit(RLIMIT_NOFILE, a) != 0:
|
if getrlimit(posix.RLIMIT_NOFILE, a) != 0:
|
||||||
raiseIOSelectorsError(osLastError())
|
raiseIOSelectorsError(osLastError())
|
||||||
var maxFD = int(a.rlim_max)
|
var maxFD = int(a.rlim_max)
|
||||||
|
|
||||||
|
|
@ -317,4 +315,4 @@ template withData*[T](s: Selector[T], fd: SocketHandle|int, value, body1,
|
||||||
|
|
||||||
|
|
||||||
proc getFd*[T](s: Selector[T]): int =
|
proc getFd*[T](s: Selector[T]): int =
|
||||||
return -1
|
return -1
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ else:
|
||||||
export Sockaddr_storage, Sockaddr_un, Sockaddr_un_path_length
|
export Sockaddr_storage, Sockaddr_un, Sockaddr_un_path_length
|
||||||
|
|
||||||
export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
|
export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
|
||||||
Sockaddr_in6,
|
Sockaddr_in6, Sockaddr_storage,
|
||||||
inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto,
|
inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto,
|
||||||
freeAddrInfo
|
freeAddrInfo
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -414,6 +414,43 @@ proc isIpAddress*(address_str: string): bool {.tags: [].} =
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
proc toSockAddr*(address: IpAddress, port: Port, sa: var Sockaddr_storage, sl: var Socklen) =
|
||||||
|
## Converts `IpAddress` and `Port` to `SockAddr` and `Socklen`
|
||||||
|
let port = htons(uint16(port))
|
||||||
|
case address.family
|
||||||
|
of IpAddressFamily.IPv4:
|
||||||
|
sl = sizeof(Sockaddr_in).Socklen
|
||||||
|
let s = cast[ptr Sockaddr_in](addr sa)
|
||||||
|
s.sin_family = type(s.sin_family)(AF_INET)
|
||||||
|
s.sin_port = port
|
||||||
|
copyMem(addr s.sin_addr, unsafeAddr address.address_v4[0], sizeof(s.sin_addr))
|
||||||
|
of IpAddressFamily.IPv6:
|
||||||
|
sl = sizeof(Sockaddr_in6).Socklen
|
||||||
|
let s = cast[ptr Sockaddr_in6](addr sa)
|
||||||
|
s.sin6_family = type(s.sin6_family)(AF_INET6)
|
||||||
|
s.sin6_port = port
|
||||||
|
copyMem(addr s.sin6_addr, unsafeAddr address.address_v6[0], sizeof(s.sin6_addr))
|
||||||
|
|
||||||
|
proc fromSockAddrAux(sa: ptr Sockaddr_storage, sl: Socklen, address: var IpAddress, port: var Port) =
|
||||||
|
if sa.ss_family.int == AF_INET.int and sl == sizeof(Sockaddr_in).Socklen:
|
||||||
|
address = IpAddress(family: IpAddressFamily.IPv4)
|
||||||
|
let s = cast[ptr Sockaddr_in](sa)
|
||||||
|
copyMem(addr address.address_v4[0], addr s.sin_addr, sizeof(address.address_v4))
|
||||||
|
port = ntohs(s.sin_port).Port
|
||||||
|
elif sa.ss_family.int == AF_INET6.int and sl == sizeof(Sockaddr_in6).Socklen:
|
||||||
|
address = IpAddress(family: IpAddressFamily.IPv6)
|
||||||
|
let s = cast[ptr Sockaddr_in6](sa)
|
||||||
|
copyMem(addr address.address_v6[0], addr s.sin6_addr, sizeof(address.address_v6))
|
||||||
|
port = ntohs(s.sin6_port).Port
|
||||||
|
else:
|
||||||
|
raise newException(ValueError, "Neither IPv4 nor IPv6")
|
||||||
|
|
||||||
|
proc fromSockAddr*(sa: Sockaddr_storage | SockAddr | Sockaddr_in | Sockaddr_in6,
|
||||||
|
sl: Socklen, address: var IpAddress, port: var Port) {.inline.} =
|
||||||
|
## Converts `SockAddr` and `Socklen` to `IpAddress` and `Port`. Raises
|
||||||
|
## `ObjectConversionError` in case of invalid `sa` and `sl` arguments.
|
||||||
|
fromSockAddrAux(unsafeAddr sa, sl, address, port)
|
||||||
|
|
||||||
when defineSsl:
|
when defineSsl:
|
||||||
CRYPTO_malloc_init()
|
CRYPTO_malloc_init()
|
||||||
doAssert SslLibraryInit() == 1
|
doAssert SslLibraryInit() == 1
|
||||||
|
|
|
||||||
|
|
@ -494,7 +494,7 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES).cint
|
||||||
sa.lpSecurityDescriptor = nil
|
sa.lpSecurityDescriptor = nil
|
||||||
sa.bInheritHandle = 1
|
sa.bInheritHandle = 1
|
||||||
if createPipe(rdHandle, wrHandle, sa, 1024) == 0'i32:
|
if createPipe(rdHandle, wrHandle, sa, 0) == 0'i32:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
proc fileClose(h: Handle) {.inline.} =
|
proc fileClose(h: Handle) {.inline.} =
|
||||||
|
|
@ -524,6 +524,12 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
he = ho
|
he = ho
|
||||||
else:
|
else:
|
||||||
createPipeHandles(he, si.hStdError)
|
createPipeHandles(he, si.hStdError)
|
||||||
|
if setHandleInformation(he, DWORD(1), DWORD(0)) == 0'i32:
|
||||||
|
raiseOsError(osLastError())
|
||||||
|
if setHandleInformation(hi, DWORD(1), DWORD(0)) == 0'i32:
|
||||||
|
raiseOsError(osLastError())
|
||||||
|
if setHandleInformation(ho, DWORD(1), DWORD(0)) == 0'i32:
|
||||||
|
raiseOsError(osLastError())
|
||||||
else:
|
else:
|
||||||
createAllPipeHandles(si, hi, ho, he, cast[int](result))
|
createAllPipeHandles(si, hi, ho, he, cast[int](result))
|
||||||
result.inHandle = FileHandle(hi)
|
result.inHandle = FileHandle(hi)
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,18 @@ proc toTime*(dt: DateTime): Time {.tags: [], raises: [], benign.} =
|
||||||
# so we need to compensate for that here.
|
# so we need to compensate for that here.
|
||||||
result.inc dt.utcOffset
|
result.inc dt.utcOffset
|
||||||
|
|
||||||
|
proc `<`*(a, b: DateTime): bool =
|
||||||
|
## Returns true iff ``a < b``, that is iff a happened before b.
|
||||||
|
return a.toTime < b.toTime
|
||||||
|
|
||||||
|
proc `<=` * (a, b: DateTime): bool =
|
||||||
|
## Returns true iff ``a <= b``.
|
||||||
|
return a.toTime <= b.toTime
|
||||||
|
|
||||||
|
proc `==`*(a, b: DateTime): bool =
|
||||||
|
## Returns true if ``a == b``, that is if both dates represent the same point in datetime.
|
||||||
|
return a.toTime == b.toTime
|
||||||
|
|
||||||
proc initDateTime(zt: ZonedTime, zone: Timezone): DateTime =
|
proc initDateTime(zt: ZonedTime, zone: Timezone): DateTime =
|
||||||
let adjTime = zt.adjTime.int64
|
let adjTime = zt.adjTime.int64
|
||||||
let epochday = (if adjTime >= 0: adjTime else: adjTime - (secondsInDay - 1)) div secondsInDay
|
let epochday = (if adjTime >= 0: adjTime else: adjTime - (secondsInDay - 1)) div secondsInDay
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,13 @@ type
|
||||||
sin6_flowinfo*: int32 # unsigned
|
sin6_flowinfo*: int32 # unsigned
|
||||||
sin6_addr*: In6_addr
|
sin6_addr*: In6_addr
|
||||||
|
|
||||||
|
Sockaddr_storage* {.importc: "SOCKADDR_STORAGE",
|
||||||
|
header: "winsock2.h".} = object
|
||||||
|
ss_family*: int16
|
||||||
|
ss_pad1: array[6, byte]
|
||||||
|
ss_align: int64
|
||||||
|
ss_pad2: array[112, byte]
|
||||||
|
|
||||||
Servent* = object
|
Servent* = object
|
||||||
s_name*: cstring
|
s_name*: cstring
|
||||||
s_aliases*: cstringArray
|
s_aliases*: cstringArray
|
||||||
|
|
@ -697,6 +704,11 @@ proc duplicateHandle*(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE,
|
||||||
dwDesiredAccess: DWORD, bInheritHandle: WINBOOL,
|
dwDesiredAccess: DWORD, bInheritHandle: WINBOOL,
|
||||||
dwOptions: DWORD): WINBOOL{.stdcall, dynlib: "kernel32",
|
dwOptions: DWORD): WINBOOL{.stdcall, dynlib: "kernel32",
|
||||||
importc: "DuplicateHandle".}
|
importc: "DuplicateHandle".}
|
||||||
|
|
||||||
|
proc setHandleInformation*(hObject: HANDLE, dwMask: DWORD,
|
||||||
|
dwFlags: DWORD): WINBOOL {.stdcall,
|
||||||
|
dynlib: "kernel32", importc: "SetHandleInformation".}
|
||||||
|
|
||||||
proc getCurrentProcess*(): HANDLE{.stdcall, dynlib: "kernel32",
|
proc getCurrentProcess*(): HANDLE{.stdcall, dynlib: "kernel32",
|
||||||
importc: "GetCurrentProcess".}
|
importc: "GetCurrentProcess".}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import net
|
import net, nativesockets
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
suite "isIpAddress tests":
|
suite "isIpAddress tests":
|
||||||
|
|
@ -45,3 +45,33 @@ suite "parseIpAddress tests":
|
||||||
test "invalid ipv6":
|
test "invalid ipv6":
|
||||||
expect(ValueError):
|
expect(ValueError):
|
||||||
discard parseIpAddress("gggg:cdba:0000:0000:0000:0000:3257:9652")
|
discard parseIpAddress("gggg:cdba:0000:0000:0000:0000:3257:9652")
|
||||||
|
|
||||||
|
block: # "IpAddress/Sockaddr conversion"
|
||||||
|
proc test(ipaddrstr: string) =
|
||||||
|
var ipaddr_1 = parseIpAddress(ipaddrstr)
|
||||||
|
# echo ipaddrstr, " ", $ipaddr_1
|
||||||
|
|
||||||
|
doAssert($ipaddrstr == $ipaddr_1)
|
||||||
|
|
||||||
|
var sockaddr: Sockaddr_storage
|
||||||
|
var socklen: Socklen
|
||||||
|
var ipaddr_2: IpAddress
|
||||||
|
var port_2: Port
|
||||||
|
|
||||||
|
toSockAddr(ipaddr_1, Port(0), sockaddr, socklen)
|
||||||
|
fromSockAddr(sockaddr, socklen, ipaddr_2, port_2)
|
||||||
|
|
||||||
|
doAssert(ipaddrstr == $ipaddr_1)
|
||||||
|
|
||||||
|
doAssert(ipaddr_1 == ipaddr_2)
|
||||||
|
doAssert($ipaddr_1 == $ipaddr_2)
|
||||||
|
|
||||||
|
|
||||||
|
# ipv6 address of example.com
|
||||||
|
test("2606:2800:220:1:248:1893:25c8:1946")
|
||||||
|
# ipv6 address of localhost
|
||||||
|
test("::1")
|
||||||
|
# ipv4 address of example.com
|
||||||
|
test("93.184.216.34")
|
||||||
|
# ipv4 address of localhost
|
||||||
|
test("127.0.0.1")
|
||||||
|
|
|
||||||
|
|
@ -367,4 +367,12 @@ suite "ttimes":
|
||||||
check $(dt - 1.months) == "2017-02-15T00:00:00+00:00"
|
check $(dt - 1.months) == "2017-02-15T00:00:00+00:00"
|
||||||
dt = initDateTime(31, mMar, 2017, 00, 00, 00, utc())
|
dt = initDateTime(31, mMar, 2017, 00, 00, 00, utc())
|
||||||
# This happens due to monthday overflow. It's consistent with Phobos.
|
# This happens due to monthday overflow. It's consistent with Phobos.
|
||||||
check $(dt - 1.months) == "2017-03-03T00:00:00+00:00"
|
check $(dt - 1.months) == "2017-03-03T00:00:00+00:00"
|
||||||
|
|
||||||
|
test "compare datetimes":
|
||||||
|
var dt1 = now()
|
||||||
|
var dt2 = dt1
|
||||||
|
check dt1 == dt2
|
||||||
|
check dt1 <= dt2
|
||||||
|
dt2 = dt2 + 1.seconds
|
||||||
|
check dt1 < dt2
|
||||||
|
|
|
||||||
|
|
@ -586,6 +586,9 @@ v("POSIX_TYPED_MEM_ALLOCATE_CONTIG")
|
||||||
v("POSIX_TYPED_MEM_MAP_ALLOCATABLE")
|
v("POSIX_TYPED_MEM_MAP_ALLOCATABLE")
|
||||||
v("MAP_POPULATE", no_other = true)
|
v("MAP_POPULATE", no_other = true)
|
||||||
|
|
||||||
|
header("<sys/resource.h>")
|
||||||
|
v("RLIMIT_NOFILE")
|
||||||
|
|
||||||
header("<sys/select.h>")
|
header("<sys/select.h>")
|
||||||
v("FD_SETSIZE")
|
v("FD_SETSIZE")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue