Add Zephyr Support (#19003)
* Porting Nim to run on Zephyr.
Includes changes to `std/net`.
Squashed commit of the following:
tweaking more memory / malloc things
revert back bitmasks
tweaking nim to use kernel heap as C malloc doesn't work
fixing socket polling on zephyr
cleanup getting maximum sockets for process or for rtos'es
reorganizing and fixing net for async / system
merge netlite changes back into nativesockets
merge netlite changes back into nativesockets
reverting native sockets back
tweaking nim / zephyr network
adding option to run 'net-lite' from linux
bridging zephyr's max connections
fixing net errors
fixing compilation with getAddrString
fixing compilation with getAddrString
experimenting with a nativesockets_lite ... getAddrString
experimenting with a nativesockets_lite ... getAddrString
experimenting with a nativesockets_lite ... getLocalAddr
experimenting with a nativesockets_lite ... getLocalAddr
experimenting with a nativesockets_lite ...
add note regarding incorrect FreeRTOS Sockadd_in fields
changing to NIM_STATIC_ASSERT
cleaning up the static_assert error messages
cleaning up the static_assert error messages
setting up static assert ftw!
testing compile time asserts
reworking Sockaddr objects to more closely match various platforms
reworking Sockaddr objects to more closely match various platforms
reworking Sockaddr objects to more closely match various platforms
finding missing items (issue #18684)
fixup posix constants (issue #18684)
adding plumbing for zephyr os (issue #18684)
adding plumbing for zephyr os (issue #18684)
* fixing constant capitalizations
* remove extra debug prints and fix TSa_Family/cint issue
* remove extra debug prints and fix TSa_Family/cint issue
* Porting Nim to run on Zephyr.
Includes changes to `std/net`.
Squashed commit of the following:
tweaking more memory / malloc things
revert back bitmasks
tweaking nim to use kernel heap as C malloc doesn't work
fixing socket polling on zephyr
cleanup getting maximum sockets for process or for rtos'es
reorganizing and fixing net for async / system
merge netlite changes back into nativesockets
merge netlite changes back into nativesockets
reverting native sockets back
tweaking nim / zephyr network
adding option to run 'net-lite' from linux
bridging zephyr's max connections
fixing net errors
fixing compilation with getAddrString
fixing compilation with getAddrString
experimenting with a nativesockets_lite ... getAddrString
experimenting with a nativesockets_lite ... getAddrString
experimenting with a nativesockets_lite ... getLocalAddr
experimenting with a nativesockets_lite ... getLocalAddr
experimenting with a nativesockets_lite ...
add note regarding incorrect FreeRTOS Sockadd_in fields
changing to NIM_STATIC_ASSERT
cleaning up the static_assert error messages
cleaning up the static_assert error messages
setting up static assert ftw!
testing compile time asserts
reworking Sockaddr objects to more closely match various platforms
reworking Sockaddr objects to more closely match various platforms
reworking Sockaddr objects to more closely match various platforms
finding missing items (issue #18684)
fixup posix constants (issue #18684)
adding plumbing for zephyr os (issue #18684)
adding plumbing for zephyr os (issue #18684)
* fixing constant capitalizations
* remove extra debug prints and fix TSa_Family/cint issue
* remove extra debug prints and fix TSa_Family/cint issue
* fixing PR issues
* Porting Nim to run on Zephyr.
Includes changes to `std/net`.
Squashed commit of the following:
tweaking more memory / malloc things
revert back bitmasks
tweaking nim to use kernel heap as C malloc doesn't work
fixing socket polling on zephyr
cleanup getting maximum sockets for process or for rtos'es
reorganizing and fixing net for async / system
merge netlite changes back into nativesockets
merge netlite changes back into nativesockets
reverting native sockets back
tweaking nim / zephyr network
adding option to run 'net-lite' from linux
bridging zephyr's max connections
fixing net errors
fixing compilation with getAddrString
fixing compilation with getAddrString
experimenting with a nativesockets_lite ... getAddrString
experimenting with a nativesockets_lite ... getAddrString
experimenting with a nativesockets_lite ... getLocalAddr
experimenting with a nativesockets_lite ... getLocalAddr
experimenting with a nativesockets_lite ...
add note regarding incorrect FreeRTOS Sockadd_in fields
changing to NIM_STATIC_ASSERT
cleaning up the static_assert error messages
cleaning up the static_assert error messages
setting up static assert ftw!
testing compile time asserts
reworking Sockaddr objects to more closely match various platforms
reworking Sockaddr objects to more closely match various platforms
reworking Sockaddr objects to more closely match various platforms
finding missing items (issue #18684)
fixup posix constants (issue #18684)
adding plumbing for zephyr os (issue #18684)
adding plumbing for zephyr os (issue #18684)
* fixing constant capitalizations
* remove extra debug prints and fix TSa_Family/cint issue
* remove extra debug prints and fix TSa_Family/cint issue
* Remerge
* fixing constant capitalizations
* remove extra debug prints and fix TSa_Family/cint issue
* remove extra debug prints and fix TSa_Family/cint issue
* fixing PR issues
* fix maxDescriptors on zephyr/freertos
* move maxDescriptors to selector.nim -- fixes compile issue
* change realloc impl on zephyr to match ansi c behavior
* change realloc impl on zephyr to match ansi c behavior
* force compileOnly mode for tlwip
Co-authored-by: Jaremy J. Creechley <jaremy.creechley@wavebaselabs.com>
Co-authored-by: Jaremy Creechley <jaremy.creechley@panthalassa.com>
This commit is contained in:
parent
41d9918591
commit
141b76e365
20 changed files with 522 additions and 346 deletions
|
|
@ -595,7 +595,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
||||||
osQnx, osAtari, osAix,
|
osQnx, osAtari, osAix,
|
||||||
osHaiku, osVxWorks, osSolaris, osNetbsd,
|
osHaiku, osVxWorks, osSolaris, osNetbsd,
|
||||||
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
|
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
|
||||||
osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos}
|
osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr}
|
||||||
of "linux":
|
of "linux":
|
||||||
result = conf.target.targetOS in {osLinux, osAndroid}
|
result = conf.target.targetOS in {osLinux, osAndroid}
|
||||||
of "bsd":
|
of "bsd":
|
||||||
|
|
@ -615,6 +615,8 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
||||||
result = conf.target.targetOS == osNintendoSwitch
|
result = conf.target.targetOS == osNintendoSwitch
|
||||||
of "freertos", "lwip":
|
of "freertos", "lwip":
|
||||||
result = conf.target.targetOS == osFreeRTOS
|
result = conf.target.targetOS == osFreeRTOS
|
||||||
|
of "zephyr":
|
||||||
|
result = conf.target.targetOS == osZephyr
|
||||||
of "littleendian": result = CPU[conf.target.targetCPU].endian == littleEndian
|
of "littleendian": result = CPU[conf.target.targetCPU].endian == littleEndian
|
||||||
of "bigendian": result = CPU[conf.target.targetCPU].endian == bigEndian
|
of "bigendian": result = CPU[conf.target.targetCPU].endian == bigEndian
|
||||||
of "cpu8": result = CPU[conf.target.targetCPU].bit == 8
|
of "cpu8": result = CPU[conf.target.targetCPU].bit == 8
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ type
|
||||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osCrossos, osAix, osPalmos, osQnx,
|
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osCrossos, osAix, osPalmos, osQnx,
|
||||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
|
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
|
||||||
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osFreeRTOS, osAny
|
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osFreeRTOS, osZephyr, osAny
|
||||||
|
|
||||||
type
|
type
|
||||||
TInfoOSProp* = enum
|
TInfoOSProp* = enum
|
||||||
|
|
@ -185,6 +185,10 @@ const
|
||||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||||
props: {ospPosix}),
|
props: {ospPosix}),
|
||||||
|
(name: "Zephyr", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||||
|
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||||
|
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||||
|
props: {ospPosix}),
|
||||||
(name: "Any", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
(name: "Any", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||||
|
|
|
||||||
|
|
@ -151,8 +151,10 @@ proc htons*(a1: uint16): uint16 {.importc, header: "<arpa/inet.h>".}
|
||||||
proc ntohl*(a1: uint32): uint32 {.importc, header: "<arpa/inet.h>".}
|
proc ntohl*(a1: uint32): uint32 {.importc, header: "<arpa/inet.h>".}
|
||||||
proc ntohs*(a1: uint16): uint16 {.importc, header: "<arpa/inet.h>".}
|
proc ntohs*(a1: uint16): uint16 {.importc, header: "<arpa/inet.h>".}
|
||||||
|
|
||||||
proc inet_addr*(a1: cstring): InAddrT {.importc, header: "<arpa/inet.h>".}
|
when not defined(zephyr):
|
||||||
proc inet_ntoa*(a1: InAddr): cstring {.importc, header: "<arpa/inet.h>".}
|
proc inet_addr*(a1: cstring): InAddrT {.importc, header: "<arpa/inet.h>".}
|
||||||
|
proc inet_ntoa*(a1: InAddr): cstring {.importc, header: "<arpa/inet.h>".}
|
||||||
|
|
||||||
proc inet_ntop*(a1: cint, a2: pointer, a3: cstring, a4: int32): cstring {.
|
proc inet_ntop*(a1: cint, a2: pointer, a3: cstring, a4: int32): cstring {.
|
||||||
importc:"(char *)$1", header: "<arpa/inet.h>".}
|
importc:"(char *)$1", header: "<arpa/inet.h>".}
|
||||||
proc inet_pton*(a1: cint, a2: cstring, a3: pointer): cint {.
|
proc inet_pton*(a1: cint, a2: cstring, a3: pointer): cint {.
|
||||||
|
|
|
||||||
|
|
@ -363,6 +363,8 @@ var SEM_FAILED* {.importc: "SEM_FAILED", header: "<semaphore.h>".}: pointer
|
||||||
# <sys/resource.h>
|
# <sys/resource.h>
|
||||||
# var RLIMIT_NOFILE* {.importc: "RLIMIT_NOFILE", header: "<sys/resource.h>".}: cint
|
# var RLIMIT_NOFILE* {.importc: "RLIMIT_NOFILE", header: "<sys/resource.h>".}: cint
|
||||||
|
|
||||||
|
var FD_MAX* {.importc: "CONFIG_LWIP_MAX_SOCKETS", header: "<lwipopts.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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
when defined(nimHasStyleChecks):
|
when defined(nimHasStyleChecks):
|
||||||
{.push styleChecks: off.}
|
{.push styleChecks: off.}
|
||||||
|
|
||||||
when defined(freertos):
|
when defined(freertos) or defined(zephyr):
|
||||||
const
|
const
|
||||||
hasSpawnH = false # should exist for every Posix system nowadays
|
hasSpawnH = false # should exist for every Posix system nowadays
|
||||||
hasAioH = false
|
hasAioH = false
|
||||||
|
|
@ -391,9 +391,29 @@ when hasSpawnH:
|
||||||
header: "<spawn.h>", final, pure.} = object
|
header: "<spawn.h>", final, pure.} = object
|
||||||
|
|
||||||
when defined(linux):
|
when defined(linux):
|
||||||
|
const Sockaddr_max_length* = 255
|
||||||
# from sys/un.h
|
# from sys/un.h
|
||||||
const Sockaddr_un_path_length* = 108
|
const Sockaddr_un_path_length* = 108
|
||||||
|
elif defined(zephyr):
|
||||||
|
when defined(net_ipv6):
|
||||||
|
const Sockaddr_max_length* = 24
|
||||||
|
elif defined(net_raw):
|
||||||
|
const Sockaddr_max_length* = 20
|
||||||
|
else:
|
||||||
|
const Sockaddr_max_length* = 8
|
||||||
|
const Sockaddr_un_path_length* = Sockaddr_max_length
|
||||||
|
# Zephyr is heavily customizable so it's easy to get to a state
|
||||||
|
# where Nim & Zephyr IPv6 settings are out of sync, causing painful runtime failures.
|
||||||
|
{.emit: ["NIM_STATIC_ASSERT(NET_SOCKADDR_MAX_SIZE == ",
|
||||||
|
Sockaddr_max_length,
|
||||||
|
",\"NET_SOCKADDR_MAX_SIZE and Sockaddr_max_length size mismatch!",
|
||||||
|
" Check that Nim and Zephyr IPv4/IPv6 settings match.",
|
||||||
|
" Try adding -d:net_ipv6 to enable IPv6 for Nim on Zephyr.\" );"].}
|
||||||
|
elif defined(freertos) or defined(lwip):
|
||||||
|
const Sockaddr_max_length* = 14
|
||||||
|
const Sockaddr_un_path_length* = 108
|
||||||
else:
|
else:
|
||||||
|
const Sockaddr_max_length* = 255
|
||||||
# according to http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/un.h.html
|
# according to http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/un.h.html
|
||||||
# this is >=92
|
# this is >=92
|
||||||
const Sockaddr_un_path_length* = 92
|
const Sockaddr_un_path_length* = 92
|
||||||
|
|
@ -408,48 +428,50 @@ when defined(lwip):
|
||||||
pure, final.} = object ## struct sockaddr
|
pure, final.} = object ## struct sockaddr
|
||||||
sa_len*: uint8 ## Address family.
|
sa_len*: uint8 ## Address family.
|
||||||
sa_family*: TSa_Family ## Address family.
|
sa_family*: TSa_Family ## Address family.
|
||||||
sa_data*: array[0..255, char] ## Socket address (variable-length data).
|
sa_data*: array[0..Sockaddr_max_length-sizeof(uint8)-sizeof(TSa_Family), char] ## Socket address (variable-length data).
|
||||||
|
|
||||||
|
Sockaddr_storage* {.importc: "struct sockaddr_storage",
|
||||||
|
header: "<sys/socket.h>",
|
||||||
|
pure, final.} = object ## struct sockaddr_storage
|
||||||
|
s2_len*: uint8 ## Address family.
|
||||||
|
ss_family*: TSa_Family ## Address family.
|
||||||
|
s2_data1*: array[2, char] ## Address family.
|
||||||
|
s2_data2*: array[3, uint32] ## Address family.
|
||||||
|
when defined(lwip6) or defined(net_ipv6):
|
||||||
|
s2_data3*: array[3, uint32] ## Address family.
|
||||||
|
elif defined(zephyr):
|
||||||
|
type
|
||||||
|
SockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>",
|
||||||
|
pure, final.} = object ## struct sockaddr
|
||||||
|
sa_family*: TSa_Family ## Address family.
|
||||||
|
data*: array[0..Sockaddr_max_length-sizeof(TSa_Family), char] ## Socket address (variable-length data).
|
||||||
|
|
||||||
|
Sockaddr_storage* {.importc: "struct sockaddr_storage",
|
||||||
|
header: "<sys/socket.h>",
|
||||||
|
pure, final.} = object ## struct sockaddr_storage
|
||||||
|
ss_family*: TSa_Family ## Address family.
|
||||||
|
data*: array[0..Sockaddr_max_length-sizeof(TSa_Family), char] ## Socket address (variable-length data).
|
||||||
|
{.emit: ["NIM_STATIC_ASSERT(sizeof(struct sockaddr) == ", sizeof(Sockaddr), ",\"struct size mismatch\" );"].}
|
||||||
|
{.emit: ["NIM_STATIC_ASSERT(sizeof(struct sockaddr_storage) == ", sizeof(Sockaddr_storage), ",\"struct size mismatch\" );"].}
|
||||||
else:
|
else:
|
||||||
type
|
type
|
||||||
SockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>",
|
SockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>",
|
||||||
pure, final.} = object ## struct sockaddr
|
pure, final.} = object ## struct sockaddr
|
||||||
sa_family*: TSa_Family ## Address family.
|
sa_family*: TSa_Family ## Address family.
|
||||||
sa_data*: array[0..255, char] ## Socket address (variable-length data).
|
sa_data*: array[0..Sockaddr_max_length-sizeof(TSa_Family), char] ## Socket address (variable-length data).
|
||||||
|
|
||||||
|
Sockaddr_storage* {.importc: "struct sockaddr_storage",
|
||||||
|
header: "<sys/socket.h>",
|
||||||
|
pure, final.} = object ## struct sockaddr_storage
|
||||||
|
ss_family*: TSa_Family ## Address family.
|
||||||
|
|
||||||
type
|
type
|
||||||
Sockaddr_un* {.importc: "struct sockaddr_un", header: "<sys/un.h>",
|
Sockaddr_un* {.importc: "struct sockaddr_un", header: "<sys/un.h>",
|
||||||
pure, final.} = object ## struct sockaddr_un
|
pure, final.} = object ## struct sockaddr_un
|
||||||
sun_family*: TSa_Family ## Address family.
|
sun_family*: TSa_Family ## Address family.
|
||||||
sun_path*: array[0..Sockaddr_un_path_length-1, char] ## Socket path
|
sun_path*: array[0..Sockaddr_un_path_length-sizeof(TSa_Family), char] ## Socket path
|
||||||
|
|
||||||
|
|
||||||
when defined(lwip):
|
|
||||||
when not defined(lwip6):
|
|
||||||
type
|
|
||||||
Sockaddr_storage* {.importc: "struct sockaddr_storage",
|
|
||||||
header: "<sys/socket.h>",
|
|
||||||
pure, final.} = object ## struct sockaddr_storage
|
|
||||||
s2_len*: uint8 ## Address family.
|
|
||||||
ss_family*: TSa_Family ## Address family.
|
|
||||||
s2_data1*: array[2, char] ## Address family.
|
|
||||||
s2_data2*: array[3, uint32] ## Address family.
|
|
||||||
else:
|
|
||||||
type
|
|
||||||
Sockaddr_storage* {.importc: "struct sockaddr_storage",
|
|
||||||
header: "<sys/socket.h>",
|
|
||||||
pure, final.} = object ## struct sockaddr_storage
|
|
||||||
s2_len*: uint8 ## Address family.
|
|
||||||
ss_family*: TSa_Family ## Address family.
|
|
||||||
s2_data1*: array[2, char] ## Address family.
|
|
||||||
s2_data2*: array[3, uint32] ## Address family.
|
|
||||||
s2_data3*: array[3, uint32] ## Address family.
|
|
||||||
else:
|
|
||||||
type
|
|
||||||
Sockaddr_storage* {.importc: "struct sockaddr_storage",
|
|
||||||
header: "<sys/socket.h>",
|
|
||||||
pure, final.} = object ## struct sockaddr_storage
|
|
||||||
ss_family*: TSa_Family ## Address family.
|
|
||||||
|
|
||||||
type
|
type
|
||||||
Tif_nameindex* {.importc: "struct if_nameindex", final,
|
Tif_nameindex* {.importc: "struct if_nameindex", final,
|
||||||
pure, header: "<net/if.h>".} = object ## struct if_nameindex
|
pure, header: "<net/if.h>".} = object ## struct if_nameindex
|
||||||
|
|
@ -494,6 +516,7 @@ type
|
||||||
header: "<netinet/in.h>".} = object ## struct in_addr
|
header: "<netinet/in.h>".} = object ## struct in_addr
|
||||||
s_addr*: InAddrScalar
|
s_addr*: InAddrScalar
|
||||||
|
|
||||||
|
# TODO: Fixme for FreeRTOS/LwIP, these are incorrect
|
||||||
Sockaddr_in* {.importc: "struct sockaddr_in", pure, final,
|
Sockaddr_in* {.importc: "struct sockaddr_in", pure, final,
|
||||||
header: "<netinet/in.h>".} = object ## struct sockaddr_in
|
header: "<netinet/in.h>".} = object ## struct sockaddr_in
|
||||||
sin_family*: TSa_Family ## AF_INET.
|
sin_family*: TSa_Family ## AF_INET.
|
||||||
|
|
@ -577,7 +600,12 @@ when not defined(lwip):
|
||||||
events*: cshort ## The input event flags (see below).
|
events*: cshort ## The input event flags (see below).
|
||||||
revents*: cshort ## The output event flags (see below).
|
revents*: cshort ## The output event flags (see below).
|
||||||
|
|
||||||
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
|
when defined(zephyr):
|
||||||
|
type
|
||||||
|
Tnfds* = distinct cint
|
||||||
|
else:
|
||||||
|
type
|
||||||
|
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
|
||||||
|
|
||||||
var
|
var
|
||||||
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
errno* {.importc, header: "<errno.h>".}: cint ## error variable
|
||||||
|
|
@ -625,7 +653,7 @@ elif defined(solaris):
|
||||||
# Solaris doesn't have MSG_NOSIGNAL
|
# Solaris doesn't have MSG_NOSIGNAL
|
||||||
const
|
const
|
||||||
MSG_NOSIGNAL* = 0'i32
|
MSG_NOSIGNAL* = 0'i32
|
||||||
elif defined(freertos) or defined(lwip):
|
elif defined(zephyr) or defined(freertos) or defined(lwip):
|
||||||
# LwIP/FreeRTOS doesn't have MSG_NOSIGNAL
|
# LwIP/FreeRTOS doesn't have MSG_NOSIGNAL
|
||||||
const
|
const
|
||||||
MSG_NOSIGNAL* = 0x20'i32
|
MSG_NOSIGNAL* = 0x20'i32
|
||||||
|
|
|
||||||
|
|
@ -462,6 +462,9 @@ var RLIMIT_NOFILE* {.importc: "RLIMIT_NOFILE", header: "<sys/resource.h>".}: cin
|
||||||
|
|
||||||
# <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
|
||||||
|
when defined(zephyr):
|
||||||
|
# Zephyr specific hardcoded value
|
||||||
|
var FD_MAX* {.importc: "CONFIG_POSIX_MAX_FDS ", header: "<sys/select.h>".}: cint
|
||||||
|
|
||||||
# <sys/socket.h>
|
# <sys/socket.h>
|
||||||
var MSG_CTRUNC* {.importc: "MSG_CTRUNC", header: "<sys/socket.h>".}: cint
|
var MSG_CTRUNC* {.importc: "MSG_CTRUNC", header: "<sys/socket.h>".}: cint
|
||||||
|
|
@ -487,10 +490,15 @@ var SO_SNDTIMEO* {.importc: "SO_SNDTIMEO", header: "<sys/socket.h>".}: cint
|
||||||
var SO_TYPE* {.importc: "SO_TYPE", header: "<sys/socket.h>".}: cint
|
var SO_TYPE* {.importc: "SO_TYPE", header: "<sys/socket.h>".}: cint
|
||||||
var SOCK_DGRAM* {.importc: "SOCK_DGRAM", header: "<sys/socket.h>".}: cint
|
var SOCK_DGRAM* {.importc: "SOCK_DGRAM", header: "<sys/socket.h>".}: cint
|
||||||
var SOCK_RAW* {.importc: "SOCK_RAW", header: "<sys/socket.h>".}: cint
|
var SOCK_RAW* {.importc: "SOCK_RAW", header: "<sys/socket.h>".}: cint
|
||||||
var SOCK_SEQPACKET* {.importc: "SOCK_SEQPACKET", header: "<sys/socket.h>".}: cint
|
when defined(zephyr):
|
||||||
|
const SOCK_SEQPACKET* = cint(5)
|
||||||
|
var SOMAXCONN* {.importc: "CONFIG_NET_SOCKETS_POLL_MAX", header: "<sys/socket.h>".}: cint
|
||||||
|
else:
|
||||||
|
var SOCK_SEQPACKET* {.importc: "SOCK_SEQPACKET", header: "<sys/socket.h>".}: cint
|
||||||
|
var SOMAXCONN* {.importc: "SOMAXCONN", header: "<sys/socket.h>".}: cint
|
||||||
|
|
||||||
var SOCK_STREAM* {.importc: "SOCK_STREAM", header: "<sys/socket.h>".}: cint
|
var SOCK_STREAM* {.importc: "SOCK_STREAM", header: "<sys/socket.h>".}: cint
|
||||||
var SOL_SOCKET* {.importc: "SOL_SOCKET", header: "<sys/socket.h>".}: cint
|
var SOL_SOCKET* {.importc: "SOL_SOCKET", header: "<sys/socket.h>".}: cint
|
||||||
var SOMAXCONN* {.importc: "SOMAXCONN", header: "<sys/socket.h>".}: cint
|
|
||||||
var MSG_PEEK* {.importc: "MSG_PEEK", header: "<sys/socket.h>".}: cint
|
var MSG_PEEK* {.importc: "MSG_PEEK", header: "<sys/socket.h>".}: cint
|
||||||
var MSG_TRUNC* {.importc: "MSG_TRUNC", header: "<sys/socket.h>".}: cint
|
var MSG_TRUNC* {.importc: "MSG_TRUNC", header: "<sys/socket.h>".}: cint
|
||||||
var MSG_WAITALL* {.importc: "MSG_WAITALL", header: "<sys/socket.h>".}: cint
|
var MSG_WAITALL* {.importc: "MSG_WAITALL", header: "<sys/socket.h>".}: cint
|
||||||
|
|
|
||||||
|
|
@ -1973,15 +1973,18 @@ proc activeDescriptors*(): int {.inline.} =
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
import posix
|
import posix
|
||||||
|
|
||||||
when defined(linux) or defined(windows) or defined(macosx) or defined(bsd):
|
when defined(linux) or defined(windows) or defined(macosx) or defined(bsd) or
|
||||||
|
defined(zephyr) or defined(freertos):
|
||||||
proc maxDescriptors*(): int {.raises: OSError.} =
|
proc maxDescriptors*(): int {.raises: OSError.} =
|
||||||
## Returns the maximum number of active file descriptors for the current
|
## Returns the maximum number of active file descriptors for the current
|
||||||
## process. This involves a system call. For now `maxDescriptors` is
|
## process. This involves a system call. For now `maxDescriptors` is
|
||||||
## supported on the following OSes: Windows, Linux, OSX, BSD.
|
## supported on the following OSes: Windows, Linux, OSX, BSD.
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
result = 16_700_000
|
result = 16_700_000
|
||||||
|
elif defined(zephyr) or defined(freertos):
|
||||||
|
result = FD_MAX
|
||||||
else:
|
else:
|
||||||
var fdLim: RLimit
|
var fdLim: RLimit
|
||||||
if getrlimit(RLIMIT_NOFILE, fdLim) < 0:
|
if getrlimit(RLIMIT_NOFILE, fdLim) < 0:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
result = int(fdLim.rlim_cur) - 1
|
result = int(fdLim.rlim_cur) - 1
|
||||||
|
|
@ -103,6 +103,7 @@ export SOBool
|
||||||
# TODO: Remove duplication introduced by PR #4683.
|
# TODO: Remove duplication introduced by PR #4683.
|
||||||
|
|
||||||
const defineSsl = defined(ssl) or defined(nimdoc)
|
const defineSsl = defined(ssl) or defined(nimdoc)
|
||||||
|
const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr)
|
||||||
|
|
||||||
when defineSsl:
|
when defineSsl:
|
||||||
import openssl
|
import openssl
|
||||||
|
|
@ -178,11 +179,12 @@ proc getLocalAddr*(socket: AsyncSocket): (string, Port) =
|
||||||
## This is high-level interface for `getsockname`:idx:.
|
## This is high-level interface for `getsockname`:idx:.
|
||||||
getLocalAddr(socket.fd, socket.domain)
|
getLocalAddr(socket.fd, socket.domain)
|
||||||
|
|
||||||
proc getPeerAddr*(socket: AsyncSocket): (string, Port) =
|
when not useNimNetLite:
|
||||||
## Get the socket's peer address and port number.
|
proc getPeerAddr*(socket: AsyncSocket): (string, Port) =
|
||||||
##
|
## Get the socket's peer address and port number.
|
||||||
## This is high-level interface for `getpeername`:idx:.
|
##
|
||||||
getPeerAddr(socket.fd, socket.domain)
|
## This is high-level interface for `getpeername`:idx:.
|
||||||
|
getPeerAddr(socket.fd, socket.domain)
|
||||||
|
|
||||||
proc newAsyncSocket*(domain, sockType, protocol: cint,
|
proc newAsyncSocket*(domain, sockType, protocol: cint,
|
||||||
buffered = true,
|
buffered = true,
|
||||||
|
|
@ -655,7 +657,7 @@ proc hasDataBuffered*(s: AsyncSocket): bool {.since: (1, 5).} =
|
||||||
# xxx dedup with std/net
|
# xxx dedup with std/net
|
||||||
s.isBuffered and s.bufLen > 0 and s.currPos != s.bufLen
|
s.isBuffered and s.bufLen > 0 and s.currPos != s.bufLen
|
||||||
|
|
||||||
when defined(posix):
|
when defined(posix) and not useNimNetLite:
|
||||||
|
|
||||||
proc connectUnix*(socket: AsyncSocket, path: string): owned(Future[void]) =
|
proc connectUnix*(socket: AsyncSocket, path: string): owned(Future[void]) =
|
||||||
## Binds Unix socket to `path`.
|
## Binds Unix socket to `path`.
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,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 maxFD = maxDescriptors()
|
||||||
if getrlimit(posix.RLIMIT_NOFILE, a) != 0:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
var maxFD = int(a.rlim_max)
|
|
||||||
doAssert(maxFD > 0)
|
doAssert(maxFD > 0)
|
||||||
# Start with a reasonable size, checkFd() will grow this on demand
|
# Start with a reasonable size, checkFd() will grow this on demand
|
||||||
const numFD = 1024
|
const numFD = 1024
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,7 @@ else:
|
||||||
body
|
body
|
||||||
|
|
||||||
proc newSelector*[T](): Selector[T] =
|
proc newSelector*[T](): Selector[T] =
|
||||||
var a = RLimit()
|
var maxFD = maxDescriptors()
|
||||||
if getrlimit(posix.RLIMIT_NOFILE, a) != 0:
|
|
||||||
raiseIOSelectorsError(osLastError())
|
|
||||||
var maxFD = int(a.rlim_max)
|
|
||||||
|
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
result = cast[Selector[T]](allocShared0(sizeof(SelectorImpl[T])))
|
result = cast[Selector[T]](allocShared0(sizeof(SelectorImpl[T])))
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
|
||||||
verifySelectParams(timeout)
|
verifySelectParams(timeout)
|
||||||
|
|
||||||
if timeout != -1:
|
if timeout != -1:
|
||||||
when defined(genode) or defined(freertos):
|
when defined(genode) or defined(freertos) or defined(zephyr):
|
||||||
tv.tv_sec = Time(timeout div 1_000)
|
tv.tv_sec = Time(timeout div 1_000)
|
||||||
else:
|
else:
|
||||||
tv.tv_sec = timeout.int32 div 1_000
|
tv.tv_sec = timeout.int32 div 1_000
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ when hostOS == "solaris":
|
||||||
{.passl: "-lsocket -lnsl".}
|
{.passl: "-lsocket -lnsl".}
|
||||||
|
|
||||||
const useWinVersion = defined(windows) or defined(nimdoc)
|
const useWinVersion = defined(windows) or defined(nimdoc)
|
||||||
|
const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr)
|
||||||
|
|
||||||
when useWinVersion:
|
when useWinVersion:
|
||||||
import winlean
|
import winlean
|
||||||
|
|
@ -35,9 +36,12 @@ else:
|
||||||
|
|
||||||
export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
|
export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
|
||||||
Sockaddr_in6, Sockaddr_storage,
|
Sockaddr_in6, Sockaddr_storage,
|
||||||
inet_ntoa, recv, `==`, connect, send, accept, recvfrom, sendto,
|
recv, `==`, connect, send, accept, recvfrom, sendto,
|
||||||
freeAddrInfo
|
freeAddrInfo
|
||||||
|
|
||||||
|
when not useNimNetLite:
|
||||||
|
export inet_ntoa
|
||||||
|
|
||||||
export
|
export
|
||||||
SO_ERROR,
|
SO_ERROR,
|
||||||
SOL_SOCKET,
|
SOL_SOCKET,
|
||||||
|
|
@ -332,125 +336,6 @@ template htons*(x: uint16): untyped =
|
||||||
## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
|
## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
|
||||||
nativesockets.ntohs(x)
|
nativesockets.ntohs(x)
|
||||||
|
|
||||||
proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
|
|
||||||
## Searches the database from the beginning and finds the first entry for
|
|
||||||
## which the service name specified by `name` matches the s_name member
|
|
||||||
## and the protocol name specified by `proto` matches the s_proto member.
|
|
||||||
##
|
|
||||||
## On posix this will search through the `/etc/services` file.
|
|
||||||
when useWinVersion:
|
|
||||||
var s = winlean.getservbyname(name, proto)
|
|
||||||
else:
|
|
||||||
var s = posix.getservbyname(name, proto)
|
|
||||||
if s == nil: raiseOSError(osLastError(), "Service not found.")
|
|
||||||
result.name = $s.s_name
|
|
||||||
result.aliases = cstringArrayToSeq(s.s_aliases)
|
|
||||||
result.port = Port(s.s_port)
|
|
||||||
result.proto = $s.s_proto
|
|
||||||
|
|
||||||
proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].} =
|
|
||||||
## Searches the database from the beginning and finds the first entry for
|
|
||||||
## which the port specified by `port` matches the s_port member and the
|
|
||||||
## protocol name specified by `proto` matches the s_proto member.
|
|
||||||
##
|
|
||||||
## On posix this will search through the `/etc/services` file.
|
|
||||||
when useWinVersion:
|
|
||||||
var s = winlean.getservbyport(ze(int16(port)).cint, proto)
|
|
||||||
else:
|
|
||||||
var s = posix.getservbyport(ze(int16(port)).cint, proto)
|
|
||||||
if s == nil: raiseOSError(osLastError(), "Service not found.")
|
|
||||||
result.name = $s.s_name
|
|
||||||
result.aliases = cstringArrayToSeq(s.s_aliases)
|
|
||||||
result.port = Port(s.s_port)
|
|
||||||
result.proto = $s.s_proto
|
|
||||||
|
|
||||||
proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
|
|
||||||
## This function will lookup the hostname of an IP Address.
|
|
||||||
var myaddr: InAddr
|
|
||||||
myaddr.s_addr = inet_addr(ip)
|
|
||||||
|
|
||||||
when useWinVersion:
|
|
||||||
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
|
|
||||||
cint(AF_INET))
|
|
||||||
if s == nil: raiseOSError(osLastError())
|
|
||||||
else:
|
|
||||||
var s =
|
|
||||||
when defined(android4):
|
|
||||||
posix.gethostbyaddr(cast[cstring](addr(myaddr)), sizeof(myaddr).cint,
|
|
||||||
cint(posix.AF_INET))
|
|
||||||
else:
|
|
||||||
posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).SockLen,
|
|
||||||
cint(posix.AF_INET))
|
|
||||||
if s == nil:
|
|
||||||
raiseOSError(osLastError(), $hstrerror(h_errno))
|
|
||||||
|
|
||||||
result.name = $s.h_name
|
|
||||||
result.aliases = cstringArrayToSeq(s.h_aliases)
|
|
||||||
when useWinVersion:
|
|
||||||
result.addrtype = Domain(s.h_addrtype)
|
|
||||||
else:
|
|
||||||
if s.h_addrtype == posix.AF_INET:
|
|
||||||
result.addrtype = AF_INET
|
|
||||||
elif s.h_addrtype == posix.AF_INET6:
|
|
||||||
result.addrtype = AF_INET6
|
|
||||||
else:
|
|
||||||
raiseOSError(osLastError(), "unknown h_addrtype")
|
|
||||||
if result.addrtype == AF_INET:
|
|
||||||
result.addrList = @[]
|
|
||||||
var i = 0
|
|
||||||
while not isNil(s.h_addr_list[i]):
|
|
||||||
var inaddrPtr = cast[ptr InAddr](s.h_addr_list[i])
|
|
||||||
result.addrList.add($inet_ntoa(inaddrPtr[]))
|
|
||||||
inc(i)
|
|
||||||
else:
|
|
||||||
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
|
||||||
result.length = int(s.h_length)
|
|
||||||
|
|
||||||
proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =
|
|
||||||
## This function will lookup the IP address of a hostname.
|
|
||||||
when useWinVersion:
|
|
||||||
var s = winlean.gethostbyname(name)
|
|
||||||
else:
|
|
||||||
var s = posix.gethostbyname(name)
|
|
||||||
if s == nil: raiseOSError(osLastError())
|
|
||||||
result.name = $s.h_name
|
|
||||||
result.aliases = cstringArrayToSeq(s.h_aliases)
|
|
||||||
when useWinVersion:
|
|
||||||
result.addrtype = Domain(s.h_addrtype)
|
|
||||||
else:
|
|
||||||
if s.h_addrtype == posix.AF_INET:
|
|
||||||
result.addrtype = AF_INET
|
|
||||||
elif s.h_addrtype == posix.AF_INET6:
|
|
||||||
result.addrtype = AF_INET6
|
|
||||||
else:
|
|
||||||
raiseOSError(osLastError(), "unknown h_addrtype")
|
|
||||||
if result.addrtype == AF_INET:
|
|
||||||
result.addrList = @[]
|
|
||||||
var i = 0
|
|
||||||
while not isNil(s.h_addr_list[i]):
|
|
||||||
var inaddrPtr = cast[ptr InAddr](s.h_addr_list[i])
|
|
||||||
result.addrList.add($inet_ntoa(inaddrPtr[]))
|
|
||||||
inc(i)
|
|
||||||
else:
|
|
||||||
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
|
||||||
result.length = int(s.h_length)
|
|
||||||
|
|
||||||
proc getHostname*(): string {.tags: [ReadIOEffect].} =
|
|
||||||
## Returns the local hostname (not the FQDN)
|
|
||||||
# https://tools.ietf.org/html/rfc1035#section-2.3.1
|
|
||||||
# https://tools.ietf.org/html/rfc2181#section-11
|
|
||||||
const size = 256
|
|
||||||
result = newString(size)
|
|
||||||
when useWinVersion:
|
|
||||||
let success = winlean.gethostname(result, size)
|
|
||||||
else:
|
|
||||||
# Posix
|
|
||||||
let success = posix.gethostname(result, size)
|
|
||||||
if success != 0.cint:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
let x = len(cstring(result))
|
|
||||||
result.setLen(x)
|
|
||||||
|
|
||||||
proc getSockDomain*(socket: SocketHandle): Domain =
|
proc getSockDomain*(socket: SocketHandle): Domain =
|
||||||
## Returns the socket's domain (AF_INET or AF_INET6).
|
## Returns the socket's domain (AF_INET or AF_INET6).
|
||||||
var name: Sockaddr_in6
|
var name: Sockaddr_in6
|
||||||
|
|
@ -464,162 +349,354 @@ proc getSockDomain*(socket: SocketHandle): Domain =
|
||||||
else:
|
else:
|
||||||
raise newException(IOError, "Unknown socket family in getSockDomain")
|
raise newException(IOError, "Unknown socket family in getSockDomain")
|
||||||
|
|
||||||
proc getAddrString*(sockAddr: ptr SockAddr): string =
|
when not useNimNetLite:
|
||||||
## Returns the string representation of address within sockAddr
|
proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
|
||||||
if sockAddr.sa_family.cint == nativeAfInet:
|
## Searches the database from the beginning and finds the first entry for
|
||||||
result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr)
|
## which the service name specified by `name` matches the s_name member
|
||||||
elif sockAddr.sa_family.cint == nativeAfInet6:
|
## and the protocol name specified by `proto` matches the s_proto member.
|
||||||
let addrLen = when not useWinVersion: posix.INET6_ADDRSTRLEN.int
|
##
|
||||||
else: 46 # it's actually 46 in both cases
|
## On posix this will search through the `/etc/services` file.
|
||||||
result = newString(addrLen)
|
when useWinVersion:
|
||||||
let addr6 = addr cast[ptr Sockaddr_in6](sockAddr).sin6_addr
|
var s = winlean.getservbyname(name, proto)
|
||||||
when not useWinVersion:
|
|
||||||
if posix.inet_ntop(posix.AF_INET6, addr6, addr result[0],
|
|
||||||
result.len.int32) == nil:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
if posix.IN6_IS_ADDR_V4MAPPED(addr6) != 0:
|
|
||||||
result.setSlice("::ffff:".len..<addrLen)
|
|
||||||
else:
|
else:
|
||||||
if winlean.inet_ntop(winlean.AF_INET6, addr6, addr result[0],
|
var s = posix.getservbyname(name, proto)
|
||||||
result.len.int32) == nil:
|
if s == nil: raiseOSError(osLastError(), "Service not found.")
|
||||||
raiseOSError(osLastError())
|
result.name = $s.s_name
|
||||||
setLen(result, len(cstring(result)))
|
result.aliases = cstringArrayToSeq(s.s_aliases)
|
||||||
else:
|
result.port = Port(s.s_port)
|
||||||
when defined(posix) and not defined(nimdoc):
|
result.proto = $s.s_proto
|
||||||
if sockAddr.sa_family.cint == nativeAfUnix:
|
|
||||||
return "unix"
|
|
||||||
raise newException(IOError, "Unknown socket family in getAddrString")
|
|
||||||
|
|
||||||
proc getAddrString*(sockAddr: ptr SockAddr, strAddress: var string) =
|
proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].} =
|
||||||
## Stores in `strAddress` the string representation of the address inside
|
## Searches the database from the beginning and finds the first entry for
|
||||||
## `sockAddr`
|
## which the port specified by `port` matches the s_port member and the
|
||||||
##
|
## protocol name specified by `proto` matches the s_proto member.
|
||||||
## **Note**
|
##
|
||||||
## * `strAddress` must be initialized to 46 in length.
|
## On posix this will search through the `/etc/services` file.
|
||||||
const length = 46
|
when useWinVersion:
|
||||||
assert(length == len(strAddress),
|
var s = winlean.getservbyport(ze(int16(port)).cint, proto)
|
||||||
"`strAddress` was not initialized correctly. 46 != `len(strAddress)`")
|
|
||||||
if sockAddr.sa_family.cint == nativeAfInet:
|
|
||||||
let addr4 = addr cast[ptr Sockaddr_in](sockAddr).sin_addr
|
|
||||||
when not useWinVersion:
|
|
||||||
if posix.inet_ntop(posix.AF_INET, addr4, addr strAddress[0],
|
|
||||||
strAddress.len.int32) == nil:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
else:
|
else:
|
||||||
if winlean.inet_ntop(winlean.AF_INET, addr4, addr strAddress[0],
|
var s = posix.getservbyport(ze(int16(port)).cint, proto)
|
||||||
strAddress.len.int32) == nil:
|
if s == nil: raiseOSError(osLastError(), "Service not found.")
|
||||||
raiseOSError(osLastError())
|
result.name = $s.s_name
|
||||||
elif sockAddr.sa_family.cint == nativeAfInet6:
|
result.aliases = cstringArrayToSeq(s.s_aliases)
|
||||||
let addr6 = addr cast[ptr Sockaddr_in6](sockAddr).sin6_addr
|
result.port = Port(s.s_port)
|
||||||
when not useWinVersion:
|
result.proto = $s.s_proto
|
||||||
if posix.inet_ntop(posix.AF_INET6, addr6, addr strAddress[0],
|
|
||||||
strAddress.len.int32) == nil:
|
proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
|
||||||
raiseOSError(osLastError())
|
## This function will lookup the hostname of an IP Address.
|
||||||
if posix.IN6_IS_ADDR_V4MAPPED(addr6) != 0:
|
var myaddr: InAddr
|
||||||
strAddress.setSlice("::ffff:".len..<length)
|
myaddr.s_addr = inet_addr(ip)
|
||||||
|
|
||||||
|
when useWinVersion:
|
||||||
|
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
|
||||||
|
cint(AF_INET))
|
||||||
|
if s == nil: raiseOSError(osLastError())
|
||||||
else:
|
else:
|
||||||
if winlean.inet_ntop(winlean.AF_INET6, addr6, addr strAddress[0],
|
var s =
|
||||||
strAddress.len.int32) == nil:
|
when defined(android4):
|
||||||
|
posix.gethostbyaddr(cast[cstring](addr(myaddr)), sizeof(myaddr).cint,
|
||||||
|
cint(posix.AF_INET))
|
||||||
|
else:
|
||||||
|
posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).SockLen,
|
||||||
|
cint(posix.AF_INET))
|
||||||
|
if s == nil:
|
||||||
|
raiseOSError(osLastError(), $hstrerror(h_errno))
|
||||||
|
|
||||||
|
result.name = $s.h_name
|
||||||
|
result.aliases = cstringArrayToSeq(s.h_aliases)
|
||||||
|
when useWinVersion:
|
||||||
|
result.addrtype = Domain(s.h_addrtype)
|
||||||
|
else:
|
||||||
|
if s.h_addrtype == posix.AF_INET:
|
||||||
|
result.addrtype = AF_INET
|
||||||
|
elif s.h_addrtype == posix.AF_INET6:
|
||||||
|
result.addrtype = AF_INET6
|
||||||
|
else:
|
||||||
|
raiseOSError(osLastError(), "unknown h_addrtype")
|
||||||
|
if result.addrtype == AF_INET:
|
||||||
|
result.addrList = @[]
|
||||||
|
var i = 0
|
||||||
|
while not isNil(s.h_addr_list[i]):
|
||||||
|
var inaddrPtr = cast[ptr InAddr](s.h_addr_list[i])
|
||||||
|
result.addrList.add($inet_ntoa(inaddrPtr[]))
|
||||||
|
inc(i)
|
||||||
|
else:
|
||||||
|
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
||||||
|
result.length = int(s.h_length)
|
||||||
|
|
||||||
|
proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =
|
||||||
|
## This function will lookup the IP address of a hostname.
|
||||||
|
when useWinVersion:
|
||||||
|
var s = winlean.gethostbyname(name)
|
||||||
|
else:
|
||||||
|
var s = posix.gethostbyname(name)
|
||||||
|
if s == nil: raiseOSError(osLastError())
|
||||||
|
result.name = $s.h_name
|
||||||
|
result.aliases = cstringArrayToSeq(s.h_aliases)
|
||||||
|
when useWinVersion:
|
||||||
|
result.addrtype = Domain(s.h_addrtype)
|
||||||
|
else:
|
||||||
|
if s.h_addrtype == posix.AF_INET:
|
||||||
|
result.addrtype = AF_INET
|
||||||
|
elif s.h_addrtype == posix.AF_INET6:
|
||||||
|
result.addrtype = AF_INET6
|
||||||
|
else:
|
||||||
|
raiseOSError(osLastError(), "unknown h_addrtype")
|
||||||
|
if result.addrtype == AF_INET:
|
||||||
|
result.addrList = @[]
|
||||||
|
var i = 0
|
||||||
|
while not isNil(s.h_addr_list[i]):
|
||||||
|
var inaddrPtr = cast[ptr InAddr](s.h_addr_list[i])
|
||||||
|
result.addrList.add($inet_ntoa(inaddrPtr[]))
|
||||||
|
inc(i)
|
||||||
|
else:
|
||||||
|
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
||||||
|
result.length = int(s.h_length)
|
||||||
|
|
||||||
|
proc getHostname*(): string {.tags: [ReadIOEffect].} =
|
||||||
|
## Returns the local hostname (not the FQDN)
|
||||||
|
# https://tools.ietf.org/html/rfc1035#section-2.3.1
|
||||||
|
# https://tools.ietf.org/html/rfc2181#section-11
|
||||||
|
const size = 256
|
||||||
|
result = newString(size)
|
||||||
|
when useWinVersion:
|
||||||
|
let success = winlean.gethostname(result, size)
|
||||||
|
else:
|
||||||
|
# Posix
|
||||||
|
let success = posix.gethostname(result, size)
|
||||||
|
if success != 0.cint:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
let x = len(cstring(result))
|
||||||
|
result.setLen(x)
|
||||||
|
|
||||||
|
proc getAddrString*(sockAddr: ptr SockAddr): string =
|
||||||
|
## Returns the string representation of address within sockAddr
|
||||||
|
if sockAddr.sa_family.cint == nativeAfInet:
|
||||||
|
result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr)
|
||||||
|
elif sockAddr.sa_family.cint == nativeAfInet6:
|
||||||
|
let addrLen = when not useWinVersion: posix.INET6_ADDRSTRLEN.int
|
||||||
|
else: 46 # it's actually 46 in both cases
|
||||||
|
result = newString(addrLen)
|
||||||
|
let addr6 = addr cast[ptr Sockaddr_in6](sockAddr).sin6_addr
|
||||||
|
when not useWinVersion:
|
||||||
|
if posix.inet_ntop(posix.AF_INET6, addr6, addr result[0],
|
||||||
|
result.len.int32) == nil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
if posix.IN6_IS_ADDR_V4MAPPED(addr6) != 0:
|
||||||
|
result.setSlice("::ffff:".len..<addrLen)
|
||||||
|
else:
|
||||||
|
if winlean.inet_ntop(winlean.AF_INET6, addr6, addr result[0],
|
||||||
|
result.len.int32) == nil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
setLen(result, len(cstring(result)))
|
||||||
|
else:
|
||||||
|
when defined(posix) and not defined(nimdoc):
|
||||||
|
if sockAddr.sa_family.cint == nativeAfUnix:
|
||||||
|
return "unix"
|
||||||
|
raise newException(IOError, "Unknown socket family in getAddrString")
|
||||||
|
|
||||||
|
proc getAddrString*(sockAddr: ptr SockAddr, strAddress: var string) =
|
||||||
|
## Stores in `strAddress` the string representation of the address inside
|
||||||
|
## `sockAddr`
|
||||||
|
##
|
||||||
|
## **Note**
|
||||||
|
## * `strAddress` must be initialized to 46 in length.
|
||||||
|
const length = 46
|
||||||
|
assert(length == len(strAddress),
|
||||||
|
"`strAddress` was not initialized correctly. 46 != `len(strAddress)`")
|
||||||
|
if sockAddr.sa_family.cint == nativeAfInet:
|
||||||
|
let addr4 = addr cast[ptr Sockaddr_in](sockAddr).sin_addr
|
||||||
|
when not useWinVersion:
|
||||||
|
if posix.inet_ntop(posix.AF_INET, addr4, addr strAddress[0],
|
||||||
|
strAddress.len.int32) == nil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
if winlean.inet_ntop(winlean.AF_INET, addr4, addr strAddress[0],
|
||||||
|
strAddress.len.int32) == nil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
elif sockAddr.sa_family.cint == nativeAfInet6:
|
||||||
|
let addr6 = addr cast[ptr Sockaddr_in6](sockAddr).sin6_addr
|
||||||
|
when not useWinVersion:
|
||||||
|
if posix.inet_ntop(posix.AF_INET6, addr6, addr strAddress[0],
|
||||||
|
strAddress.len.int32) == nil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
if posix.IN6_IS_ADDR_V4MAPPED(addr6) != 0:
|
||||||
|
strAddress.setSlice("::ffff:".len..<length)
|
||||||
|
else:
|
||||||
|
if winlean.inet_ntop(winlean.AF_INET6, addr6, addr strAddress[0],
|
||||||
|
strAddress.len.int32) == nil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
raise newException(IOError, "Unknown socket family in getAddrString")
|
||||||
|
setLen(strAddress, len(cstring(strAddress)))
|
||||||
|
|
||||||
|
when defined(posix) and not defined(nimdoc):
|
||||||
|
proc makeUnixAddr*(path: string): Sockaddr_un =
|
||||||
|
result.sun_family = AF_UNIX.TSa_Family
|
||||||
|
if path.len >= Sockaddr_un_path_length:
|
||||||
|
raise newException(ValueError, "socket path too long")
|
||||||
|
copyMem(addr result.sun_path, path.cstring, path.len + 1)
|
||||||
|
|
||||||
|
proc getSockName*(socket: SocketHandle): Port =
|
||||||
|
## Returns the socket's associated port number.
|
||||||
|
var name: Sockaddr_in
|
||||||
|
when useWinVersion:
|
||||||
|
name.sin_family = uint16(ord(AF_INET))
|
||||||
|
else:
|
||||||
|
name.sin_family = TSa_Family(posix.AF_INET)
|
||||||
|
#name.sin_port = htons(cint16(port))
|
||||||
|
#name.sin_addr.s_addr = htonl(INADDR_ANY)
|
||||||
|
var namelen = sizeof(name).SockLen
|
||||||
|
if getsockname(socket, cast[ptr SockAddr](addr(name)),
|
||||||
|
addr(namelen)) == -1'i32:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
result = Port(nativesockets.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 = uint16(ord(AF_INET))
|
||||||
|
else:
|
||||||
|
name.sin_family = TSa_Family(posix.AF_INET)
|
||||||
|
var namelen = sizeof(name).SockLen
|
||||||
|
if getsockname(socket, cast[ptr SockAddr](addr(name)),
|
||||||
|
addr(namelen)) == -1'i32:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
else:
|
result = ($inet_ntoa(name.sin_addr),
|
||||||
raise newException(IOError, "Unknown socket family in getAddrString")
|
Port(nativesockets.ntohs(name.sin_port)))
|
||||||
setLen(strAddress, len(cstring(strAddress)))
|
of AF_INET6:
|
||||||
|
var name: Sockaddr_in6
|
||||||
|
when useWinVersion:
|
||||||
|
name.sin6_family = uint16(ord(AF_INET6))
|
||||||
|
else:
|
||||||
|
name.sin6_family = TSa_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.
|
||||||
|
result[0] = newString(64)
|
||||||
|
if inet_ntop(name.sin6_family.cint,
|
||||||
|
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
setLen(result[0], result[0].cstring.len)
|
||||||
|
result[1] = Port(nativesockets.ntohs(name.sin6_port))
|
||||||
|
else:
|
||||||
|
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
||||||
|
|
||||||
when defined(posix) and not defined(nimdoc):
|
proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
||||||
proc makeUnixAddr*(path: string): Sockaddr_un =
|
## Returns the socket's peer address and port number.
|
||||||
result.sun_family = AF_UNIX.TSa_Family
|
##
|
||||||
if path.len >= Sockaddr_un_path_length:
|
## Similar to POSIX's `getpeername`:idx:
|
||||||
raise newException(ValueError, "socket path too long")
|
case domain
|
||||||
copyMem(addr result.sun_path, path.cstring, path.len + 1)
|
of AF_INET:
|
||||||
|
var name: Sockaddr_in
|
||||||
|
when useWinVersion:
|
||||||
|
name.sin_family = uint16(ord(AF_INET))
|
||||||
|
else:
|
||||||
|
name.sin_family = TSa_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(nativesockets.ntohs(name.sin_port)))
|
||||||
|
of AF_INET6:
|
||||||
|
var name: Sockaddr_in6
|
||||||
|
when useWinVersion:
|
||||||
|
name.sin6_family = uint16(ord(AF_INET6))
|
||||||
|
else:
|
||||||
|
name.sin6_family = TSa_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.
|
||||||
|
result[0] = newString(64)
|
||||||
|
if inet_ntop(name.sin6_family.cint,
|
||||||
|
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
setLen(result[0], result[0].cstring.len)
|
||||||
|
result[1] = Port(nativesockets.ntohs(name.sin6_port))
|
||||||
|
else:
|
||||||
|
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
||||||
|
|
||||||
|
when useNimNetLite:
|
||||||
|
|
||||||
proc getSockName*(socket: SocketHandle): Port =
|
|
||||||
## Returns the socket's associated port number.
|
|
||||||
var name: Sockaddr_in
|
|
||||||
when useWinVersion:
|
when useWinVersion:
|
||||||
name.sin_family = uint16(ord(AF_INET))
|
const
|
||||||
else:
|
INET_ADDRSTRLEN = 16
|
||||||
name.sin_family = TSa_Family(posix.AF_INET)
|
INET6_ADDRSTRLEN = 46 # it's actually 46 in both cases
|
||||||
#name.sin_port = htons(cint16(port))
|
|
||||||
#name.sin_addr.s_addr = htonl(INADDR_ANY)
|
|
||||||
var namelen = sizeof(name).SockLen
|
|
||||||
if getsockname(socket, cast[ptr SockAddr](addr(name)),
|
|
||||||
addr(namelen)) == -1'i32:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
result = Port(nativesockets.ntohs(name.sin_port))
|
|
||||||
|
|
||||||
proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
proc sockAddrToStr(sa: ptr Sockaddr): string {.noinit.} =
|
||||||
## Returns the socket's local address and port number.
|
let af_family = sa.sa_family
|
||||||
##
|
var nl, v4Slice: cint
|
||||||
## Similar to POSIX's `getsockname`:idx:.
|
var si_addr: ptr InAddr
|
||||||
case domain
|
|
||||||
of AF_INET:
|
|
||||||
var name: Sockaddr_in
|
|
||||||
when useWinVersion:
|
|
||||||
name.sin_family = uint16(ord(AF_INET))
|
|
||||||
else:
|
|
||||||
name.sin_family = TSa_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(nativesockets.ntohs(name.sin_port)))
|
|
||||||
of AF_INET6:
|
|
||||||
var name: Sockaddr_in6
|
|
||||||
when useWinVersion:
|
|
||||||
name.sin6_family = uint16(ord(AF_INET6))
|
|
||||||
else:
|
|
||||||
name.sin6_family = TSa_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.
|
|
||||||
result[0] = newString(64)
|
|
||||||
if inet_ntop(name.sin6_family.cint,
|
|
||||||
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
setLen(result[0], result[0].cstring.len)
|
|
||||||
result[1] = Port(nativesockets.ntohs(name.sin6_port))
|
|
||||||
else:
|
|
||||||
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
|
||||||
|
|
||||||
proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
if af_family == AF_INET.TSa_Family:
|
||||||
## Returns the socket's peer address and port number.
|
nl = INET_ADDRSTRLEN
|
||||||
##
|
si_addr = cast[ptr Sockaddr_in](sa).sin_addr.addr()
|
||||||
## Similar to POSIX's `getpeername`:idx:
|
elif af_family == AF_INET6.TSa_Family:
|
||||||
case domain
|
nl = INET6_ADDRSTRLEN
|
||||||
of AF_INET:
|
let si6_addr = cast[ptr Sockaddr_in6](sa).sin6_addr.addr()
|
||||||
var name: Sockaddr_in
|
si_addr = cast[ptr InAddr](si6_addr) # let's us reuse logic below
|
||||||
when useWinVersion:
|
when defined(posix) and not defined(nimdoc) and not defined(zephyr):
|
||||||
name.sin_family = uint16(ord(AF_INET))
|
if posix.IN6_IS_ADDR_V4MAPPED(si6_addr) != 0:
|
||||||
|
v4Slice = "::ffff:".len()
|
||||||
else:
|
else:
|
||||||
name.sin_family = TSa_Family(posix.AF_INET)
|
when defined(posix) and not defined(nimdoc):
|
||||||
var namelen = sizeof(name).SockLen
|
if af_family.cint == nativeAfUnix:
|
||||||
if getpeername(socket, cast[ptr SockAddr](addr(name)),
|
return "unix"
|
||||||
addr(namelen)) == -1'i32:
|
return ""
|
||||||
raiseOSError(osLastError())
|
|
||||||
result = ($inet_ntoa(name.sin_addr),
|
result = newString(nl)
|
||||||
Port(nativesockets.ntohs(name.sin_port)))
|
let namePtr = result.cstring()
|
||||||
of AF_INET6:
|
if namePtr == inet_ntop(af_family.cint, si_addr, namePtr, nl):
|
||||||
var name: Sockaddr_in6
|
result.setLen(len(namePtr))
|
||||||
when useWinVersion:
|
if v4Slice > 0: result.setSlice(v4Slice.int ..< nl.int)
|
||||||
name.sin6_family = uint16(ord(AF_INET6))
|
|
||||||
else:
|
else:
|
||||||
name.sin6_family = TSa_Family(posix.AF_INET6)
|
return ""
|
||||||
var namelen = sizeof(name).SockLen
|
|
||||||
if getpeername(socket, cast[ptr SockAddr](addr(name)),
|
proc sockAddrToStr(sa: var Sockaddr_in | var Sockaddr_in6): string =
|
||||||
addr(namelen)) == -1'i32:
|
result = sockAddrToStr(cast[ptr SockAddr](unsafeAddr(sa)))
|
||||||
|
|
||||||
|
proc getAddrString*(sockAddr: ptr SockAddr): string =
|
||||||
|
result = sockAddrToStr(sockAddr)
|
||||||
|
if result.len() == 0:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
|
|
||||||
result[0] = newString(64)
|
proc getAddrString*(sockAddr: ptr SockAddr, strAddress: var string) {.noinit.} =
|
||||||
if inet_ntop(name.sin6_family.cint,
|
strAddress = getAddrString(sockAddr)
|
||||||
addr name.sin6_addr, addr result[0][0], (result[0].len+1).int32).isNil:
|
|
||||||
raiseOSError(osLastError())
|
proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
||||||
setLen(result[0], result[0].cstring.len)
|
## Returns the socket's local address and port number.
|
||||||
result[1] = Port(nativesockets.ntohs(name.sin6_port))
|
##
|
||||||
else:
|
## Similar to POSIX's `getsockname`:idx:.
|
||||||
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
template sockGetNameOrRaiseError(socket: untyped, name: untyped) =
|
||||||
|
var namelen = sizeof(socket).SockLen
|
||||||
|
if getsockname(socket, cast[ptr SockAddr](addr(name)),
|
||||||
|
addr(namelen)) == -1'i32:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
|
case domain
|
||||||
|
of AF_INET:
|
||||||
|
var name = Sockaddr_in(sin_family: TSa_Family(posix.AF_INET))
|
||||||
|
sockGetNameOrRaiseError(socket, name)
|
||||||
|
result = (sockAddrToStr(name),
|
||||||
|
Port(nativesockets.ntohs(name.sin_port)))
|
||||||
|
of AF_INET6:
|
||||||
|
var name = Sockaddr_in6(sin6_family: TSa_Family(posix.AF_INET6))
|
||||||
|
sockGetNameOrRaiseError(socket, name)
|
||||||
|
result = (sockAddrToStr(name),
|
||||||
|
Port(nativesockets.ntohs(name.sin6_port)))
|
||||||
|
else:
|
||||||
|
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
||||||
|
|
||||||
|
|
||||||
proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
|
proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
|
||||||
tags: [ReadIOEffect].} =
|
tags: [ReadIOEffect].} =
|
||||||
|
|
@ -733,14 +810,14 @@ proc accept*(fd: SocketHandle, inheritable = defined(nimInheritHandles)): (Socke
|
||||||
## child processes.
|
## child processes.
|
||||||
##
|
##
|
||||||
## Returns (osInvalidSocket, "") if an error occurred.
|
## Returns (osInvalidSocket, "") if an error occurred.
|
||||||
var sockAddress: Sockaddr_in
|
var sockAddress: Sockaddr
|
||||||
var addrLen = sizeof(sockAddress).SockLen
|
var addrLen = sizeof(sockAddress).SockLen
|
||||||
var sock =
|
var sock =
|
||||||
when (defined(linux) or defined(bsd)) and not defined(nimdoc):
|
when (defined(linux) or defined(bsd)) and not defined(nimdoc):
|
||||||
accept4(fd, cast[ptr SockAddr](addr(sockAddress)), addr(addrLen),
|
accept4(fd, addr(sockAddress), addr(addrLen),
|
||||||
if inheritable: 0 else: SOCK_CLOEXEC)
|
if inheritable: 0 else: SOCK_CLOEXEC)
|
||||||
else:
|
else:
|
||||||
accept(fd, cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
|
accept(fd, addr(sockAddress), addr(addrLen))
|
||||||
when declared(setInheritable) and not (defined(linux) or defined(bsd)):
|
when declared(setInheritable) and not (defined(linux) or defined(bsd)):
|
||||||
if not setInheritable(sock, inheritable):
|
if not setInheritable(sock, inheritable):
|
||||||
close sock
|
close sock
|
||||||
|
|
@ -748,7 +825,11 @@ proc accept*(fd: SocketHandle, inheritable = defined(nimInheritHandles)): (Socke
|
||||||
if sock == osInvalidSocket:
|
if sock == osInvalidSocket:
|
||||||
return (osInvalidSocket, "")
|
return (osInvalidSocket, "")
|
||||||
else:
|
else:
|
||||||
return (sock, $inet_ntoa(sockAddress.sin_addr))
|
when useNimNetLite:
|
||||||
|
var name = sockAddrToStr(addr sockAddress)
|
||||||
|
return (sock, name)
|
||||||
|
else:
|
||||||
|
return (sock, $inet_ntoa(cast[Sockaddr_in](sockAddress).sin_addr))
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
var wsa: WSAData
|
var wsa: WSAData
|
||||||
|
|
|
||||||
|
|
@ -85,12 +85,14 @@ runnableExamples("-r:off"):
|
||||||
|
|
||||||
import std/private/since
|
import std/private/since
|
||||||
|
|
||||||
import nativesockets, os, strutils, times, sets, options, std/monotimes
|
import nativesockets
|
||||||
|
import os, strutils, times, sets, options, std/monotimes
|
||||||
import ssl_config
|
import ssl_config
|
||||||
export nativesockets.Port, nativesockets.`$`, nativesockets.`==`
|
export nativesockets.Port, nativesockets.`$`, nativesockets.`==`
|
||||||
export Domain, SockType, Protocol
|
export Domain, SockType, Protocol
|
||||||
|
|
||||||
const useWinVersion = defined(windows) or defined(nimdoc)
|
const useWinVersion = defined(windows) or defined(nimdoc)
|
||||||
|
const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr)
|
||||||
const defineSsl = defined(ssl) or defined(nimdoc)
|
const defineSsl = defined(ssl) or defined(nimdoc)
|
||||||
|
|
||||||
when useWinVersion:
|
when useWinVersion:
|
||||||
|
|
@ -1243,11 +1245,12 @@ proc getLocalAddr*(socket: Socket): (string, Port) =
|
||||||
## This is high-level interface for `getsockname`:idx:.
|
## This is high-level interface for `getsockname`:idx:.
|
||||||
getLocalAddr(socket.fd, socket.domain)
|
getLocalAddr(socket.fd, socket.domain)
|
||||||
|
|
||||||
proc getPeerAddr*(socket: Socket): (string, Port) =
|
when not useNimNetLite:
|
||||||
## Get the socket's peer address and port number.
|
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)
|
## This is high-level interface for `getpeername`:idx:.
|
||||||
|
getPeerAddr(socket.fd, socket.domain)
|
||||||
|
|
||||||
proc setSockOpt*(socket: Socket, opt: SOBool, value: bool,
|
proc setSockOpt*(socket: Socket, opt: SOBool, value: bool,
|
||||||
level = SOL_SOCKET) {.tags: [WriteIOEffect].} =
|
level = SOL_SOCKET) {.tags: [WriteIOEffect].} =
|
||||||
|
|
@ -1259,7 +1262,7 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool,
|
||||||
var valuei = cint(if value: 1 else: 0)
|
var valuei = cint(if value: 1 else: 0)
|
||||||
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
||||||
|
|
||||||
when defined(posix) or defined(nimdoc):
|
when defined(nimdoc) or (defined(posix) and not useNimNetLite):
|
||||||
proc connectUnix*(socket: Socket, path: string) =
|
proc connectUnix*(socket: Socket, path: string) =
|
||||||
## Connects to Unix socket on `path`.
|
## Connects to Unix socket on `path`.
|
||||||
## This only works on Unix-style systems: Mac OS X, BSD and Linux
|
## This only works on Unix-style systems: Mac OS X, BSD and Linux
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,23 @@ else:
|
||||||
# Anything higher is the time to wait in milliseconds.
|
# Anything higher is the time to wait in milliseconds.
|
||||||
doAssert(timeout >= -1, "Cannot select with a negative value, got: " & $timeout)
|
doAssert(timeout >= -1, "Cannot select with a negative value, got: " & $timeout)
|
||||||
|
|
||||||
|
when defined(linux) or defined(windows) or defined(macosx) or defined(bsd) or
|
||||||
|
defined(zephyr) or defined(freertos):
|
||||||
|
template maxDescriptors*(): int =
|
||||||
|
## Returns the maximum number of active file descriptors for the current
|
||||||
|
## process. This involves a system call. For now `maxDescriptors` is
|
||||||
|
## supported on the following OSes: Windows, Linux, OSX, BSD.
|
||||||
|
when defined(windows):
|
||||||
|
16_700_000
|
||||||
|
elif defined(zephyr) or defined(freertos):
|
||||||
|
FD_MAX
|
||||||
|
else:
|
||||||
|
var fdLim: RLimit
|
||||||
|
var res = int(getrlimit(RLIMIT_NOFILE, fdLim))
|
||||||
|
if res >= 0:
|
||||||
|
res = int(fdLim.rlim_cur) - 1
|
||||||
|
res
|
||||||
|
|
||||||
when defined(linux) and not defined(emscripten):
|
when defined(linux) and not defined(emscripten):
|
||||||
include ioselects/ioselectors_epoll
|
include ioselects/ioselectors_epoll
|
||||||
elif bsdPlatform:
|
elif bsdPlatform:
|
||||||
|
|
@ -337,5 +354,7 @@ else:
|
||||||
include ioselects/ioselectors_select
|
include ioselects/ioselectors_select
|
||||||
elif defined(freertos) or defined(lwip):
|
elif defined(freertos) or defined(lwip):
|
||||||
include ioselects/ioselectors_select
|
include ioselects/ioselectors_select
|
||||||
|
elif defined(zephyr):
|
||||||
|
include ioselects/ioselectors_poll
|
||||||
else:
|
else:
|
||||||
include ioselects/ioselectors_poll
|
include ioselects/ioselectors_poll
|
||||||
|
|
|
||||||
|
|
@ -142,14 +142,29 @@ proc c_sprintf*(buf, frmt: cstring): cint {.
|
||||||
importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.}
|
importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.}
|
||||||
# we use it only in a way that cannot lead to security issues
|
# we use it only in a way that cannot lead to security issues
|
||||||
|
|
||||||
proc c_malloc*(size: csize_t): pointer {.
|
when defined(zephyr) and not defined(zephyrUseLibcMalloc):
|
||||||
importc: "malloc", header: "<stdlib.h>".}
|
proc c_malloc*(size: csize_t): pointer {.
|
||||||
proc c_calloc*(nmemb, size: csize_t): pointer {.
|
importc: "k_malloc", header: "<kernel.h>".}
|
||||||
importc: "calloc", header: "<stdlib.h>".}
|
proc c_calloc*(nmemb, size: csize_t): pointer {.
|
||||||
proc c_free*(p: pointer) {.
|
importc: "k_calloc", header: "<kernel.h>".}
|
||||||
importc: "free", header: "<stdlib.h>".}
|
proc c_free*(p: pointer) {.
|
||||||
proc c_realloc*(p: pointer, newsize: csize_t): pointer {.
|
importc: "k_free", header: "<kernel.h>".}
|
||||||
importc: "realloc", header: "<stdlib.h>".}
|
proc c_realloc*(p: pointer, newsize: csize_t): pointer =
|
||||||
|
# Zephyr's kernel malloc doesn't support realloc
|
||||||
|
result = c_malloc(newSize)
|
||||||
|
# match the ansi c behavior
|
||||||
|
if not result.isNil():
|
||||||
|
copyMem(result, p, newSize)
|
||||||
|
c_free(p)
|
||||||
|
else:
|
||||||
|
proc c_malloc*(size: csize_t): pointer {.
|
||||||
|
importc: "malloc", header: "<stdlib.h>".}
|
||||||
|
proc c_calloc*(nmemb, size: csize_t): pointer {.
|
||||||
|
importc: "calloc", header: "<stdlib.h>".}
|
||||||
|
proc c_free*(p: pointer) {.
|
||||||
|
importc: "free", header: "<stdlib.h>".}
|
||||||
|
proc c_realloc*(p: pointer, newsize: csize_t): pointer {.
|
||||||
|
importc: "realloc", header: "<stdlib.h>".}
|
||||||
|
|
||||||
proc c_fwrite*(buf: pointer, size, n: csize_t, f: CFilePtr): cint {.
|
proc c_fwrite*(buf: pointer, size, n: csize_t, f: CFilePtr): cint {.
|
||||||
importc: "fwrite", header: "<stdio.h>".}
|
importc: "fwrite", header: "<stdio.h>".}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ const
|
||||||
PageSize = 1 shl PageShift
|
PageSize = 1 shl PageShift
|
||||||
PageMask = PageSize-1
|
PageMask = PageSize-1
|
||||||
|
|
||||||
|
|
||||||
MemAlign = # also minimal allocatable memory block
|
MemAlign = # also minimal allocatable memory block
|
||||||
when defined(useMalloc):
|
when defined(useMalloc):
|
||||||
when defined(amd64): 16
|
when defined(amd64): 16
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ elif defined(genode):
|
||||||
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
|
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
|
||||||
raiseAssert("nimGetProcAddr not implemented")
|
raiseAssert("nimGetProcAddr not implemented")
|
||||||
|
|
||||||
elif defined(nintendoswitch) or defined(freertos):
|
elif defined(nintendoswitch) or defined(freertos) or defined(zephyr):
|
||||||
proc nimUnloadLibrary(lib: LibHandle) =
|
proc nimUnloadLibrary(lib: LibHandle) =
|
||||||
cstderr.rawWrite("nimUnLoadLibrary not implemented")
|
cstderr.rawWrite("nimUnLoadLibrary not implemented")
|
||||||
cstderr.rawWrite("\n")
|
cstderr.rawWrite("\n")
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,7 @@ when defined(nimdoc) or (defined(posix) and not defined(nimscript)) or defined(w
|
||||||
## availability with `declared() <system.html#declared,untyped>`.
|
## availability with `declared() <system.html#declared,untyped>`.
|
||||||
when SupportIoctlInheritCtl:
|
when SupportIoctlInheritCtl:
|
||||||
result = c_ioctl(f, if inheritable: FIONCLEX else: FIOCLEX) != -1
|
result = c_ioctl(f, if inheritable: FIONCLEX else: FIOCLEX) != -1
|
||||||
elif defined(freertos):
|
elif defined(freertos) or defined(zephyr):
|
||||||
result = true
|
result = true
|
||||||
elif defined(posix):
|
elif defined(posix):
|
||||||
var flags = c_fcntl(f, F_GETFD)
|
var flags = c_fcntl(f, F_GETFD)
|
||||||
|
|
@ -780,8 +780,11 @@ when declared(stdout):
|
||||||
var echoLock: SysLock
|
var echoLock: SysLock
|
||||||
initSysLock echoLock
|
initSysLock echoLock
|
||||||
|
|
||||||
const stdOutLock = not defined(windows) and not defined(android) and
|
const stdOutLock = not defined(windows) and
|
||||||
not defined(nintendoswitch) and not defined(freertos) and
|
not defined(android) and
|
||||||
|
not defined(nintendoswitch) and
|
||||||
|
not defined(freertos) and
|
||||||
|
not defined(zephyr) and
|
||||||
hostOS != "any"
|
hostOS != "any"
|
||||||
|
|
||||||
proc echoBinSafe(args: openArray[string]) {.compilerproc.} =
|
proc echoBinSafe(args: openArray[string]) {.compilerproc.} =
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,22 @@
|
||||||
{.push stackTrace: off.}
|
{.push stackTrace: off.}
|
||||||
|
|
||||||
proc allocImpl(size: Natural): pointer =
|
proc allocImpl(size: Natural): pointer =
|
||||||
c_malloc(size.csize_t)
|
result = c_malloc(size.csize_t)
|
||||||
|
when defined(zephyr):
|
||||||
|
if result == nil:
|
||||||
|
raiseOutOfMem()
|
||||||
|
|
||||||
proc alloc0Impl(size: Natural): pointer =
|
proc alloc0Impl(size: Natural): pointer =
|
||||||
c_calloc(size.csize_t, 1)
|
result = c_calloc(size.csize_t, 1)
|
||||||
|
when defined(zephyr):
|
||||||
|
if result == nil:
|
||||||
|
raiseOutOfMem()
|
||||||
|
|
||||||
proc reallocImpl(p: pointer, newSize: Natural): pointer =
|
proc reallocImpl(p: pointer, newSize: Natural): pointer =
|
||||||
c_realloc(p, newSize.csize_t)
|
result = c_realloc(p, newSize.csize_t)
|
||||||
|
when defined(zephyr):
|
||||||
|
if result == nil:
|
||||||
|
raiseOutOfMem()
|
||||||
|
|
||||||
proc realloc0Impl(p: pointer, oldsize, newSize: Natural): pointer =
|
proc realloc0Impl(p: pointer, oldsize, newSize: Natural): pointer =
|
||||||
result = realloc(p, newSize.csize_t)
|
result = realloc(p, newSize.csize_t)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
targets: "c"
|
targets: "c"
|
||||||
cmd: "nim $target --os:freertos --gc:arc $options $file"
|
cmd: "nim $target --compileOnly --os:freertos --gc:arc $options $file"
|
||||||
disabled: "bsd"
|
disabled: "bsd"
|
||||||
disabled: "windows"
|
disabled: "windows"
|
||||||
action: compile
|
action: compile
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue