diff --git a/chronos/asyncloop.nim b/chronos/asyncloop.nim index abf3edc..6e3bd9a 100644 --- a/chronos/asyncloop.nim +++ b/chronos/asyncloop.nim @@ -152,14 +152,15 @@ elif defined(macosx) or defined(freebsd) or defined(netbsd) or defined(openbsd) or defined(dragonfly) or defined(macos) or defined(linux) or defined(android) or defined(solaris): import "."/selectors2 - from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK, - MSG_NOSIGNAL, + import "."/oserrno + from posix import MSG_PEEK, MSG_NOSIGNAL, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGPIPE export SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGPIPE + export oserrno type CallbackFunc* = proc (arg: pointer) {.gcsafe, raises: [Defect].} @@ -282,6 +283,12 @@ proc raiseOsDefect*(error: OSErrorCode, msg = "") {.noreturn, noinline.} = raise (ref Defect)(msg: msg & "\n[" & $int(error) & "] " & osErrorMsg(error) & "\n" & getStackTrace()) +func toPointer(error: OSErrorCode): pointer = + when sizeof(int) == 8: + cast[pointer](uint64(uint32(error))) + else: + cast[pointer](uint32(error)) + func toException*(v: OSErrorCode): ref OSError = newOSError(v) # This helper will allow to use `tryGet()` and raise OSError for # Result[T, OSErrorCode] values. @@ -518,27 +525,30 @@ when defined(windows): ## Closes a socket and ensures that it is unregistered. let loop = getThreadDispatcher() loop.handles.excl(fd) - let param = - if closeFd(SocketHandle(fd)) == 0: - OSErrorCode(0) - else: - osLastError() - if not isNil(aftercb): - var acb = AsyncCallback(function: aftercb, udata: cast[pointer](param)) - loop.callbacks.addLast(acb) + let + param = toPointer( + if closeFd(SocketHandle(fd)) == 0: + OSErrorCode(0) + else: + osLastError() + ) + if not(isNil(aftercb)): + loop.callbacks.addLast(AsyncCallback(function: aftercb, udata: param)) proc closeHandle*(fd: AsyncFD, aftercb: CallbackFunc = nil) = ## Closes a (pipe/file) handle and ensures that it is unregistered. let loop = getThreadDispatcher() loop.handles.excl(fd) - let param = - if closeFd(HANDLE(fd)) == 0: - OSErrorCode(0) - else: - osLastError() - if not isNil(aftercb): - var acb = AsyncCallback(function: aftercb, udata: cast[pointer](param)) - loop.callbacks.addLast(acb) + let + param = toPointer( + if closeFd(HANDLE(fd)) == 0: + OSErrorCode(0) + else: + osLastError() + ) + + if not(isNil(aftercb)): + loop.callbacks.addLast(AsyncCallback(function: aftercb, udata: param)) proc contains*(disp: PDispatcher, fd: AsyncFD): bool = ## Returns ``true`` if ``fd`` is registered in thread's dispatcher. @@ -720,21 +730,22 @@ elif defined(macosx) or defined(freebsd) or defined(netbsd) or let loop = getThreadDispatcher() proc continuation(udata: pointer) = - let param = - if SocketHandle(fd) in loop.selector: - let ures = unregister2(fd) - if ures.isErr(): - discard closeFd(cint(fd)) - ures.error() - else: - if closeFd(cint(fd)) != 0: - osLastError() + let + param = toPointer( + if SocketHandle(fd) in loop.selector: + let ures = unregister2(fd) + if ures.isErr(): + discard closeFd(cint(fd)) + ures.error() else: - OSErrorCode(0) - else: - OSErrorCode(osdefs.EBADF) - if not isNil(aftercb): - aftercb(cast[pointer](param)) + if closeFd(cint(fd)) != 0: + osLastError() + else: + OSErrorCode(0) + else: + OSErrorCode(osdefs.EBADF) + ) + if not(isNil(aftercb)): aftercb(param) withData(loop.selector, cint(fd), adata) do: # We are scheduling reader and writer callbacks to be called diff --git a/chronos/ioselects/ioselectors_epoll.nim b/chronos/ioselects/ioselectors_epoll.nim index 187479f..3eed870 100644 --- a/chronos/ioselects/ioselectors_epoll.nim +++ b/chronos/ioselects/ioselectors_epoll.nim @@ -42,7 +42,7 @@ proc getVirtualId[T](s: Selector[T]): SelectResult[int32] = ok(s.virtualHoles.popLast()) else: if s.virtualId == low(int32): - err(OSErrorCode(EMFILE)) + err(oserrno.EMFILE) else: dec(s.virtualId) ok(s.virtualId) @@ -139,7 +139,7 @@ proc trigger2*(event: SelectEvent): SelectResult[void] = if res == -1: err(osLastError()) elif res != sizeof(uint64): - err(OSErrorCode(osdefs.EINVAL)) + err(oserrno.EINVAL) else: ok() @@ -521,11 +521,11 @@ proc prepareKey[T](s: Selector[T], event: EpollEvent): Opt[ReadyKey] = if (event.events and EPOLLERR) != 0: rkey.events.incl(Event.Error) - rkey.errorCode = OSErrorCode(ECONNRESET) + rkey.errorCode = oserrno.ECONNRESET if (event.events and EPOLLHUP) != 0 or (event.events and EPOLLRDHUP) != 0: rkey.events.incl(Event.Error) - rkey.errorCode = OSErrorCode(ECONNRESET) + rkey.errorCode = oserrno.ECONNRESET if (event.events and EPOLLOUT) != 0: rkey.events.incl(Event.Write) @@ -580,7 +580,8 @@ proc prepareKey[T](s: Selector[T], event: EpollEvent): Opt[ReadyKey] = let res = handleEintr(osdefs.read(fdi32, addr data, sizeof(uint64))) if res != sizeof(uint64): let errorCode = osLastError() - if errorCode == EAGAIN: + case errorCode + of oserrno.EAGAIN: return Opt.none(ReadyKey) else: rkey.events.incl({Event.User, Event.Error}) diff --git a/chronos/ioselects/ioselectors_kqueue.nim b/chronos/ioselects/ioselectors_kqueue.nim index 4ff746e..dc95671 100644 --- a/chronos/ioselects/ioselectors_kqueue.nim +++ b/chronos/ioselects/ioselectors_kqueue.nim @@ -58,6 +58,12 @@ proc toString(key: int32|cint|SocketHandle|int): string = else: Base10.toString(uint32(fdi32)) +proc toPointer(data: int32): pointer = + when sizeof(int) == 8: + cast[pointer](uint64(uint32(data))) + else: + cast[pointer](uint32(data)) + template addKey[T](s: Selector[T], key: int32, skey: SelectorKey[T]) = if s.fds.hasKeyOrPut(key, skey): raiseAssert "Descriptor [" & key.toString() & @@ -154,7 +160,7 @@ proc trigger2*(event: SelectEvent): SelectResult[void] = if res == -1: err(osLastError()) elif res != sizeof(uint64): - err(OSErrorCode(osdefs.EINVAL)) + err(oserrno.EINVAL) else: ok() @@ -310,7 +316,7 @@ proc registerSignal*[T](s: Selector[T], signal: int, # To be compatible with linux semantic we need to "eat" signals signal(cint(signal), SIG_IGN) changes.modifyKQueue(0, uint(signal), EVFILT_SIGNAL, EV_ADD, 0, 0, - cast[pointer](uint32(fdi32))) + fdi32.toPointer()) if handleEintr(kevent(s.kqFd, addr(changes[0]), cint(1), nil, 0, nil)) == -1: let errorCode = osLastError() s.freeKey(fdi32) @@ -341,7 +347,7 @@ proc registerProcess*[T](s: Selector[T], pid: int, s.addKey(fdi32, selectorKey) changes.modifyKQueue(0, uint(uint32(pid)), EVFILT_PROC, flags, NOTE_EXIT, - 0, cast[pointer](uint32(fdi32))) + 0, fdi32.toPointer()) if handleEintr(kevent(s.kqFd, addr(changes[0]), cint(1), nil, 0, nil)) == -1: s.freeKey(fdi32) return err(osLastError()) @@ -490,14 +496,14 @@ proc prepareKey[T](s: Selector[T], event: KEvent): Opt[ReadyKey] = of EVFILT_READ: if (event.flags and EV_EOF) != 0: rkey.events.incl(Event.Error) - rkey.errorCode = OSErrorCode(ECONNRESET) + rkey.errorCode = oserrno.ECONNRESET if Event.User in pkey.events: var data: uint64 = 0 if handleEintr(osdefs.read(cint(event.ident), addr data, sizeof(uint64))) != sizeof(uint64): let errorCode = osLastError() - if errorCode == EAGAIN: + if errorCode == oserrno.EAGAIN: # Someone already consumed event data return Opt.none(ReadyKey) else: @@ -510,7 +516,7 @@ proc prepareKey[T](s: Selector[T], event: KEvent): Opt[ReadyKey] = of EVFILT_WRITE: if (event.flags and EV_EOF) != 0: rkey.events.incl(Event.Error) - rkey.errorCode = OSErrorCode(ECONNRESET) + rkey.errorCode = oserrno.ECONNRESET rkey.events.incl(Event.Write) @@ -577,7 +583,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int, maxEventsCount, ptrTimeout) if res < 0: let errorCode = osLastError() - if errorCode == EINTR: + if errorCode == oserrno.EINTR: continue return err(errorCode) else: diff --git a/chronos/osdefs.nim b/chronos/osdefs.nim index 07eb90c..0d7bfab 100644 --- a/chronos/osdefs.nim +++ b/chronos/osdefs.nim @@ -6,18 +6,10 @@ # Licensed under either of # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) - -from std/os import osLastError, osErrorMsg, OSErrorCode, raiseOSError, - newOSError -export osLastError, osErrorMsg, OSError, OSErrorCode, raiseOSError, newOSError +import oserrno +export oserrno when defined(windows): - from std/winlean import SocketHandle, SockLen, SockAddr, InAddr, - In6_addr, Sockaddr_in, Sockaddr_in6, Sockaddr_storage, - AddrInfo - export SocketHandle, SockLen, SockAddr, InAddr, - In6_addr, Sockaddr_in, Sockaddr_in6, Sockaddr_storage, AddrInfo - # Prerequisites for constants template WSAIORW*(x, y): untyped = (IOC_INOUT or x or y) template WSAIOW*(x, y): untyped = @@ -25,6 +17,49 @@ when defined(windows): ((clong(sizeof(int32)) and clong(IOCPARM_MASK)) shl 16) or (x shl 8) or y type + Sockaddr_storage* {.final, pure.} = object + ss_family*: uint16 + ss_pad1: array[6, byte] + ss_align: int64 + ss_pad2: array[112, byte] + + InAddr* {.final, pure, union.} = object + s_addr*: uint32 + + In6Addr* {.final, pure, union.} = object + s_addr*: array[16, byte] + + Sockaddr_in* {.final, pure.} = object + sin_family*: uint16 + sin_port*: uint16 + sin_addr*: InAddr + sin_zero*: array[0..7, char] + + Sockaddr_in6* {.final, pure.} = object + sin6_family*: uint16 + sin6_port*: uint16 + sin6_flowinfo*: uint32 + sin6_addr*: In6Addr + sin6_scope_id*: uint32 + + SockLen* = cuint + + SockAddr* {.final, pure.} = object + sa_family*: uint16 + sa_data*: array[14, char] + + AddrInfo* {.final, pure.} = object + ai_flags*: cint ## Input flags. + ai_family*: cint ## Address family of socket. + ai_socktype*: cint ## Socket type. + ai_protocol*: cint ## Protocol of socket. + ai_addrlen*: csize_t ## Length of socket address. + ai_canonname*: pointer ## Canonical name of service location. + ai_addr*: ptr SockAddr ## Socket address of socket. + ai_next*: ptr AddrInfo ## Pointer to next in list. + + SocketHandle* = distinct int + HANDLE* = distinct uint GUID* {.final, pure.} = object D1*: uint32 @@ -104,36 +139,6 @@ when defined(windows): PIPE_UNLIMITED_INSTANCES* = 255'u32 DEFAULT_PIPE_SIZE* = 65536'u32 - ERROR_SUCCESS* = 0 - ERROR_FILE_NOT_FOUND* = 2 - ERROR_TOO_MANY_OPEN_FILES* = 4 - ERROR_ACCESS_DENIED* = 5 - ERROR_BROKEN_PIPE* = 109 - ERROR_BUFFER_OVERFLOW* = 111 - ERROR_PIPE_BUSY* = 231 - ERROR_NO_DATA* = 232 - ERROR_PIPE_NOT_CONNECTED* = 233 - ERROR_PIPE_CONNECTED* = 535 - ERROR_OPERATION_ABORTED* = 995 - ERROR_IO_PENDING* = 997 - ERROR_CONNECTION_REFUSED* = 1225 - ERROR_CONNECTION_ABORTED* = 1236 - - WSAEMFILE* = 10024 - WSAENETDOWN* = 10050 - WSAENETRESET* = 10052 - WSAECONNABORTED* = 10053 - WSAECONNRESET* = 10054 - WSAENOBUFS* = 10055 - WSAETIMEDOUT* = 10060 - WSAEADDRINUSE* = 10048 - WSAEDISCON* = 10101 - WSANOTINITIALISED* = 10093 - WSAENOTSOCK* = 10038 - WSAEINPROGRESS* = 10036 - WSAEINTR* = 10004 - WSAEWOULDBLOCK* = 10035 - ERROR_NETNAME_DELETED* = 64 STATUS_PENDING* = 0x103 IOCPARM_MASK* = 0x7f'u32 @@ -1283,8 +1288,6 @@ when defined(posix): INVALID_SOCKET* = SocketHandle(-1) INVALID_HANDLE_VALUE* = cint(-1) -proc `==`*(x: OSErrorCode, y: int): bool = - int(x) == y proc `==`*(x: SocketHandle, y: int): bool = x == SocketHandle(y) diff --git a/chronos/oserrno.nim b/chronos/oserrno.nim new file mode 100644 index 0000000..5cacb22 --- /dev/null +++ b/chronos/oserrno.nim @@ -0,0 +1,1346 @@ +# +# Chronos Posix OS error codes +# (c) Copyright 2023-Present +# Status Research & Development GmbH +# +# Licensed under either of +# Apache License, version 2.0, (LICENSE-APACHEv2) +# MIT license (LICENSE-MIT) +from std/os import osLastError, osErrorMsg, OSErrorCode, raiseOSError, + newOSError, `==` +export osLastError, osErrorMsg, OSError, OSErrorCode, raiseOSError, newOSError, + `==` + +when defined(netbsd): + ## Source: https://github.com/NetBSD/src/blob/trunk/sys/sys/errno.h + const + EPERM* = OSErrorCode(1) + # Operation not permitted + ENOENT* = OSErrorCode(2) + # No such file or directory + ESRCH* = OSErrorCode(3) + # No such process + EINTR* = OSErrorCode(4) + # Interrupted system call + EIO* = OSErrorCode(5) + # Input/output error + ENXIO* = OSErrorCode(6) + # Device not configured + E2BIG* = OSErrorCode(7) + # Argument list too long + ENOEXEC* = OSErrorCode(8) + # Exec format error + EBADF* = OSErrorCode(9) + # Bad file descriptor + ECHILD* = OSErrorCode(10) + # No child processes + EDEADLK* = OSErrorCode(11) + # Resource deadlock avoided + ENOMEM* = OSErrorCode(12) + # Cannot allocate memory + EACCES* = OSErrorCode(13) + # Permission denied + EFAULT* = OSErrorCode(14) + # Bad address + ENOTBLK* = OSErrorCode(15) + # Block device required + EBUSY* = OSErrorCode(16) + # Device busy + EEXIST* = OSErrorCode(17) + # File exists + EXDEV* = OSErrorCode(18) + # Cross-device link + ENODEV* = OSErrorCode(19) + # Operation not supported by device + ENOTDIR* = OSErrorCode(20) + # Not a directory + EISDIR* = OSErrorCode(21) + # Is a directory + EINVAL* = OSErrorCode(22) + # Invalid argument + ENFILE* = OSErrorCode(23) + # Too many open files in system + EMFILE* = OSErrorCode(24) + # Too many open files + ENOTTY* = OSErrorCode(25) + # Inappropriate ioctl for device + ETXTBSY* = OSErrorCode(26) + # Text file busy + EFBIG* = OSErrorCode(27) + # File too large + ENOSPC* = OSErrorCode(28) + # No space left on device + ESPIPE* = OSErrorCode(29) + # Illegal seek + EROFS* = OSErrorCode(30) + # Read-only file system + EMLINK* = OSErrorCode(31) + # Too many links + EPIPE* = OSErrorCode(32) + # Broken pipe + EDOM* = OSErrorCode(33) + # Numerical argument out of domain + ERANGE* = OSErrorCode(34) + # Result too large or too small + EAGAIN* = OSErrorCode(35) + # Resource temporarily unavailable + EWOULDBLOCK* = EAGAIN + # Operation would block + EINPROGRESS* = OSErrorCode(36) + # Operation now in progress + EALREADY* = OSErrorCode(37) + # Operation already in progress + ENOTSOCK* = OSErrorCode(38) + # Socket operation on non-socket + EDESTADDRREQ* = OSErrorCode(39) + # Destination address required + EMSGSIZE* = OSErrorCode(40) + # Message too long + EPROTOTYPE* = OSErrorCode(41) + # Protocol wrong type for socket + ENOPROTOOPT* = OSErrorCode(42) + # Protocol option not available + EPROTONOSUPPORT* = OSErrorCode(43) + # Protocol not supported + ESOCKTNOSUPPORT* = OSErrorCode(44) + # Socket type not supported + EOPNOTSUPP* = OSErrorCode(45) + # Operation not supported + EPFNOSUPPORT* = OSErrorCode(46) + # Protocol family not supported + EAFNOSUPPORT* = OSErrorCode(47) + # Address family not supported by protocol family + EADDRINUSE* = OSErrorCode(48) + # Address already in use + EADDRNOTAVAIL* = OSErrorCode(49) + # Can't assign requested address + ENETDOWN* = OSErrorCode(50) + # Network is down + ENETUNREACH* = OSErrorCode(51) + # Network is unreachable + ENETRESET* = OSErrorCode(52) + # Network dropped connection on reset + ECONNABORTED* = OSErrorCode(53) + # Software caused connection abort + ECONNRESET* = OSErrorCode(54) + # Connection reset by peer + ENOBUFS* = OSErrorCode(55) + # No buffer space available + EISCONN* = OSErrorCode(56) + # Socket is already connected + ENOTCONN* = OSErrorCode(57) + # Socket is not connected + ESHUTDOWN* = OSErrorCode(58) + # Can't send after socket shutdown + ETOOMANYREFS* = OSErrorCode(59) + # Too many references: can't splice + ETIMEDOUT* = OSErrorCode(60) + # Operation timed out + ECONNREFUSED* = OSErrorCode(61) + # Connection refused + ELOOP* = OSErrorCode(62) + # Too many levels of symbolic links + ENAMETOOLONG* = OSErrorCode(63) + # File name too long + EHOSTDOWN* = OSErrorCode(64) + # Host is down + EHOSTUNREACH* = OSErrorCode(65) + # No route to host + ENOTEMPTY* = OSErrorCode(66) + # Directory not empty + EPROCLIM* = OSErrorCode(67) + # Too many processes + EUSERS* = OSErrorCode(68) + # Too many users + EDQUOT* = OSErrorCode(69) + # Disc quota exceeded + ESTALE* = OSErrorCode(70) + # Stale NFS file handle + EREMOTE* = OSErrorCode(71) + # Too many levels of remote in path + EBADRPC* = OSErrorCode(72) + # RPC struct is bad + ERPCMISMATCH* = OSErrorCode(73) + # RPC version wrong + EPROGUNAVAIL* = OSErrorCode(74) + # RPC prog. not avail + EPROGMISMATCH* = OSErrorCode(75) + # Program version wrong + EPROCUNAVAIL* = OSErrorCode(76) + # Bad procedure for program + ENOLCK* = OSErrorCode(77) + # No locks available + ENOSYS* = OSErrorCode(78) + # Function not implemented + EFTYPE* = OSErrorCode(79) + # Inappropriate file type or format + EAUTH* = OSErrorCode(80) + # Authentication error + ENEEDAUTH* = OSErrorCode(81) + # Need authenticator + EIDRM* = OSErrorCode(82) + # Identifier removed + ENOMSG* = OSErrorCode(83) + # No message of desired type + EOVERFLOW* = OSErrorCode(84) + # Value too large to be stored in data type + EILSEQ* = OSErrorCode(85) + # Illegal byte sequence + ENOTSUP* = OSErrorCode(86) + # Not supported + ECANCELED* = OSErrorCode(87) + # Operation canceled + EBADMSG* = OSErrorCode(88) + # Bad or Corrupt message + ENODATA* = OSErrorCode(89) + # No message available + ENOSR* = OSErrorCode(90) + # No STREAM resources + ENOSTR* = OSErrorCode(91) + # Not a STREAM + ETIME* = OSErrorCode(92) + # STREAM ioctl timeout + ENOATTR* = OSErrorCode(93) + # Attribute not found + EMULTIHOP* = OSErrorCode(94) + # Multihop attempted + ENOLINK* = OSErrorCode(95) + # Link has been severed + EPROTO* = OSErrorCode(96) + # Protocol error + EOWNERDEAD* = OSErrorCode(97) + # Previous owner died + ENOTRECOVERABLE* = OSErrorCode(98) + # State not recoverable + ELAST* = OSErrorCode(98) + # Must equal largest errno + +elif defined(openbsd): + ## Source: https://github.com/openbsd/src/blob/master/sys/sys/errno.h + const + EPERM* = OSErrorCode(1) + # Operation not permitted + ENOENT* = OSErrorCode(2) + # No such file or directory + ESRCH* = OSErrorCode(3) + # No such process + EINTR* = OSErrorCode(4) + # Interrupted system call + EIO* = OSErrorCode(5) + # Input/output error + ENXIO* = OSErrorCode(6) + # Device not configured + E2BIG* = OSErrorCode(7) + # Argument list too long + ENOEXEC* = OSErrorCode(8) + # Exec format error + EBADF* = OSErrorCode(9) + # Bad file descriptor + ECHILD* = OSErrorCode(10) + # No child processes + EDEADLK* = OSErrorCode(11) + # Resource deadlock avoided + ENOMEM* = OSErrorCode(12) + # Cannot allocate memory + EACCES* = OSErrorCode(13) + # Permission denied + EFAULT* = OSErrorCode(14) + # Bad address + ENOTBLK* = OSErrorCode(15) + # Block device required + EBUSY* = OSErrorCode(16) + # Device busy + EEXIST* = OSErrorCode(17) + # File exists + EXDEV* = OSErrorCode(18) + # Cross-device link + ENODEV* = OSErrorCode(19) + # Operation not supported by device + ENOTDIR* = OSErrorCode(20) + # Not a directory + EISDIR* = OSErrorCode(21) + # Is a directory + EINVAL* = OSErrorCode(22) + # Invalid argument + ENFILE* = OSErrorCode(23) + # Too many open files in system + EMFILE* = OSErrorCode(24) + # Too many open files + ENOTTY* = OSErrorCode(25) + # Inappropriate ioctl for device + ETXTBSY* = OSErrorCode(26) + # Text file busy + EFBIG* = OSErrorCode(27) + # File too large + ENOSPC* = OSErrorCode(28) + # No space left on device + ESPIPE* = OSErrorCode(29) + # Illegal seek + EROFS* = OSErrorCode(30) + # Read-only file system + EMLINK* = OSErrorCode(31) + # Too many links + EPIPE* = OSErrorCode(32) + # Broken pipe + EDOM* = OSErrorCode(33) + # Numerical argument out of domain + ERANGE* = OSErrorCode(34) + # Result too large + EAGAIN* = OSErrorCode(35) + # Resource temporarily unavailable + EWOULDBLOCK* = EAGAIN + # Operation would block + EINPROGRESS* = OSErrorCode(36) + # Operation now in progress + EALREADY* = OSErrorCode(37) + # Operation already in progress + ENOTSOCK* = OSErrorCode(38) + # Socket operation on non-socket + EDESTADDRREQ* = OSErrorCode(39) + # Destination address required + EMSGSIZE* = OSErrorCode(40) + # Message too long + EPROTOTYPE* = OSErrorCode(41) + # Protocol wrong type for socket + ENOPROTOOPT* = OSErrorCode(42) + # Protocol not available + EPROTONOSUPPORT* = OSErrorCode(43) + # Protocol not supported + ESOCKTNOSUPPORT* = OSErrorCode(44) + # Socket type not supported + EOPNOTSUPP* = OSErrorCode(45) + # Operation not supported + EPFNOSUPPORT* = OSErrorCode(46) + # Protocol family not supported + EAFNOSUPPORT* = OSErrorCode(47) + # Address family not supported by protocol family + EADDRINUSE* = OSErrorCode(48) + # Address already in use + EADDRNOTAVAIL* = OSErrorCode(49) + # Can't assign requested address + ENETDOWN* = OSErrorCode(50) + # Network is down + ENETUNREACH* = OSErrorCode(51) + # Network is unreachable + ENETRESET* = OSErrorCode(52) + # Network dropped connection on reset + ECONNABORTED* = OSErrorCode(53) + # Software caused connection abort + ECONNRESET* = OSErrorCode(54) + # Connection reset by peer + ENOBUFS* = OSErrorCode(55) + # No buffer space available + EISCONN* = OSErrorCode(56) + # Socket is already connected + ENOTCONN* = OSErrorCode(57) + # Socket is not connected + ESHUTDOWN* = OSErrorCode(58) + # Can't send after socket shutdown + ETOOMANYREFS* = OSErrorCode(59) + # Too many references: can't splice + ETIMEDOUT* = OSErrorCode(60) + # Operation timed out + ECONNREFUSED* = OSErrorCode(61) + # Connection refused + ELOOP* = OSErrorCode(62) + # Too many levels of symbolic links + ENAMETOOLONG* = OSErrorCode(63) + # File name too long + EHOSTDOWN* = OSErrorCode(64) + # Host is down + EHOSTUNREACH* = OSErrorCode(65) + # No route to host + ENOTEMPTY* = OSErrorCode(66) + # Directory not empty + EPROCLIM* = OSErrorCode(67) + # Too many processes + EUSERS* = OSErrorCode(68) + # Too many users + EDQUOT* = OSErrorCode(69) + # Disk quota exceeded + ESTALE* = OSErrorCode(70) + # Stale NFS file handle + EREMOTE* = OSErrorCode(71) + # Too many levels of remote in path + EBADRPC* = OSErrorCode(72) + # RPC struct is bad + ERPCMISMATCH* = OSErrorCode(73) + # RPC version wrong + EPROGUNAVAIL* = OSErrorCode(74) + # RPC program not available + EPROGMISMATCH* = OSErrorCode(75) + # Program version wrong + EPROCUNAVAIL* = OSErrorCode(76) + # Bad procedure for program + ENOLCK* = OSErrorCode(77) + # No locks available + ENOSYS* = OSErrorCode(78) + # Function not implemented + EFTYPE* = OSErrorCode(79) + # Inappropriate file type or format + EAUTH* = OSErrorCode(80) + # Authentication error + ENEEDAUTH* = OSErrorCode(81) + # Need authenticator + EIPSEC* = OSErrorCode(82) + # IPsec processing failure + ENOATTR* = OSErrorCode(83) + # Attribute not found + EILSEQ* = OSErrorCode(84) + # Illegal byte sequence + ENOMEDIUM* = OSErrorCode(85) + # No medium found + EMEDIUMTYPE* = OSErrorCode(86) + # Wrong medium type + EOVERFLOW* = OSErrorCode(87) + # Value too large to be stored in data type + ECANCELED* = OSErrorCode(88) + # Operation canceled + EIDRM* = OSErrorCode(89) + # Identifier removed + ENOMSG* = OSErrorCode(90) + # No message of desired type + ENOTSUP* = OSErrorCode(91) + # Not supported + EBADMSG* = OSErrorCode(92) + # Bad message + ENOTRECOVERABLE* = OSErrorCode(93) + # State not recoverable + EOWNERDEAD* = OSErrorCode(94) + # Previous owner died + EPROTO* = OSErrorCode(95) + # Protocol error + ELAST* = OSErrorCode(95) + # Must be equal largest errno + +elif defined(freebsd): + ## Source: https://github.com/freebsd/freebsd-src/blob/main/sys/sys/errno.h + const + EPERM* = OSErrorCode(1) + # Operation not permitted + ENOENT* = OSErrorCode(2) + # No such file or directory + ESRCH* = OSErrorCode(3) + # No such process + EINTR* = OSErrorCode(4) + # Interrupted system call + EIO* = OSErrorCode(5) + # Input/output error + ENXIO* = OSErrorCode(6) + # Device not configured + E2BIG* = OSErrorCode(7) + # Argument list too long + ENOEXEC* = OSErrorCode(8) + # Exec format error + EBADF* = OSErrorCode(9) + # Bad file descriptor + ECHILD* = OSErrorCode(10) + # No child processes + EDEADLK* = OSErrorCode(11) + # Resource deadlock avoided + ENOMEM* = OSErrorCode(12) + # Cannot allocate memory + EACCES* = OSErrorCode(13) + # Permission denied + EFAULT* = OSErrorCode(14) + # Bad address + ENOTBLK* = OSErrorCode(15) + # Block device required + EBUSY* = OSErrorCode(16) + # Device busy + EEXIST* = OSErrorCode(17) + # File exists + EXDEV* = OSErrorCode(18) + # Cross-device link + ENODEV* = OSErrorCode(19) + # Operation not supported by device + ENOTDIR* = OSErrorCode(20) + # Not a directory + EISDIR* = OSErrorCode(21) + # Is a directory + EINVAL* = OSErrorCode(22) + # Invalid argument + ENFILE* = OSErrorCode(23) + # Too many open files in system + EMFILE* = OSErrorCode(24) + # Too many open files + ENOTTY* = OSErrorCode(25) + # Inappropriate ioctl for device + ETXTBSY* = OSErrorCode(26) + # Text file busy + EFBIG* = OSErrorCode(27) + # File too large + ENOSPC* = OSErrorCode(28) + # No space left on device + ESPIPE* = OSErrorCode(29) + # Illegal seek + EROFS* = OSErrorCode(30) + # Read-only filesystem + EMLINK* = OSErrorCode(31) + # Too many links + EPIPE* = OSErrorCode(32) + # Broken pipe + EDOM* = OSErrorCode(33) + # Numerical argument out of domain + ERANGE* = OSErrorCode(34) + # Result too large + EAGAIN* = OSErrorCode(35) + # Resource temporarily unavailable + EWOULDBLOCK* = EAGAIN + # Operation would block + EINPROGRESS* = OSErrorCode(36) + # Operation now in progress + EALREADY* = OSErrorCode(37) + # Operation already in progress + ENOTSOCK* = OSErrorCode(38) + # Socket operation on non-socket + EDESTADDRREQ* = OSErrorCode(39) + # Destination address required + EMSGSIZE* = OSErrorCode(40) + # Message too long + EPROTOTYPE* = OSErrorCode(41) + # Protocol wrong type for socket + ENOPROTOOPT* = OSErrorCode(42) + # Protocol not available + EPROTONOSUPPORT* = OSErrorCode(43) + # Protocol not supported + ESOCKTNOSUPPORT* = OSErrorCode(44) + # Socket type not supported + EOPNOTSUPP* = OSErrorCode(45) + # Operation not supported + ENOTSUP* = EOPNOTSUPP + # Operation not supported + EPFNOSUPPORT* = OSErrorCode(46) + # Protocol family not supported + EAFNOSUPPORT* = OSErrorCode(47) + # Address family not supported by protocol family + EADDRINUSE* = OSErrorCode(48) + # Address already in use + EADDRNOTAVAIL* = OSErrorCode(49) + # Can't assign requested address + ENETDOWN* = OSErrorCode(50) + # Network is down + ENETUNREACH* = OSErrorCode(51) + # Network is unreachable + ENETRESET* = OSErrorCode(52) + # Network dropped connection on reset + ECONNABORTED* = OSErrorCode(53) + # Software caused connection abort + ECONNRESET* = OSErrorCode(54) + # Connection reset by peer + ENOBUFS* = OSErrorCode(55) + # No buffer space available + EISCONN* = OSErrorCode(56) + # Socket is already connected + ENOTCONN* = OSErrorCode(57) + # Socket is not connected + ESHUTDOWN* = OSErrorCode(58) + # Can't send after socket shutdown + ETOOMANYREFS* = OSErrorCode(59) + # Too many references: can't splice + ETIMEDOUT* = OSErrorCode(60) + # Operation timed out + ECONNREFUSED* = OSErrorCode(61) + # Connection refused + ELOOP* = OSErrorCode(62) + # Too many levels of symbolic links + ENAMETOOLONG* = OSErrorCode(63) + # File name too long + EHOSTDOWN* = OSErrorCode(64) + # Host is down + EHOSTUNREACH* = OSErrorCode(65) + # No route to host + ENOTEMPTY* = OSErrorCode(66) + # Directory not empty + EPROCLIM* = OSErrorCode(67) + # Too many processes + EUSERS* = OSErrorCode(68) + # Too many users + EDQUOT* = OSErrorCode(69) + # Disc quota exceeded + ESTALE* = OSErrorCode(70) + # Stale NFS file handle + EREMOTE* = OSErrorCode(71) + # Too many levels of remote in path + EBADRPC* = OSErrorCode(72) + # RPC struct is bad + ERPCMISMATCH* = OSErrorCode(73) + # RPC version wrong + EPROGUNAVAIL* = OSErrorCode(74) + # RPC prog. not avail + EPROGMISMATCH* = OSErrorCode(75) + # Program version wrong + EPROCUNAVAIL* = OSErrorCode(76) + # Bad procedure for program + ENOLCK* = OSErrorCode(77) + # No locks available + ENOSYS* = OSErrorCode(78) + # Function not implemented + EFTYPE* = OSErrorCode(79) + # Inappropriate file type or format + EAUTH* = OSErrorCode(80) + # Authentication error + ENEEDAUTH* = OSErrorCode(81) + # Need authenticator + EIDRM* = OSErrorCode(82) + # Identifier removed + ENOMSG* = OSErrorCode(83) + # No message of desired type + EOVERFLOW* = OSErrorCode(84) + # Value too large to be stored in data type + ECANCELED* = OSErrorCode(85) + # Operation canceled + EILSEQ* = OSErrorCode(86) + # Illegal byte sequence + ENOATTR* = OSErrorCode(87) + # Attribute not found + EDOOFUS* = OSErrorCode(88) + # Programming error + EBADMSG* = OSErrorCode(89) + # Bad message + EMULTIHOP* = OSErrorCode(90) + # Multihop attempted + ENOLINK* = OSErrorCode(91) + # Link has been severed + EPROTO* = OSErrorCode(92) + # Protocol error + ENOTCAPABLE* = OSErrorCode(93) + # Capabilities insufficient + ECAPMODE* = OSErrorCode(94) + # Not permitted in capability mode + ENOTRECOVERABLE* = OSErrorCode(95) + # State not recoverable + EOWNERDEAD* = OSErrorCode(96) + # Previous owner died + EINTEGRITY* = OSErrorCode(97) + # Integrity check failed + ELAST* = OSErrorCode(97) + # Must be equal largest errno + +elif defined(dragonfly) or defined(dragonflybsd): + ## Source: https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/errno.h + const + EPERM* = OSErrorCode(1) + # Operation not permitted + ENOENT* = OSErrorCode(2) + # No such file or directory + ESRCH* = OSErrorCode(3) + # No such process + EINTR* = OSErrorCode(4) + # Interrupted system call + EIO* = OSErrorCode(5) + # Input/output error + ENXIO* = OSErrorCode(6) + # Device not configured + E2BIG* = OSErrorCode(7) + # Argument list too long + ENOEXEC* = OSErrorCode(8) + # Exec format error + EBADF* = OSErrorCode(9) + # Bad file descriptor + ECHILD* = OSErrorCode(10) + # No child processes + EDEADLK* = OSErrorCode(11) + # Resource deadlock avoided + ENOMEM* = OSErrorCode(12) + # Cannot allocate memory + EACCES* = OSErrorCode(13) + # Permission denied + EFAULT* = OSErrorCode(14) + # Bad address + ENOTBLK* = OSErrorCode(15) + # Block device required + EBUSY* = OSErrorCode(16) + # Device busy + EEXIST* = OSErrorCode(17) + # File exists + EXDEV* = OSErrorCode(18) + # Cross-device link + ENODEV* = OSErrorCode(19) + # Operation not supported by device + ENOTDIR* = OSErrorCode(20) + # Not a directory + EISDIR* = OSErrorCode(21) + # Is a directory + EINVAL* = OSErrorCode(22) + # Invalid argument + ENFILE* = OSErrorCode(23) + # Too many open files in system + EMFILE* = OSErrorCode(24) + # Too many open files + ENOTTY* = OSErrorCode(25) + # Inappropriate ioctl for device + ETXTBSY* = OSErrorCode(26) + # Text file busy + EFBIG* = OSErrorCode(27) + # File too large + ENOSPC* = OSErrorCode(28) + # No space left on device + ESPIPE* = OSErrorCode(29) + # Illegal seek + EROFS* = OSErrorCode(30) + # Read-only filesystem + EMLINK* = OSErrorCode(31) + # Too many links + EPIPE* = OSErrorCode(32) + # Broken pipe + EDOM* = OSErrorCode(33) + # Numerical argument out of domain + ERANGE* = OSErrorCode(34) + # Result too large + EAGAIN* = OSErrorCode(35) + # Resource temporarily unavailable + EWOULDBLOCK* = EAGAIN + # Operation would block + EINPROGRESS* = OSErrorCode(36) + # Operation now in progress + EALREADY* = OSErrorCode(37) + # Operation already in progress + ENOTSOCK* = OSErrorCode(38) + # Socket operation on non-socket + EDESTADDRREQ* = OSErrorCode(39) + # Destination address required + EMSGSIZE* = OSErrorCode(40) + # Message too long + EPROTOTYPE* = OSErrorCode(41) + # Protocol wrong type for socket + ENOPROTOOPT* = OSErrorCode(42) + # Protocol not available + EPROTONOSUPPORT* = OSErrorCode(43) + # Protocol not supported + ESOCKTNOSUPPORT* = OSErrorCode(44) + # Socket type not supported + EOPNOTSUPP* = OSErrorCode(45) + # Operation not supported + ENOTSUP* = EOPNOTSUPP + # Operation not supported + EPFNOSUPPORT* = OSErrorCode(46) + # Protocol family not supported + EAFNOSUPPORT* = OSErrorCode(47) + # Address family not supported by protocol family + EADDRINUSE* = OSErrorCode(48) + # Address already in use + EADDRNOTAVAIL* = OSErrorCode(49) + # Can't assign requested address + ENETDOWN* = OSErrorCode(50) + # Network is down + ENETUNREACH* = OSErrorCode(51) + # Network is unreachable + ENETRESET* = OSErrorCode(52) + # Network dropped connection on reset + ECONNABORTED* = OSErrorCode(53) + # Software caused connection abort + ECONNRESET* = OSErrorCode(54) + # Connection reset by peer + ENOBUFS* = OSErrorCode(55) + # No buffer space available + EISCONN* = OSErrorCode(56) + # Socket is already connected + ENOTCONN* = OSErrorCode(57) + # Socket is not connected + ESHUTDOWN* = OSErrorCode(58) + # Can't send after socket shutdown + ETOOMANYREFS* = OSErrorCode(59) + # Too many references: can't splice + ETIMEDOUT* = OSErrorCode(60) + # Operation timed out + ECONNREFUSED* = OSErrorCode(61) + # Connection refused + ELOOP* = OSErrorCode(62) + # Too many levels of symbolic links + ENAMETOOLONG* = OSErrorCode(63) + # File name too long + EHOSTDOWN* = OSErrorCode(64) + # Host is down + EHOSTUNREACH* = OSErrorCode(65) + # No route to host + ENOTEMPTY* = OSErrorCode(66) + # Directory not empty + EPROCLIM* = OSErrorCode(67) + # Too many processes + EUSERS* = OSErrorCode(68) + # Too many users + EDQUOT* = OSErrorCode(69) + # Disc quota exceeded + ESTALE* = OSErrorCode(70) + # Stale NFS file handle + EREMOTE* = OSErrorCode(71) + # Too many levels of remote in path + EBADRPC* = OSErrorCode(72) + # RPC struct is bad + ERPCMISMATCH* = OSErrorCode(73) + # RPC version wrong + EPROGUNAVAIL* = OSErrorCode(74) + # RPC prog. not avail + EPROGMISMATCH* = OSErrorCode(75) + # Program version wrong + EPROCUNAVAIL* = OSErrorCode(76) + # Bad procedure for program + ENOLCK* = OSErrorCode(77) + # No locks available + ENOSYS* = OSErrorCode(78) + # Function not implemented + EFTYPE* = OSErrorCode(79) + # Inappropriate file type or format + EAUTH* = OSErrorCode(80) + # Authentication error + ENEEDAUTH* = OSErrorCode(81) + # Need authenticator + EIDRM* = OSErrorCode(82) + # Identifier removed + ENOMSG* = OSErrorCode(83) + # No message of desired type + EOVERFLOW* = OSErrorCode(84) + # Value too large to be stored in data type + ECANCELED* = OSErrorCode(85) + # Operation canceled + EILSEQ* = OSErrorCode(86) + # Illegal byte sequence + ENOATTR* = OSErrorCode(87) + # Attribute not found + EDOOFUS* = OSErrorCode(88) + # Programming error + EBADMSG* = OSErrorCode(89) + # Bad message + EMULTIHOP* = OSErrorCode(90) + # Multihop attempted + ENOLINK* = OSErrorCode(91) + # Link has been severed + EPROTO* = OSErrorCode(92) + # Protocol error + ENOMEDIUM* = OSErrorCode(93) + # linux + ENOTRECOVERABLE* = OSErrorCode(94) + # State not recoverable + EOWNERDEAD* = OSErrorCode(95) + # Previous owner died + EASYNC* = OSErrorCode(99) + # XXX + ELAST* = OSErrorCode(99) + # Must be equal largest errno + +elif defined(macos) or defined(macosx): + ## Source: https://github.com/apple/darwin-xnu/blob/main/bsd/sys/errno.h + const + EPERM* = OSErrorCode(1) + # Operation not permitted + ENOENT* = OSErrorCode(2) + # No such file or directory + ESRCH* = OSErrorCode(3) + # No such process + EINTR* = OSErrorCode(4) + # Interrupted system call + EIO* = OSErrorCode(5) + # Input/output error + ENXIO* = OSErrorCode(6) + # Device not configured + E2BIG* = OSErrorCode(7) + # Argument list too long + ENOEXEC* = OSErrorCode(8) + # Exec format error + EBADF* = OSErrorCode(9) + # Bad file descriptor + ECHILD* = OSErrorCode(10) + # No child processes + EDEADLK* = OSErrorCode(11) + # Resource deadlock avoided + ENOMEM* = OSErrorCode(12) + # Cannot allocate memory + EACCES* = OSErrorCode(13) + # Permission denied + EFAULT* = OSErrorCode(14) + # Bad address + ENOTBLK* = OSErrorCode(15) + # Block device required + EBUSY* = OSErrorCode(16) + # Device / Resource busy + EEXIST* = OSErrorCode(17) + # File exists + EXDEV* = OSErrorCode(18) + # Cross-device link + ENODEV* = OSErrorCode(19) + # Operation not supported by device + ENOTDIR* = OSErrorCode(20) + # Not a directory + EISDIR* = OSErrorCode(21) + # Is a directory + EINVAL* = OSErrorCode(22) + # Invalid argument + ENFILE* = OSErrorCode(23) + # Too many open files in system + EMFILE* = OSErrorCode(24) + # Too many open files + ENOTTY* = OSErrorCode(25) + # Inappropriate ioctl for device + ETXTBSY* = OSErrorCode(26) + # Text file busy + EFBIG* = OSErrorCode(27) + # File too large + ENOSPC* = OSErrorCode(28) + # No space left on device + ESPIPE* = OSErrorCode(29) + # Illegal seek + EROFS* = OSErrorCode(30) + # Read-only file system + EMLINK* = OSErrorCode(31) + # Too many links + EPIPE* = OSErrorCode(32) + # Broken pipe + EDOM* = OSErrorCode(33) + # Numerical argument out of domain + ERANGE* = OSErrorCode(34) + # Result too large + EAGAIN* = OSErrorCode(35) + # Resource temporarily unavailable + EWOULDBLOCK* = EAGAIN + # Operation would block + EINPROGRESS* = OSErrorCode(36) + # Operation now in progress + EALREADY* = OSErrorCode(37) + # Operation already in progress + ENOTSOCK* = OSErrorCode(38) + # Socket operation on non-socket + EDESTADDRREQ* = OSErrorCode(39) + # Destination address required + EMSGSIZE* = OSErrorCode(40) + # Message too long + EPROTOTYPE* = OSErrorCode(41) + # Protocol wrong type for socket + ENOPROTOOPT* = OSErrorCode(42) + # Protocol not available + EPROTONOSUPPORT* = OSErrorCode(43) + # Protocol not supported + ESOCKTNOSUPPORT* = OSErrorCode(44) + # Socket type not supported + ENOTSUP* = OSErrorCode(45) + # Operation not supported + EPFNOSUPPORT* = OSErrorCode(46) + # Protocol family not supported + EAFNOSUPPORT* = OSErrorCode(47) + # Address family not supported by protocol family + EADDRINUSE* = OSErrorCode(48) + # Address already in use + EADDRNOTAVAIL* = OSErrorCode(49) + # Can't assign requested address + ENETDOWN* = OSErrorCode(50) + # Network is down + ENETUNREACH* = OSErrorCode(51) + # Network is unreachable + ENETRESET* = OSErrorCode(52) + # Network dropped connection on reset + ECONNABORTED* = OSErrorCode(53) + # Software caused connection abort + ECONNRESET* = OSErrorCode(54) + # Connection reset by peer + ENOBUFS* = OSErrorCode(55) + # No buffer space available + EISCONN* = OSErrorCode(56) + # Socket is already connected + ENOTCONN* = OSErrorCode(57) + # Socket is not connected + ESHUTDOWN* = OSErrorCode(58) + # Can't send after socket shutdown + ETOOMANYREFS* = OSErrorCode(59) + # Too many references: can't splice + ETIMEDOUT* = OSErrorCode(60) + # Operation timed out + ECONNREFUSED* = OSErrorCode(61) + # Connection refused + ELOOP* = OSErrorCode(62) + # Too many levels of symbolic links + ENAMETOOLONG* = OSErrorCode(63) + # File name too long + EHOSTDOWN* = OSErrorCode(64) + # Host is down + EHOSTUNREACH* = OSErrorCode(65) + # No route to host + ENOTEMPTY* = OSErrorCode(66) + # Directory not empty + EPROCLIM* = OSErrorCode(67) + # Too many processes + EUSERS* = OSErrorCode(68) + # Too many users + EDQUOT* = OSErrorCode(69) + # Disc quota exceeded + ESTALE* = OSErrorCode(70) + # Stale NFS file handle + EREMOTE* = OSErrorCode(71) + # Too many levels of remote in path + EBADRPC* = OSErrorCode(72) + # RPC struct is bad + ERPCMISMATCH* = OSErrorCode(73) + # RPC version wrong + EPROGUNAVAIL* = OSErrorCode(74) + # RPC prog. not avail + EPROGMISMATCH* = OSErrorCode(75) + # Program version wrong + EPROCUNAVAIL* = OSErrorCode(76) + # Bad procedure for program + ENOLCK* = OSErrorCode(77) + # No locks available + ENOSYS* = OSErrorCode(78) + # Function not implemented + EFTYPE* = OSErrorCode(79) + # Inappropriate file type or format + EAUTH* = OSErrorCode(80) + # Authentication error + ENEEDAUTH* = OSErrorCode(81) + # Need authenticator + EPWROFF* = OSErrorCode(82) + # Device power is off + EDEVERR* = OSErrorCode(83) + # Device error, e.g. paper out + EOVERFLOW* = OSErrorCode(84) + # Value too large to be stored in data type + EBADEXEC* = OSErrorCode(85) + # Bad executable + EBADARCH* = OSErrorCode(86) + # Bad CPU type in executable + ESHLIBVERS* = OSErrorCode(87) + # Shared library version mismatch + EBADMACHO* = OSErrorCode(88) + # Malformed Macho file + ECANCELED* = OSErrorCode(89) + # Operation canceled + EIDRM* = OSErrorCode(90) + # Identifier removed + ENOMSG* = OSErrorCode(91) + # No message of desired type + EILSEQ* = OSErrorCode(92) + # Illegal byte sequence + ENOATTR* = OSErrorCode(93) + # Attribute not found + EBADMSG* = OSErrorCode(94) + # Bad message + EMULTIHOP* = OSErrorCode(95) + # Reserved + ENODATA* = OSErrorCode(96) + # No message available on STREAM + ENOLINK* = OSErrorCode(97) + # Reserved + ENOSR* = OSErrorCode(98) + # No STREAM resources + ENOSTR* = OSErrorCode(99) + # Not a STREAM + EPROTO* = OSErrorCode(100) + # Protocol error + ETIME* = OSErrorCode(101) + # STREAM ioctl timeout + EOPNOTSUPP* = OSErrorCode(102) + # Operation not supported on socket + ENOPOLICY* = OSErrorCode(103) + # No such policy registered + ENOTRECOVERABLE* = OSErrorCode(104) + # State not recoverable + EOWNERDEAD* = OSErrorCode(105) + # Previous owner died + EQFULL* = OSErrorCode(106) + # Interface output queue is full + ELAST* = OSErrorCode(106) + # Must be equal largest errno + +elif defined(linux): + ## Source: https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno-base.h + ## https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno.h + const + EPERM* = OSErrorCode(1) + # Operation not permitted + ENOENT* = OSErrorCode(2) + # No such file or directory + ESRCH* = OSErrorCode(3) + # No such process + EINTR* = OSErrorCode(4) + # Interrupted system call + EIO* = OSErrorCode(5) + # I/O error + ENXIO* = OSErrorCode(6) + # No such device or address + E2BIG* = OSErrorCode(7) + # Argument list too long + ENOEXEC* = OSErrorCode(8) + # Exec format error + EBADF* = OSErrorCode(9) + # Bad file number + ECHILD* = OSErrorCode(10) + # No child processes + EAGAIN* = OSErrorCode(11) + # Try again + ENOMEM* = OSErrorCode(12) + # Out of memory + EACCES* = OSErrorCode(13) + # Permission denied + EFAULT* = OSErrorCode(14) + # Bad address + ENOTBLK* = OSErrorCode(15) + # Block device required + EBUSY* = OSErrorCode(16) + # Device or resource busy + EEXIST* = OSErrorCode(17) + # File exists + EXDEV* = OSErrorCode(18) + # Cross-device link + ENODEV* = OSErrorCode(19) + # No such device + ENOTDIR* = OSErrorCode(20) + # Not a directory + EISDIR* = OSErrorCode(21) + # Is a directory + EINVAL* = OSErrorCode(22) + # Invalid argument + ENFILE* = OSErrorCode(23) + # File table overflow + EMFILE* = OSErrorCode(24) + # Too many open files + ENOTTY* = OSErrorCode(25) + # Not a typewriter + ETXTBSY* = OSErrorCode(26) + # Text file busy + EFBIG* = OSErrorCode(27) + # File too large + ENOSPC* = OSErrorCode(28) + # No space left on device + ESPIPE* = OSErrorCode(29) + # Illegal seek + EROFS* = OSErrorCode(30) + # Read-only file system + EMLINK* = OSErrorCode(31) + # Too many links + EPIPE* = OSErrorCode(32) + # Broken pipe + EDOM* = OSErrorCode(33) + # Math argument out of domain of func + ERANGE* = OSErrorCode(34) + # Math result not representable + EDEADLK* = OSErrorCode(35) + # Resource deadlock would occur + ENAMETOOLONG* = OSErrorCode(36) + # File name too long + ENOLCK* = OSErrorCode(37) + # No record locks available + ENOSYS* = OSErrorCode(38) + # Invalid system call number + ENOTEMPTY* = OSErrorCode(39) + # Directory not empty + ELOOP* = OSErrorCode(40) + # Too many symbolic links encountered + EWOULDBLOCK* = EAGAIN + # Operation would block + ENOMSG* = OSErrorCode(42) + # No message of desired type + EIDRM* = OSErrorCode(43) + # Identifier removed + ECHRNG* = OSErrorCode(44) + # Channel number out of range + EL2NSYNC* = OSErrorCode(45) + # Level 2 not synchronized + EL3HLT* = OSErrorCode(46) + # Level 3 halted + EL3RST* = OSErrorCode(47) + # Level 3 reset + ELNRNG* = OSErrorCode(48) + # Link number out of range + EUNATCH* = OSErrorCode(49) + # Protocol driver not attached + ENOCSI* = OSErrorCode(50) + # No CSI structure available + EL2HLT* = OSErrorCode(51) + # Level 2 halted + EBADE* = OSErrorCode(52) + # Invalid exchange + EBADR* = OSErrorCode(53) + # Invalid request descriptor + EXFULL* = OSErrorCode(54) + # Exchange full + ENOANO* = OSErrorCode(55) + # No anode + EBADRQC* = OSErrorCode(56) + # Invalid request code + EBADSLT* = OSErrorCode(57) + # Invalid slot + EDEADLOCK* = EDEADLK + # Resource deadlock would occur + EBFONT* = OSErrorCode(59) + # Bad font file format + ENOSTR* = OSErrorCode(60) + # Device not a stream + ENODATA* = OSErrorCode(61) + # No data available + ETIME* = OSErrorCode(62) + # Timer expired + ENOSR* = OSErrorCode(63) + # Out of streams resources + ENONET* = OSErrorCode(64) + # Machine is not on the network + ENOPKG* = OSErrorCode(65) + # Package not installed + EREMOTE* = OSErrorCode(66) + # Object is remote + ENOLINK* = OSErrorCode(67) + # Link has been severed + EADV* = OSErrorCode(68) + # Advertise error + ESRMNT* = OSErrorCode(69) + # Srmount error + ECOMM* = OSErrorCode(70) + # Communication error on send + EPROTO* = OSErrorCode(71) + # Protocol error + EMULTIHOP* = OSErrorCode(72) + # Multihop attempted + EDOTDOT* = OSErrorCode(73) + # RFS specific error + EBADMSG* = OSErrorCode(74) + # Not a data message + EOVERFLOW* = OSErrorCode(75) + # Value too large for defined data type + ENOTUNIQ* = OSErrorCode(76) + # Name not unique on network + EBADFD* = OSErrorCode(77) + # File descriptor in bad state + EREMCHG* = OSErrorCode(78) + # Remote address changed + ELIBACC* = OSErrorCode(79) + # Can not access a needed shared library + ELIBBAD* = OSErrorCode(80) + # Accessing a corrupted shared library + ELIBSCN* = OSErrorCode(81) + # .lib section in a.out corrupted + ELIBMAX* = OSErrorCode(82) + # Attempting to link in too many shared libraries + ELIBEXEC* = OSErrorCode(83) + # Cannot exec a shared library directly + EILSEQ* = OSErrorCode(84) + # Illegal byte sequence + ERESTART* = OSErrorCode(85) + # Interrupted system call should be restarted + ESTRPIPE* = OSErrorCode(86) + # Streams pipe error + EUSERS* = OSErrorCode(87) + # Too many users + ENOTSOCK* = OSErrorCode(88) + # Socket operation on non-socket + EDESTADDRREQ* = OSErrorCode(89) + # Destination address required + EMSGSIZE* = OSErrorCode(90) + # Message too long + EPROTOTYPE* = OSErrorCode(91) + # Protocol wrong type for socket + ENOPROTOOPT* = OSErrorCode(92) + # Protocol not available + EPROTONOSUPPORT* = OSErrorCode(93) + # Protocol not supported + ESOCKTNOSUPPORT* = OSErrorCode(94) + # Socket type not supported + EOPNOTSUPP* = OSErrorCode(95) + # Operation not supported on transport endpoint + EPFNOSUPPORT* = OSErrorCode(96) + # Protocol family not supported + EAFNOSUPPORT* = OSErrorCode(97) + # Address family not supported by protocol + EADDRINUSE* = OSErrorCode(98) + # Address already in use + EADDRNOTAVAIL* = OSErrorCode(99) + # Cannot assign requested address + ENETDOWN* = OSErrorCode(100) + # Network is down + ENETUNREACH* = OSErrorCode(101) + # Network is unreachable + ENETRESET* = OSErrorCode(102) + # Network dropped connection because of reset + ECONNABORTED* = OSErrorCode(103) + # Software caused connection abort + ECONNRESET* = OSErrorCode(104) + # Connection reset by peer + ENOBUFS* = OSErrorCode(105) + # No buffer space available + EISCONN* = OSErrorCode(106) + # Transport endpoint is already connected + ENOTCONN* = OSErrorCode(107) + # Transport endpoint is not connected + ESHUTDOWN* = OSErrorCode(108) + # Cannot send after transport endpoint shutdown + ETOOMANYREFS* = OSErrorCode(109) + # Too many references: cannot splice + ETIMEDOUT* = OSErrorCode(110) + # Connection timed out + ECONNREFUSED* = OSErrorCode(111) + # Connection refused + EHOSTDOWN* = OSErrorCode(112) + # Host is down + EHOSTUNREACH* = OSErrorCode(113) + # No route to host + EALREADY* = OSErrorCode(114) + # Operation already in progress + EINPROGRESS* = OSErrorCode(115) + # Operation now in progress + ESTALE* = OSErrorCode(116) + # Stale file handle + EUCLEAN* = OSErrorCode(117) + # Structure needs cleaning + ENOTNAM* = OSErrorCode(118) + # Not a XENIX named type file + ENAVAIL* = OSErrorCode(119) + # No XENIX semaphores available + EISNAM* = OSErrorCode(120) + # Is a named type file + EREMOTEIO* = OSErrorCode(121) + # Remote I/O error + EDQUOT* = OSErrorCode(122) + # Quota exceeded + ENOMEDIUM* = OSErrorCode(123) + # No medium found + EMEDIUMTYPE* = OSErrorCode(124) + # Wrong medium type + ECANCELED* = OSErrorCode(125) + # Operation Canceled + ENOKEY* = OSErrorCode(126) + # Required key not available + EKEYEXPIRED* = OSErrorCode(127) + # Key has expired + EKEYREVOKED* = OSErrorCode(128) + # Key has been revoked + EKEYREJECTED* = OSErrorCode(129) + # Key was rejected by service + EOWNERDEAD* = OSErrorCode(130) + # Owner died + ENOTRECOVERABLE* = OSErrorCode(131) + # State not recoverable + ERFKILL* = OSErrorCode(132) + # Operation not possible due to RF-kill + EHWPOISON* = OSErrorCode(133) + # Memory page has hardware error +elif defined(windows): + const + ERROR_SUCCESS* = OSErrorCode(0) + ERROR_FILE_NOT_FOUND* = OSErrorCode(2) + ERROR_TOO_MANY_OPEN_FILES* = OSErrorCode(4) + ERROR_ACCESS_DENIED* = OSErrorCode(5) + ERROR_BROKEN_PIPE* = OSErrorCode(109) + ERROR_BUFFER_OVERFLOW* = OSErrorCode(111) + ERROR_PIPE_BUSY* = OSErrorCode(231) + ERROR_NO_DATA* = OSErrorCode(232) + ERROR_PIPE_NOT_CONNECTED* = OSErrorCode(233) + ERROR_PIPE_CONNECTED* = OSErrorCode(535) + ERROR_OPERATION_ABORTED* = OSErrorCode(995) + ERROR_IO_PENDING* = OSErrorCode(997) + ERROR_CONNECTION_REFUSED* = OSErrorCode(1225) + ERROR_CONNECTION_ABORTED* = OSErrorCode(1236) + WSAEMFILE* = OSErrorCode(10024) + WSAENETDOWN* = OSErrorCode(10050) + WSAENETRESET* = OSErrorCode(10052) + WSAECONNABORTED* = OSErrorCode(10053) + WSAECONNRESET* = OSErrorCode(10054) + WSAENOBUFS* = OSErrorCode(10055) + WSAETIMEDOUT* = OSErrorCode(10060) + WSAEADDRINUSE* = OSErrorCode(10048) + WSAEDISCON* = OSErrorCode(10101) + WSANOTINITIALISED* = OSErrorCode(10093) + WSAENOTSOCK* = OSErrorCode(10038) + WSAEINPROGRESS* = OSErrorCode(10036) + WSAEINTR* = OSErrorCode(10004) + WSAEWOULDBLOCK* = OSErrorCode(10035) + ERROR_NETNAME_DELETED* = OSErrorCode(64) + STATUS_PENDING* = OSErrorCode(0x103) + +else: + {.fatal: "Operation system is not yet supported!".} diff --git a/chronos/osutils.nim b/chronos/osutils.nim index 2359469..2ff1072 100644 --- a/chronos/osutils.nim +++ b/chronos/osutils.nim @@ -7,9 +7,9 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) import stew/results -import osdefs +import osdefs, oserrno -export results +export results, osdefs, oserrno when (NimMajor, NimMinor) < (1, 4): {.push raises: [Defect].} @@ -187,10 +187,10 @@ when defined(windows): let cleanupFlag = block: let errorCode = osLastError() - case int(errorCode) - of osdefs.ERROR_PIPE_CONNECTED: + case errorCode + of ERROR_PIPE_CONNECTED: false - of osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: if DescriptorFlag.NonBlock in writeset: var bytesRead = 0.DWORD if getOverlappedResult(pipeIn, addr ovl, bytesRead, 1) == FALSE: @@ -215,7 +215,7 @@ else: var res = 0 while true: res = body - if not((res == -1) and (osLastError() == EINTR)): + if not((res == -1) and (osLastError() == oserrno.EINTR)): break res diff --git a/chronos/selectors2.nim b/chronos/selectors2.nim index bbb52a5..45c4533 100644 --- a/chronos/selectors2.nim +++ b/chronos/selectors2.nim @@ -32,8 +32,8 @@ # backwards-compatible. import stew/results -import osdefs, osutils -export results +import osdefs, osutils, oserrno +export results, oserrno const asyncEventsCount* {.intdefine.} = 64 diff --git a/chronos/transports/common.nim b/chronos/transports/common.nim index 8d75a5a..0b3f431 100644 --- a/chronos/transports/common.nim +++ b/chronos/transports/common.nim @@ -12,10 +12,17 @@ when (NimMajor, NimMinor) < (1, 4): else: {.push raises: [].} -import std/[strutils, nativesockets, net] +import std/[strutils] import stew/[base10, byteutils] -import ".."/[asyncloop, osdefs] -export net +import ".."/[asyncloop, osdefs, oserrno] + +from std/net import Domain, `==`, IpAddress, IpAddressFamily, parseIpAddress, + SockType, Protocol, Port, `$` +from std/nativesockets import toInt, `$` + +export Domain, `==`, IpAddress, IpAddressFamily, parseIpAddress, SockType, + Protocol, Port, toInt, `$` + const DefaultStreamBufferSize* = 4096 ## Default buffer size for stream @@ -600,35 +607,37 @@ proc isLiteral*[T](s: seq[T]): bool {.inline.} = else: (cast[ptr SeqHeader](s).reserved and (1 shl (sizeof(int) * 8 - 2))) != 0 -template getTransportTooManyError*(code: int = 0): ref TransportTooManyError = +template getTransportTooManyError*( + code = OSErrorCode(0) + ): ref TransportTooManyError = let msg = when defined(posix): - if code == 0: + if code == OSErrorCode(0): "Too many open transports" - elif code == EMFILE: + elif code == oserrno.EMFILE: "[EMFILE] Too many open files in the process" - elif code == ENFILE: + elif code == oserrno.ENFILE: "[ENFILE] Too many open files in system" - elif code == ENOBUFS: + elif code == oserrno.ENOBUFS: "[ENOBUFS] No buffer space available" - elif code == ENOMEM: + elif code == oserrno.ENOMEM: "[ENOMEM] Not enough memory availble" else: - "[" & $code & "] Too many open transports" + "[" & $int(code) & "] Too many open transports" elif defined(windows): case code - of 0: + of OSErrorCode(0): "Too many open transports" - of osdefs.ERROR_TOO_MANY_OPEN_FILES: + of ERROR_TOO_MANY_OPEN_FILES: "[ERROR_TOO_MANY_OPEN_FILES] Too many open files" - of osdefs.WSAENOBUFS: + of WSAENOBUFS: "[WSAENOBUFS] No buffer space available" - of osdefs.WSAEMFILE: + of WSAEMFILE: "[WSAEMFILE] Too many open sockets" else: - "[" & $code & "] Too many open transports" + "[" & $int(code) & "] Too many open transports" else: - "[" & $code & "] Too many open transports" + "[" & $int(code) & "] Too many open transports" newException(TransportTooManyError, msg) template getConnectionAbortedError*(m: string = ""): ref TransportAbortedError = @@ -639,32 +648,34 @@ template getConnectionAbortedError*(m: string = ""): ref TransportAbortedError = "[ECONNABORTED] " & m newException(TransportAbortedError, msg) -template getConnectionAbortedError*(code: int): ref TransportAbortedError = +template getConnectionAbortedError*( + code: OSErrorCode + ): ref TransportAbortedError = let msg = when defined(posix): - if code == 0: + if code == OSErrorCode(0): "[ECONNABORTED] Connection has been aborted before being accepted" - elif code == EPERM: + elif code == oserrno.EPERM: "[EPERM] Firewall rules forbid connection" - elif code == ETIMEDOUT: + elif code == oserrno.ETIMEDOUT: "[ETIMEDOUT] Operation has been timed out" else: - "[" & $code & "] Connection has been aborted" + "[" & $int(code) & "] Connection has been aborted" elif defined(windows): case code - of 0, osdefs.WSAECONNABORTED: + of OSErrorCode(0), oserrno.WSAECONNABORTED: "[ECONNABORTED] Connection has been aborted before being accepted" - of osdefs.WSAENETDOWN: + of WSAENETDOWN: "[ENETDOWN] Network is down" - of osdefs.WSAENETRESET: + of oserrno.WSAENETRESET: "[ENETRESET] Network dropped connection on reset" - of osdefs.WSAECONNRESET: + of oserrno.WSAECONNRESET: "[ECONNRESET] Connection reset by peer" - of osdefs.WSAETIMEDOUT: + of WSAETIMEDOUT: "[ETIMEDOUT] Connection timed out" else: - "[" & $code & "] Connection has been aborted" + "[" & $int(code) & "] Connection has been aborted" else: - "[" & $code & "] Connection has been aborted" + "[" & $int(code) & "] Connection has been aborted" newException(TransportAbortedError, msg) diff --git a/chronos/transports/datagram.nim b/chronos/transports/datagram.nim index f372af2..a642b59 100644 --- a/chronos/transports/datagram.nim +++ b/chronos/transports/datagram.nim @@ -14,7 +14,7 @@ else: import std/deques when not(defined(windows)): import ".."/selectors2 -import ".."/[asyncloop, osdefs, handles] +import ".."/[asyncloop, osdefs, oserrno, handles] import "."/common type @@ -139,10 +139,11 @@ when defined(windows): transp.state.excl(WritePending) let err = transp.wovl.data.errCode let vector = transp.queue.popFirst() - if err == OSErrorCode(-1): + case err + of OSErrorCode(-1): if not(vector.writer.finished()): vector.writer.complete() - elif int(err) == osdefs.ERROR_OPERATION_ABORTED: + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.incl(WritePaused) if not(vector.writer.finished()): @@ -170,13 +171,14 @@ when defined(windows): DWORD(0), cast[POVERLAPPED](addr transp.wovl), nil) if ret != 0: let err = osLastError() - if int(err) == osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.excl(WritePending) transp.state.incl(WritePaused) if not(vector.writer.finished()): vector.writer.complete() - elif int(err) == osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: transp.queue.addFirst(vector) else: transp.state.excl(WritePending) @@ -201,14 +203,15 @@ when defined(windows): ## Continuation transp.state.excl(ReadPending) let err = transp.rovl.data.errCode - if err == OSErrorCode(-1): + case err + of OSErrorCode(-1): let bytesCount = transp.rovl.data.bytesCount if bytesCount == 0: transp.state.incl({ReadEof, ReadPaused}) fromSAddr(addr transp.raddr, transp.ralen, raddr) transp.buflen = int(bytesCount) asyncSpawn transp.function(transp, raddr) - elif int(err) == osdefs.ERROR_OPERATION_ABORTED: + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt or closeSocket() call. transp.state.incl(ReadPaused) if ReadClosed in transp.state and not(transp.future.finished()): @@ -237,15 +240,16 @@ when defined(windows): cast[POVERLAPPED](addr transp.rovl), nil) if ret != 0: let err = osLastError() - if int(err) == osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.excl(ReadPending) transp.state.incl(ReadPaused) - elif int(err) == osdefs.WSAECONNRESET: + of WSAECONNRESET: transp.state.excl(ReadPending) transp.state.incl({ReadPaused, ReadEof}) break - elif int(err) == osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: discard else: transp.state.excl(ReadPending) @@ -419,7 +423,8 @@ else: asyncSpawn transp.function(transp, raddr) else: let err = osLastError() - if int(err) == EINTR: + case err + of oserrno.EINTR: continue else: transp.buflen = 0 @@ -454,7 +459,8 @@ else: vector.writer.complete() else: let err = osLastError() - if int(err) == EINTR: + case err + of oserrno.EINTR: continue else: if not(vector.writer.finished()): diff --git a/chronos/transports/osnet.nim b/chronos/transports/osnet.nim index c5753d8..29b9562 100644 --- a/chronos/transports/osnet.nim +++ b/chronos/transports/osnet.nim @@ -838,17 +838,15 @@ elif defined(macosx) or defined(macos) or defined(bsd): if family == osdefs.AF_INET: fromSAddr(cast[ptr Sockaddr_storage](ifap.ifa_netmask), SockLen(sizeof(Sockaddr_in)), na) - if cint(ifaddress.host.family) == osdefs.AF_INET: + if ifaddress.host.family == AddressFamily.IPv4: ifaddress.net = IpNet.init(ifaddress.host, na) elif family == osdefs.AF_INET6: fromSAddr(cast[ptr Sockaddr_storage](ifap.ifa_netmask), SockLen(sizeof(Sockaddr_in6)), na) - if cint(ifaddress.host.family) == osdefs.AF_INET6: + if ifaddress.host.family == AddressFamily.IPv6: ifaddress.net = IpNet.init(ifaddress.host, na) if ifaddress.host.family != AddressFamily.None: - if len(res[i].addresses) == 0: - res[i].addresses = newSeq[InterfaceAddress]() res[i].addresses.add(ifaddress) ifap = ifap.ifa_next @@ -1047,10 +1045,11 @@ elif defined(windows): var addresses = cast[ptr IpAdapterAddressesXp](addr buffer[0]) gres = getAdaptersAddresses(osdefs.AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nil, addresses, addr size) - if gres == ERROR_SUCCESS: + case OSErrorCode(gres) + of ERROR_SUCCESS: buffer.setLen(size) break - elif gres == ERROR_BUFFER_OVERFLOW: + of ERROR_BUFFER_OVERFLOW: discard else: break @@ -1058,7 +1057,7 @@ elif defined(windows): if tries >= MaxTries: break - if gres == ERROR_SUCCESS: + if OSErrorCode(gres) == ERROR_SUCCESS: var slider = cast[ptr IpAdapterAddressesXp](addr buffer[0]) while not isNil(slider): var iface = NetworkInterface( diff --git a/chronos/transports/stream.nim b/chronos/transports/stream.nim index 4264e77..1b28b1d 100644 --- a/chronos/transports/stream.nim +++ b/chronos/transports/stream.nim @@ -13,7 +13,7 @@ else: {.push raises: [].} import std/deques -import ".."/[asyncloop, handles, osdefs, osutils] +import ".."/[asyncloop, handles, osdefs, osutils, oserrno] import common type @@ -322,10 +322,12 @@ when defined(windows): (t).wwsabuf.buf = cast[cstring](v.buf) (t).wwsabuf.len = cast[ULONG](v.buflen) - proc isConnResetError(err: OSErrorCode): bool {.inline.} = - result = (err == OSErrorCode(osdefs.WSAECONNRESET)) or - (err == OSErrorCode(osdefs.WSAECONNABORTED)) or - (err == OSErrorCode(osdefs.ERROR_PIPE_NOT_CONNECTED)) + func isConnResetError(err: OSErrorCode): bool {.inline.} = + case err + of WSAECONNRESET, WSAECONNABORTED, ERROR_PIPE_NOT_CONNECTED: + true + else: + false proc writeStreamLoop(udata: pointer) {.gcsafe, nimcall.} = var bytesCount: uint32 @@ -343,7 +345,8 @@ when defined(windows): ## Continuation transp.state.excl(WritePending) let err = transp.wovl.data.errCode - if err == OSErrorCode(-1): + case err + of OSErrorCode(-1): bytesCount = transp.wovl.data.bytesCount var vector = transp.queue.popFirst() if bytesCount == 0: @@ -377,7 +380,7 @@ when defined(windows): # This conversion to `int` safe, because its impossible # to call write() with size bigger than `int`. vector.writer.complete(int(transp.wwsabuf.len)) - elif int(err) == osdefs.ERROR_OPERATION_ABORTED: + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.incl({WritePaused, WriteEof}) let vector = transp.queue.popFirst() @@ -416,7 +419,8 @@ when defined(windows): cast[POVERLAPPED](addr transp.wovl), nil) if ret != 0: let err = osLastError() - if int(err) == osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.excl(WritePending) transp.state.incl({WritePaused, WriteEof}) @@ -424,7 +428,7 @@ when defined(windows): vector.writer.complete(0) completePendingWriteQueue(transp.queue, 0) break - elif int(err) == osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: transp.queue.addFirst(vector) else: transp.state.excl(WritePending) @@ -456,7 +460,8 @@ when defined(windows): nil, 0'u32) if ret == 0: let err = osLastError() - if int(err) == osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.excl(WritePending) transp.state.incl({WritePaused, WriteEof}) @@ -464,7 +469,7 @@ when defined(windows): vector.writer.complete(0) completePendingWriteQueue(transp.queue, 0) break - elif int(err) == osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: transp.queue.addFirst(vector) else: transp.state.excl(WritePending) @@ -496,8 +501,8 @@ when defined(windows): cast[POVERLAPPED](addr transp.wovl)) if ret == 0: let err = osLastError() - if int(err) in {osdefs.ERROR_OPERATION_ABORTED, - osdefs.ERROR_NO_DATA}: + case err + of ERROR_OPERATION_ABORTED, ERROR_NO_DATA: # CancelIO() interrupt transp.state.excl(WritePending) transp.state.incl({WritePaused, WriteEof}) @@ -505,7 +510,7 @@ when defined(windows): vector.writer.complete(0) completePendingWriteQueue(transp.queue, 0) break - elif int(err) == osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: transp.queue.addFirst(vector) else: transp.state.excl(WritePending) @@ -539,7 +544,8 @@ when defined(windows): ## Continuation transp.state.excl(ReadPending) let err = transp.rovl.data.errCode - if err == OSErrorCode(-1): + case err + of OSErrorCode(-1): let bytesCount = transp.rovl.data.bytesCount if bytesCount == 0: transp.state.incl({ReadEof, ReadPaused}) @@ -552,19 +558,20 @@ when defined(windows): transp.roffset = transp.offset if transp.offset == len(transp.buffer): transp.state.incl(ReadPaused) - elif int(err) in {osdefs.ERROR_OPERATION_ABORTED, - osdefs.ERROR_CONNECTION_ABORTED, - osdefs.ERROR_BROKEN_PIPE, - osdefs.ERROR_NETNAME_DELETED}: + of ERROR_OPERATION_ABORTED, ERROR_CONNECTION_ABORTED, + ERROR_BROKEN_PIPE: # CancelIO() interrupt or closeSocket() call. transp.state.incl(ReadPaused) - elif transp.kind == TransportKind.Socket and - (int(err) in {osdefs.ERROR_NETNAME_DELETED, - osdefs.WSAECONNABORTED}): - transp.state.incl({ReadEof, ReadPaused}) - elif transp.kind == TransportKind.Pipe and - (int(err) in {osdefs.ERROR_PIPE_NOT_CONNECTED}): - transp.state.incl({ReadEof, ReadPaused}) + of ERROR_NETNAME_DELETED, WSAECONNABORTED: + if transp.kind == TransportKind.Socket: + transp.state.incl({ReadEof, ReadPaused}) + else: + transp.setReadError(err) + of ERROR_PIPE_NOT_CONNECTED: + if transp.kind == TransportKind.Pipe: + transp.state.incl({ReadEof, ReadPaused}) + else: + transp.setReadError(err) else: transp.setReadError(err) @@ -593,16 +600,18 @@ when defined(windows): cast[POVERLAPPED](addr transp.rovl), nil) if ret != 0: let err = osLastError() - if int32(err) == osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.excl(ReadPending) transp.state.incl(ReadPaused) - elif int32(err) in {osdefs.WSAECONNRESET, osdefs.WSAENETRESET, - osdefs.WSAECONNABORTED}: + of WSAECONNRESET, WSAENETRESET, WSAECONNABORTED: transp.state.excl(ReadPending) transp.state.incl({ReadEof, ReadPaused}) transp.completeReader() - elif int32(err) != osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: + discard + else: transp.state.excl(ReadPending) transp.state.incl(ReadPaused) transp.setReadError(err) @@ -616,16 +625,18 @@ when defined(windows): cast[POVERLAPPED](addr transp.rovl)) if ret == 0: let err = osLastError() - if int32(err) == osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt transp.state.excl(ReadPending) transp.state.incl(ReadPaused) - elif int32(err) in {osdefs.ERROR_BROKEN_PIPE, - osdefs.ERROR_PIPE_NOT_CONNECTED}: + of ERROR_BROKEN_PIPE, ERROR_PIPE_NOT_CONNECTED: transp.state.excl(ReadPending) transp.state.incl({ReadEof, ReadPaused}) transp.completeReader() - elif int32(err) != osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: + discard + else: transp.state.excl(ReadPending) transp.state.incl(ReadPaused) transp.setReadError(err) @@ -769,8 +780,8 @@ when defined(windows): var ovl = cast[RefCustomOverlapped](udata) if not(retFuture.finished()): if ovl.data.errCode == OSErrorCode(-1): - if setsockopt(SocketHandle(sock), cint(osdefs.SOL_SOCKET), - cint(osdefs.SO_UPDATE_CONNECT_CONTEXT), nil, + if setsockopt(SocketHandle(sock), cint(SOL_SOCKET), + cint(SO_UPDATE_CONNECT_CONTEXT), nil, SockLen(0)) != 0'i32: let err = wsaGetLastError() sock.closeSocket() @@ -796,9 +807,12 @@ when defined(windows): cint(slen), nil, 0, nil, cast[POVERLAPPED](povl)) # We will not process immediate completion, to avoid undefined behavior. - if res == osdefs.FALSE: + if res == FALSE: let err = osLastError() - if int32(err) != osdefs.ERROR_IO_PENDING: + case err + of ERROR_IO_PENDING: + discard + else: GC_unref(povl) sock.closeSocket() retFuture.fail(getTransportOsError(err)) @@ -809,7 +823,7 @@ when defined(windows): ## Unix domain socket emulation with Windows Named Pipes. # For some reason Nim compiler does not detect `pipeHandle` usage in # pipeContinuation() procedure, so we marking it as {.used.} here. - var pipeHandle {.used.} = osdefs.INVALID_HANDLE_VALUE + var pipeHandle {.used.} = INVALID_HANDLE_VALUE var pipeContinuation: proc (udata: pointer) {.gcsafe, raises: [Defect].} pipeContinuation = proc (udata: pointer) {.gcsafe, raises: [Defect].} = @@ -821,15 +835,16 @@ when defined(windows): pipeName = toWideString(pipeAsciiName).valueOr: retFuture.fail(getTransportOsError(error)) return - genericFlags = osdefs.GENERIC_READ or osdefs.GENERIC_WRITE - shareFlags = osdefs.FILE_SHARE_READ or osdefs.FILE_SHARE_WRITE + genericFlags = GENERIC_READ or GENERIC_WRITE + shareFlags = FILE_SHARE_READ or FILE_SHARE_WRITE pipeHandle = createFile(pipeName, genericFlags, shareFlags, - nil, osdefs.OPEN_EXISTING, - osdefs.FILE_FLAG_OVERLAPPED, HANDLE(0)) + nil, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, HANDLE(0)) free(pipeName) - if pipeHandle == osdefs.INVALID_HANDLE_VALUE: + if pipeHandle == INVALID_HANDLE_VALUE: let err = osLastError() - if int32(err) == osdefs.ERROR_PIPE_BUSY: + case err + of ERROR_PIPE_BUSY: discard setTimer(Moment.fromNow(50.milliseconds), pipeContinuation, nil) else: @@ -856,23 +871,22 @@ when defined(windows): openMode = if FirstPipe notin server.flags: server.flags.incl(FirstPipe) - osdefs.PIPE_ACCESS_DUPLEX or osdefs.FILE_FLAG_OVERLAPPED or - osdefs.FILE_FLAG_FIRST_PIPE_INSTANCE + PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED or + FILE_FLAG_FIRST_PIPE_INSTANCE else: - osdefs.PIPE_ACCESS_DUPLEX or osdefs.FILE_FLAG_OVERLAPPED - pipeMode = osdefs.PIPE_TYPE_BYTE or osdefs.PIPE_READMODE_BYTE or - osdefs.PIPE_WAIT + PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED + pipeMode = PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT pipeHandle = createNamedPipe(pipeName, openMode, pipeMode, - osdefs.PIPE_UNLIMITED_INSTANCES, + PIPE_UNLIMITED_INSTANCES, DWORD(server.bufferSize), DWORD(server.bufferSize), DWORD(0), nil) free(pipeName) - if pipeHandle == osdefs.INVALID_HANDLE_VALUE: + if pipeHandle == INVALID_HANDLE_VALUE: return err(osLastError()) let res = register2(AsyncFD(pipeHandle)) if res.isErr(): - discard osdefs.closeHandle(pipeHandle) + discard closeHandle(pipeHandle) return err(res.error()) ok(AsyncFD(pipeHandle)) @@ -886,7 +900,8 @@ when defined(windows): ## Continuation server.apending = false if server.status notin {ServerStatus.Stopped, ServerStatus.Closed}: - if ovl.data.errCode == OSErrorCode(-1): + case ovl.data.errCode + of OSErrorCode(-1): var ntransp: StreamTransport var flags = {WinServerPipe} if NoPipeFlash in server.flags: @@ -901,7 +916,7 @@ when defined(windows): # Start tracking transport trackStream(ntransp) asyncSpawn server.function(server, ntransp) - elif int32(ovl.data.errCode) == osdefs.ERROR_OPERATION_ABORTED: + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt or close call. if server.status in {ServerStatus.Closed, ServerStatus.Stopped}: server.clean() @@ -931,19 +946,18 @@ when defined(windows): openMode = if FirstPipe notin server.flags: server.flags.incl(FirstPipe) - osdefs.PIPE_ACCESS_DUPLEX or osdefs.FILE_FLAG_OVERLAPPED or - osdefs.FILE_FLAG_FIRST_PIPE_INSTANCE + PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED or + FILE_FLAG_FIRST_PIPE_INSTANCE else: - osdefs.PIPE_ACCESS_DUPLEX or osdefs.FILE_FLAG_OVERLAPPED - pipeMode = osdefs.PIPE_TYPE_BYTE or osdefs.PIPE_READMODE_BYTE or - osdefs.PIPE_WAIT + PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED + pipeMode = PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT pipeHandle = createNamedPipe(pipeName, openMode, pipeMode, - osdefs.PIPE_UNLIMITED_INSTANCES, + PIPE_UNLIMITED_INSTANCES, DWORD(server.bufferSize), DWORD(server.bufferSize), DWORD(0), nil) free(pipeName) - if pipeHandle == osdefs.INVALID_HANDLE_VALUE: + if pipeHandle == INVALID_HANDLE_VALUE: raiseOsDefect(osLastError(), "acceptPipeLoop(): Unable to create " & "new pipe") server.sock = AsyncFD(pipeHandle) @@ -955,12 +969,12 @@ when defined(windows): cast[POVERLAPPED](addr server.aovl)) if res == 0: let errCode = osLastError() - if errCode == osdefs.ERROR_OPERATION_ABORTED: + if errCode == ERROR_OPERATION_ABORTED: server.apending = false break - elif errCode == osdefs.ERROR_IO_PENDING: + elif errCode == ERROR_IO_PENDING: discard - elif errCode == osdefs.ERROR_PIPE_CONNECTED: + elif errCode == ERROR_PIPE_CONNECTED: discard else: raiseOsDefect(errCode, "acceptPipeLoop(): Unable to establish " & @@ -983,9 +997,10 @@ when defined(windows): ## Continuation server.apending = false if server.status notin {ServerStatus.Stopped, ServerStatus.Closed}: - if ovl.data.errCode == OSErrorCode(-1): - if setsockopt(SocketHandle(server.asock), cint(osdefs.SOL_SOCKET), - cint(osdefs.SO_UPDATE_ACCEPT_CONTEXT), + case ovl.data.errCode + of OSErrorCode(-1): + if setsockopt(SocketHandle(server.asock), cint(SOL_SOCKET), + cint(SO_UPDATE_ACCEPT_CONTEXT), addr server.sock, SockLen(sizeof(SocketHandle))) != 0'i32: let errCode = OSErrorCode(wsaGetLastError()) @@ -1006,7 +1021,7 @@ when defined(windows): trackStream(ntransp) asyncSpawn server.function(server, ntransp) - elif int32(ovl.data.errCode) == osdefs.ERROR_OPERATION_ABORTED: + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt or close. server.asock.closeSocket() if server.status in {ServerStatus.Closed, ServerStatus.Stopped}: @@ -1049,12 +1064,12 @@ when defined(windows): dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, addr dwBytesReceived, cast[POVERLAPPED](addr server.aovl)) - if res == osdefs.FALSE: + if res == FALSE: let errCode = osLastError() - if errCode == osdefs.ERROR_OPERATION_ABORTED: + if errCode == ERROR_OPERATION_ABORTED: server.apending = false break - elif errCode == osdefs.ERROR_IO_PENDING: + elif errCode == ERROR_IO_PENDING: discard else: raiseOsDefect(errCode, "acceptLoop(): Unable to accept " & @@ -1121,13 +1136,14 @@ when defined(windows): else: case ovl.data.errCode of OSErrorCode(-1): - if setsockopt(SocketHandle(server.asock), cint(osdefs.SOL_SOCKET), - cint(osdefs.SO_UPDATE_ACCEPT_CONTEXT), + if setsockopt(SocketHandle(server.asock), cint(SOL_SOCKET), + cint(SO_UPDATE_ACCEPT_CONTEXT), addr server.sock, SockLen(sizeof(SocketHandle))) != 0'i32: let err = osLastError() server.asock.closeSocket() - if err == osdefs.WSAENOTSOCK: + case err + of WSAENOTSOCK: # This can be happened when server get closed, but continuation # was already scheduled, so we failing it not with OS error. retFuture.fail(getServerUseClosedError()) @@ -1147,18 +1163,15 @@ when defined(windows): # Start tracking transport trackStream(ntransp) retFuture.complete(ntransp) - of OSErrorCode(osdefs.ERROR_OPERATION_ABORTED): + of ERROR_OPERATION_ABORTED: # CancelIO() interrupt or close. server.asock.closeSocket() retFuture.fail(getServerUseClosedError()) server.clean() - of OSErrorCode(osdefs.WSAENETDOWN), - OSErrorCode(osdefs.WSAENETRESET), - OSErrorCode(osdefs.WSAECONNABORTED), - OSErrorCode(osdefs.WSAECONNRESET), - OSErrorCode(osdefs.WSAETIMEDOUT): + of WSAENETDOWN, WSAENETRESET, WSAECONNABORTED, WSAECONNRESET, + WSAETIMEDOUT: server.asock.closeSocket() - retFuture.fail(getConnectionAbortedError(int(ovl.data.errCode))) + retFuture.fail(getConnectionAbortedError(ovl.data.errCode)) server.clean() else: server.asock.closeSocket() @@ -1189,7 +1202,8 @@ when defined(windows): server.sock.closeHandle() server.clean() else: - if ovl.data.errCode == OSErrorCode(-1): + case ovl.data.errCode + of OSErrorCode(-1): var ntransp: StreamTransport var flags = {WinServerPipe} if NoPipeFlash in server.flags: @@ -1210,8 +1224,7 @@ when defined(windows): trackStream(ntransp) retFuture.complete(ntransp) - elif int32(ovl.data.errCode) in {osdefs.ERROR_OPERATION_ABORTED, - osdefs.ERROR_PIPE_NOT_CONNECTED}: + of ERROR_OPERATION_ABORTED, ERROR_PIPE_NOT_CONNECTED: # CancelIO() interrupt or close call. retFuture.fail(getServerUseClosedError()) server.clean() @@ -1236,10 +1249,9 @@ when defined(windows): Protocol.IPPROTO_TCP) if server.asock == asyncInvalidSocket: let err = osLastError() - case int(err) - of osdefs.ERROR_TOO_MANY_OPEN_FILES, - osdefs.WSAENOBUFS, osdefs.WSAEMFILE: - retFuture.fail(getTransportTooManyError(int(err))) + case err + of ERROR_TOO_MANY_OPEN_FILES, WSAENOBUFS, WSAEMFILE: + retFuture.fail(getTransportTooManyError(err)) else: retFuture.fail(getTransportOsError(err)) return retFuture @@ -1258,19 +1270,19 @@ when defined(windows): dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, addr dwBytesReceived, cast[POVERLAPPED](addr server.aovl)) - if res == osdefs.FALSE: + if res == FALSE: let err = osLastError() - case int(err) - of osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: server.apending = false retFuture.fail(getServerUseClosedError()) return retFuture - of osdefs.ERROR_IO_PENDING: + of ERROR_IO_PENDING: discard - of osdefs.WSAECONNRESET, osdefs.WSAECONNABORTED, osdefs.WSAENETDOWN, - osdefs.WSAENETRESET, osdefs.WSAETIMEDOUT: + of WSAECONNRESET, WSAECONNABORTED, WSAENETDOWN, + WSAENETRESET, WSAETIMEDOUT: server.apending = false - retFuture.fail(getConnectionAbortedError(int(err))) + retFuture.fail(getConnectionAbortedError(err)) return retFuture else: server.apending = false @@ -1284,7 +1296,8 @@ when defined(windows): server.apending = true if server.sock == asyncInvalidPipe: let err = server.errorCode - if int32(err) == osdefs.ERROR_TOO_MANY_OPEN_FILES: + case err + of ERROR_TOO_MANY_OPEN_FILES: retFuture.fail(getTransportTooManyError()) else: retFuture.fail(getTransportOsError(err)) @@ -1297,12 +1310,12 @@ when defined(windows): cast[POVERLAPPED](addr server.aovl)) if res == 0: let err = osLastError() - if int32(err) == osdefs.ERROR_OPERATION_ABORTED: + case err + of ERROR_OPERATION_ABORTED: server.apending = false retFuture.fail(getServerUseClosedError()) return retFuture - elif int32(err) in {osdefs.ERROR_IO_PENDING, - osdefs.ERROR_PIPE_CONNECTED}: + of ERROR_IO_PENDING, ERROR_PIPE_CONNECTED: discard else: server.apending = false @@ -1317,7 +1330,7 @@ else: import ../sendfile proc isConnResetError(err: OSErrorCode): bool {.inline.} = - (err == OSErrorCode(ECONNRESET)) or (err == OSErrorCode(EPIPE)) + (err == oserrno.ECONNRESET) or (err == oserrno.EPIPE) proc writeStreamLoop(udata: pointer) = if isNil(udata): @@ -1345,33 +1358,32 @@ else: while len(transp.queue) > 0: template handleError() = let err = osLastError() - - if cint(err) == EINTR: + case err + of oserrno.EINTR: # Signal happened while writing - try again with all data transp.queue.addFirst(vector) continue - - if cint(err) in [EWOULDBLOCK, EAGAIN]: + of oserrno.EWOULDBLOCK: # Socket buffer is full - wait until next write notification - in # particular, ensure removeWriter is not called transp.queue.addFirst(vector) return - - # The errors below will clear the write queue, meaning we'll exit the - # loop - if isConnResetError(err): - # Soft error happens which indicates that remote peer got - # disconnected, complete all pending writes in queue with 0. - transp.state.incl({WriteEof}) - if not(vector.writer.finished()): - vector.writer.complete(0) - completePendingWriteQueue(transp.queue, 0) else: - transp.state.incl({WriteError}) - let error = getTransportOsError(err) - if not(vector.writer.finished()): - vector.writer.fail(error) - failPendingWriteQueue(transp.queue, error) + # The errors below will clear the write queue, meaning we'll exit the + # loop + if isConnResetError(err): + # Soft error happens which indicates that remote peer got + # disconnected, complete all pending writes in queue with 0. + transp.state.incl({WriteEof}) + if not(vector.writer.finished()): + vector.writer.complete(0) + completePendingWriteQueue(transp.queue, 0) + else: + transp.state.incl({WriteError}) + let error = getTransportOsError(err) + if not(vector.writer.finished()): + vector.writer.fail(error) + failPendingWriteQueue(transp.queue, error) var vector = transp.queue.popFirst() case vector.kind @@ -1443,7 +1455,8 @@ else: len(transp.buffer) - transp.offset, cint(0))) if res < 0: let err = osLastError() - if int(err) == ECONNRESET: + case err + of oserrno.ECONNRESET: transp.state.incl({ReadEof, ReadPaused}) let rres = removeReader2(transp.fd) if rres.isErr(): @@ -1553,7 +1566,8 @@ else: proto) if sock == asyncInvalidSocket: let err = osLastError() - if int(err) == EMFILE: + case err + of oserrno.EMFILE: retFuture.fail(getTransportTooManyError()) else: retFuture.fail(getTransportOsError(err)) @@ -1641,7 +1655,8 @@ else: # and the connection shall be established asynchronously. # # http://www.madore.org/~david/computers/connect-intr.html - if (errorCode == EINPROGRESS) or (errorCode == EINTR): + case errorCode + of oserrno.EINPROGRESS, oserrno.EINTR: let res = addWriter2(sock, continuation) if res.isErr(): discard unregisterAndCloseFd(sock) @@ -1692,7 +1707,7 @@ else: discard closeFd(cint(sock)) else: let errorCode = sres.error() - if errorCode != EAGAIN: + if errorCode != oserrno.EAGAIN: # This EAGAIN error appears only when server get closed, while # acceptLoop() reader callback is already scheduled. raiseOsDefect(errorCode, "acceptLoop(): Unable to accept connection") @@ -1745,14 +1760,15 @@ else: addr slen, flags) if sres.isErr(): let errorCode = sres.error() - if errorCode == EAGAIN: + case errorCode + of oserrno.EAGAIN: # This error appears only when server get closed, while accept() # continuation is already scheduled. retFuture.fail(getServerUseClosedError()) - elif cint(errorCode) in {EMFILE, ENFILE, ENOBUFS, ENOMEM}: - retFuture.fail(getTransportTooManyError(cint(errorCode))) - elif cint(errorCode) in {ECONNABORTED, EPERM, ETIMEDOUT}: - retFuture.fail(getConnectionAbortedError(cint(errorCode))) + of oserrno.EMFILE, oserrno.ENFILE, oserrno.ENOBUFS, oserrno.ENOMEM: + retFuture.fail(getTransportTooManyError(errorCode)) + of oserrno.ECONNABORTED, oserrno.EPERM, oserrno.ETIMEDOUT: + retFuture.fail(getConnectionAbortedError(errorCode)) else: retFuture.fail(getTransportOsError(errorCode)) # Error is already happened so we ignore removeReader2() errors. @@ -1933,15 +1949,13 @@ proc createStreamServer*(host: TransportAddress, serverSocket = sock # SO_REUSEADDR is not useful for Unix domain sockets. if ServerFlags.ReuseAddr in flags: - if not(setSockOpt(serverSocket, osdefs.SOL_SOCKET, - osdefs.SO_REUSEADDR, 1)): + if not(setSockOpt(serverSocket, SOL_SOCKET, SO_REUSEADDR, 1)): let err = osLastError() if sock == asyncInvalidSocket: discard closeFd(SocketHandle(serverSocket)) raiseTransportOsError(err) if ServerFlags.ReusePort in flags: - if not(setSockOpt(serverSocket, osdefs.SOL_SOCKET, - osdefs.SO_REUSEPORT, 1)): + if not(setSockOpt(serverSocket, SOL_SOCKET, SO_REUSEPORT, 1)): let err = osLastError() if sock == asyncInvalidSocket: discard closeFd(SocketHandle(serverSocket)) @@ -1955,8 +1969,8 @@ proc createStreamServer*(host: TransportAddress, discard closeFd(SocketHandle(serverSocket)) raiseTransportOsError(err) host.toSAddr(saddr, slen) - if osdefs.bindSocket(SocketHandle(serverSocket), - cast[ptr SockAddr](addr saddr), slen) != 0: + if bindSocket(SocketHandle(serverSocket), + cast[ptr SockAddr](addr saddr), slen) != 0: let err = osLastError() if sock == asyncInvalidSocket: discard closeFd(SocketHandle(serverSocket)) @@ -2165,21 +2179,21 @@ template fastWrite(transp: auto, pbytes: var ptr byte, rbytes: var int, # Not all bytes written - keep going else: let err = osLastError() - if cint(err) in [EAGAIN, EWOULDBLOCK]: + case err + of oserrno.EWOULDBLOCK: break # No bytes written, add to queue - - if cint(err) == EINTR: + of oserrno.EINTR: continue - - if isConnResetError(err): - transp.state.incl({WriteEof}) - retFuture.complete(0) - return retFuture else: - transp.state.incl({WriteError}) - let error = getTransportOsError(err) - retFuture.fail(error) - return retFuture + if isConnResetError(err): + transp.state.incl({WriteEof}) + retFuture.complete(0) + return retFuture + else: + transp.state.incl({WriteError}) + let error = getTransportOsError(err) + retFuture.fail(error) + return retFuture proc write*(transp: StreamTransport, pbytes: pointer, nbytes: int): Future[int] = @@ -2340,7 +2354,7 @@ template readLoop(name, body: untyped): untyped = raiseOsDefect(errorCode, "readLoop(): Unable to resume reading") else: transp.reader.complete() - if errorCode == ESRCH: + if errorCode == oserrno.ESRCH: # ESRCH 3 "No such process" # This error could be happened on pipes only, when process which # owns and communicates through this pipe (stdin, stdout, stderr) is diff --git a/tests/teststream.nim b/tests/teststream.nim index c76ccf6..ea1de43 100644 --- a/tests/teststream.nim +++ b/tests/teststream.nim @@ -7,7 +7,7 @@ # MIT license (LICENSE-MIT) import std/[strutils, os] import unittest2 -import ".."/chronos, ".."/chronos/osdefs +import ".."/chronos, ".."/chronos/[osdefs, oserrno] {.used.} @@ -639,12 +639,11 @@ suite "Stream Transport test suite": var transp = await connect(address) doAssert(isNil(transp)) except TransportOsError as e: - let ecode = int(e.code) when defined(windows): - result = (ecode == ERROR_FILE_NOT_FOUND) or - (ecode == ERROR_CONNECTION_REFUSED) + return (e.code == ERROR_FILE_NOT_FOUND) or + (e.code == ERROR_CONNECTION_REFUSED) else: - result = (ecode == ECONNREFUSED) or (ecode == ENOENT) + return (e.code == oserrno.ECONNREFUSED) or (e.code == oserrno.ENOENT) proc serveClient16(server: StreamServer, transp: StreamTransport) {.async.} = var res = await transp.write(BigMessagePattern)