Deprecated OSError, and modified it to require an explicit OS error code.

The deprecated functions include the OSError and OSErrorMsg, the name did not change however the signature of the new functions did. They now require a TOSErrorCode value be passed to them. This value can be retrieved using OSLastError. The reason this was done is because on Windows any win api call can reset the last error code to 0, this change allows the user to immediately grab the error code and worry about the string representation later if needs be.
This commit is contained in:
Dominik Picheta 2013-06-25 20:10:28 +01:00
commit bacb20a379
5 changed files with 196 additions and 126 deletions

View file

@ -231,7 +231,7 @@ when defined(ssl):
if err == 0:
raise newException(ESSL, "No error reported.")
if err == -1:
OSError()
OSError(OSLastError())
var errStr = ErrErrorString(err, nil)
raise newException(ESSL, $errStr)
@ -347,24 +347,23 @@ proc SocketError*(socket: TSocket, err: int = -1, async = false) =
else: SSLError("Unknown Error")
if err == -1 and not (when defined(ssl): socket.isSSL else: false):
let lastError = OSLastError()
if async:
when defined(windows):
# TODO: Test on Windows
var err = WSAGetLastError()
if err == WSAEWOULDBLOCK:
if lastError.int32 == WSAEWOULDBLOCK:
return
else: OSError()
else: OSError(lastError)
else:
if errno == EAGAIN or errno == EWOULDBLOCK:
if lastError.int32 == EAGAIN or lastError.int32 == EWOULDBLOCK:
return
else: OSError()
else: OSError()
else: OSError(lastError)
else: OSError(lastError)
proc listen*(socket: TSocket, backlog = SOMAXCONN) {.tags: [FReadIO].} =
## Marks ``socket`` as accepting connections.
## ``Backlog`` specifies the maximum length of the
## queue of pending connections.
if listen(socket.fd, cint(backlog)) < 0'i32: OSError()
if listen(socket.fd, cint(backlog)) < 0'i32: OSError(OSLastError())
proc invalidIp4(s: string) {.noreturn, noinline.} =
raise newException(EInvalidValue, "invalid ip4 address: " & s)
@ -403,7 +402,7 @@ template gaiNim(a, p, h, list: expr): stmt =
var gaiResult = getAddrInfo(a, $p, addr(h), list)
if gaiResult != 0'i32:
when defined(windows):
OSError()
OSError(OSLastError())
else:
OSError($gai_strerror(gaiResult))
@ -423,7 +422,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {.
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)),
sizeof(name).TSockLen) < 0'i32:
OSError()
OSError(OSLastError())
else:
var hints: TAddrInfo
var aiList: ptr TAddrInfo = nil
@ -432,21 +431,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {.
hints.ai_protocol = toInt(IPPROTO_TCP)
gaiNim(address, port, hints, aiList)
if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrLen.TSockLen) < 0'i32:
OSError()
when false:
proc bindAddr*(socket: TSocket, port = TPort(0)) =
## binds a port number to a socket.
var name: Tsockaddr_in
when defined(Windows):
name.sin_family = int16(ord(AF_INET))
else:
name.sin_family = posix.AF_INET
name.sin_port = sockets.htons(int16(port))
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)),
sizeof(name).TSockLen) < 0'i32:
OSError()
OSError(OSLastError())
proc getSockName*(socket: TSocket): TPort =
## returns the socket's associated port number.
@ -460,7 +445,7 @@ proc getSockName*(socket: TSocket): TPort =
var namelen = sizeof(name).TSockLen
if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)),
addr(namelen)) == -1'i32:
OSError()
OSError(OSLastError())
result = TPort(sockets.ntohs(name.sin_port))
template acceptAddrPlain(noClientRet, successRet: expr,
@ -472,26 +457,25 @@ template acceptAddrPlain(noClientRet, successRet: expr,
addr(addrLen))
if sock < 0:
# TODO: Test on Windows.
let err = OSLastError()
when defined(windows):
var err = WSAGetLastError()
if err == WSAEINPROGRESS:
if err.int32 == WSAEINPROGRESS:
client = InvalidSocket
address = ""
when noClientRet.int == -1:
return
else:
return noClientRet
else: OSError()
else: OSError(err)
else:
if errno == EAGAIN or errno == EWOULDBLOCK:
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
client = InvalidSocket
address = ""
when noClientRet.int == -1:
return
else:
return noClientRet
else: OSError()
else: OSError(err)
else:
client.fd = sock
client.isBuffered = server.isBuffered
@ -644,7 +628,7 @@ proc getServByName*(name, proto: string): TServent {.tags: [FReadIO].} =
var s = winlean.getservbyname(name, proto)
else:
var s = posix.getservbyname(name, proto)
if s == nil: OSError()
if s == nil: OSError(OSLastError())
result.name = $s.s_name
result.aliases = cstringArrayToSeq(s.s_aliases)
result.port = TPort(s.s_port)
@ -656,7 +640,7 @@ proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} =
var s = winlean.getservbyport(ze(int16(port)).cint, proto)
else:
var s = posix.getservbyport(ze(int16(port)).cint, proto)
if s == nil: OSError()
if s == nil: OSError(OSLastError())
result.name = $s.s_name
result.aliases = cstringArrayToSeq(s.s_aliases)
result.port = TPort(s.s_port)
@ -670,7 +654,7 @@ proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} =
when defined(windows):
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
cint(sockets.AF_INET))
if s == nil: OSError()
if s == nil: OSError(OSLastError())
else:
var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSockLen,
cint(posix.AF_INET))
@ -687,7 +671,7 @@ proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} =
elif s.h_addrtype == posix.AF_INET6:
result.addrType = AF_INET6
else:
OSError("unknown h_addrtype")
raise newException(EOS, "unknown h_addrtype")
result.addrList = cstringArrayToSeq(s.h_addr_list)
result.length = int(s.h_length)
@ -697,7 +681,7 @@ proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} =
var s = winlean.gethostbyname(name)
else:
var s = posix.gethostbyname(name)
if s == nil: OSError()
if s == nil: OSError(OSLastError())
result.name = $s.h_name
result.aliases = cstringArrayToSeq(s.h_aliases)
when defined(windows):
@ -708,7 +692,7 @@ proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} =
elif s.h_addrtype == posix.AF_INET6:
result.addrType = AF_INET6
else:
OSError("unknown h_addrtype")
raise newException(EOS, "unknown h_addrtype")
result.addrList = cstringArrayToSeq(s.h_addr_list)
result.length = int(s.h_length)
@ -719,7 +703,7 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int {.
var size = sizeof(res).TSockLen
if getsockopt(socket.fd, cint(level), cint(optname),
addr(res), addr(size)) < 0'i32:
OSError()
OSError(OSLastError())
result = int(res)
proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {.
@ -728,7 +712,7 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {.
var value = cint(optval)
if setsockopt(socket.fd, cint(level), cint(optname), addr(value),
sizeof(value).TSockLen) < 0'i32:
OSError()
OSError(OSLastError())
proc connect*(socket: TSocket, address: string, port = TPort(0),
af: TDomain = AF_INET) {.tags: [FReadIO].} =
@ -746,15 +730,17 @@ proc connect*(socket: TSocket, address: string, port = TPort(0),
gaiNim(address, port, hints, aiList)
# try all possibilities:
var success = false
var lastError: TOSErrorCode
var it = aiList
while it != nil:
if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen) == 0'i32:
success = true
break
else: lastError = OSLastError()
it = it.ai_next
freeaddrinfo(aiList)
if not success: OSError()
if not success: OSError(lastError)
when defined(ssl):
if socket.isSSL:
@ -807,6 +793,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
gaiNim(name, port, hints, aiList)
# try all possibilities:
var success = false
var lastError: TOSErrorCode
var it = aiList
while it != nil:
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen)
@ -814,22 +801,21 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
success = true
break
else:
# TODO: Test on Windows.
lastError = OSLastError()
when defined(windows):
var err = WSAGetLastError()
# Windows EINTR doesn't behave same as POSIX.
if err == WSAEWOULDBLOCK:
if lastError.int32 == WSAEWOULDBLOCK:
success = true
break
else:
if errno == EINTR or errno == EINPROGRESS:
if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
success = true
break
it = it.ai_next
freeaddrinfo(aiList)
if not success: OSError()
if not success: OSError(lastError)
when defined(ssl):
if socket.isSSL:
socket.sslNoHandshake = true
@ -1110,7 +1096,7 @@ proc waitFor(socket: TSocket, waited: var float, timeout, size: int,
var s = @[socket]
var startTime = epochTime()
let selRet = select(s, timeout - int(waited * 1000.0))
if selRet < 0: OSError()
if selRet < 0: OSError(OSLastError())
if selRet != 1:
raise newException(ETimeout, "Call to '" & funcName & "' timed out.")
waited += (epochTime() - startTime)
@ -1259,14 +1245,14 @@ proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {.
var c: char
discard waitFor(socket, waited, timeout, 1, "readLine")
var n = recv(socket, addr(c), 1)
if n < 0: OSError()
if n < 0: OSError(OSLastError())
elif n == 0: return
if c == '\r':
discard waitFor(socket, waited, timeout, 1, "readLine")
n = peekChar(socket, c)
if n > 0 and c == '\L':
discard recv(socket, addr(c), 1)
elif n <= 0: OSError()
elif n <= 0: OSError(OSLastError())
addNlIfEmpty()
return
elif c == '\L':
@ -1326,6 +1312,7 @@ proc readLineAsync*(socket: TSocket,
while true:
var c: char
var n = recv(socket, addr(c), 1)
#echo(n)
if n < 0:
if line.len == 0: errorOrNone else: return ReadPartialLine
elif n == 0:
@ -1352,7 +1339,7 @@ proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO], deprecated.} =
var pos = 0
while true:
var bytesRead = recv(socket, addr(string(result)[pos]), bufSize-1)
if bytesRead == -1: OSError()
if bytesRead == -1: OSError(OSLastError())
setLen(result.string, pos + bytesRead)
if bytesRead != bufSize-1: break
# increase capacity:
@ -1364,7 +1351,7 @@ proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO], deprecated.} =
while true:
var bytesRead = recv(socket, cstring(buf), bufSize-1)
# Error
if bytesRead == -1: OSError()
if bytesRead == -1: OSError(OSLastError())
buf[bytesRead] = '\0' # might not be necessary
setLen(buf, bytesRead)
@ -1421,16 +1408,15 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool {.
else: SSLError("Unknown Error")
if bytesRead == -1 and not (when defined(ssl): socket.isSSL else: false):
let err = OSLastError()
when defined(windows):
# TODO: Test on Windows
var err = WSAGetLastError()
if err == WSAEWOULDBLOCK:
if err.int32 == WSAEWOULDBLOCK:
return False
else: OSError()
else: OSError(err)
else:
if errno == EAGAIN or errno == EWOULDBLOCK:
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
return False
else: OSError()
else: OSError(err)
setLen(s.string, pos + bytesRead)
if bytesRead != bufSize-1: break
@ -1475,16 +1461,15 @@ proc recvFromAsync*(socket: TSocket, data: var String, length: int,
result = true
var callRes = recvFrom(socket, data, length, address, port, flags)
if callRes < 0:
let err = OSLastError()
when defined(windows):
# TODO: Test on Windows
var err = WSAGetLastError()
if err == WSAEWOULDBLOCK:
if err.int32 == WSAEWOULDBLOCK:
return False
else: OSError()
else: OSError(err)
else:
if errno == EAGAIN or errno == EWOULDBLOCK:
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
return False
else: OSError()
else: OSError(err)
proc skip*(socket: TSocket) {.tags: [FReadIO], deprecated.} =
## skips all the data that is pending for the socket
@ -1531,7 +1516,7 @@ proc send*(socket: TSocket, data: string) {.tags: [FWriteIO].} =
if socket.isSSL:
SSLError()
OSError()
OSError(OSLastError())
proc sendAsync*(socket: TSocket, data: string): int {.tags: [FWriteIO].} =
## sends data to a non-blocking socket.
@ -1561,16 +1546,15 @@ proc sendAsync*(socket: TSocket, data: string): int {.tags: [FWriteIO].} =
else:
return
if result == -1:
let err = OSLastError()
when defined(windows):
var err = WSAGetLastError()
# TODO: Test on windows.
if err == WSAEINPROGRESS:
if err.int32 == WSAEINPROGRESS:
return 0
else: OSError()
else: OSError(err)
else:
if errno == EAGAIN or errno == EWOULDBLOCK:
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
return 0
else: OSError()
else: OSError(err)
proc trySend*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} =
@ -1626,15 +1610,15 @@ proc setBlocking(s: TSocket, blocking: bool) =
when defined(Windows):
var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking
if ioctlsocket(TWinSocket(s.fd), FIONBIO, addr(mode)) == -1:
OSError()
OSError(OSLastError())
else: # BSD sockets
var x: int = fcntl(s.fd, F_GETFL, 0)
if x == -1:
OSError()
OSError(OSLastError())
else:
var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK
if fcntl(s.fd, F_SETFL, mode) == -1:
OSError()
OSError(OSLastError())
s.nonblocking = not blocking
proc connect*(socket: TSocket, address: string, port = TPort(0), timeout: int,
@ -1665,6 +1649,6 @@ proc getFD*(socket: TSocket): cint = return socket.fd
when defined(Windows):
var wsa: TWSADATA
if WSAStartup(0x0101'i16, wsa) != 0: OSError()
if WSAStartup(0x0101'i16, addr wsa) != 0: OSError(OSLastError())