Merge branch 'bigbreak' of https://github.com/Araq/Nimrod into bigbreak

This commit is contained in:
Araq 2014-08-31 01:43:19 +02:00
commit d3a7fa20ae
3 changed files with 59 additions and 59 deletions

View file

@ -720,42 +720,42 @@ else:
proc update(sock: TAsyncFD, events: set[TEvent]) = proc update(sock: TAsyncFD, events: set[TEvent]) =
let p = getGlobalDispatcher() let p = getGlobalDispatcher()
assert sock.TSocketHandle in p.selector assert sock.SocketHandle in p.selector
discard p.selector.update(sock.TSocketHandle, events) discard p.selector.update(sock.SocketHandle, events)
proc register(sock: TAsyncFD) = proc register(sock: TAsyncFD) =
let p = getGlobalDispatcher() let p = getGlobalDispatcher()
var data = PData(sock: sock, readCBs: @[], writeCBs: @[]) var data = PData(sock: sock, readCBs: @[], writeCBs: @[])
p.selector.register(sock.TSocketHandle, {}, data.PObject) p.selector.register(sock.SocketHandle, {}, data.PObject)
proc newAsyncRawSocket*(domain: TDomain = AF_INET, proc newAsyncRawSocket*(domain: TDomain = AF_INET,
typ: TType = SOCK_STREAM, typ: TType = SOCK_STREAM,
protocol: TProtocol = IPPROTO_TCP): TAsyncFD = protocol: TProtocol = IPPROTO_TCP): TAsyncFD =
result = newRawSocket(domain, typ, protocol).TAsyncFD result = newRawSocket(domain, typ, protocol).TAsyncFD
result.TSocketHandle.setBlocking(false) result.SocketHandle.setBlocking(false)
register(result) register(result)
proc closeSocket*(sock: TAsyncFD) = proc closeSocket*(sock: TAsyncFD) =
let disp = getGlobalDispatcher() let disp = getGlobalDispatcher()
sock.TSocketHandle.close() sock.SocketHandle.close()
disp.selector.unregister(sock.TSocketHandle) disp.selector.unregister(sock.SocketHandle)
proc unregister*(fd: TAsyncFD) = proc unregister*(fd: TAsyncFD) =
getGlobalDispatcher().selector.unregister(fd.TSocketHandle) getGlobalDispatcher().selector.unregister(fd.SocketHandle)
proc addRead(sock: TAsyncFD, cb: TCallback) = proc addRead(sock: TAsyncFD, cb: TCallback) =
let p = getGlobalDispatcher() let p = getGlobalDispatcher()
if sock.TSocketHandle notin p.selector: if sock.SocketHandle notin p.selector:
raise newException(EInvalidValue, "File descriptor not registered.") raise newException(EInvalidValue, "File descriptor not registered.")
p.selector[sock.TSocketHandle].data.PData.readCBs.add(cb) p.selector[sock.SocketHandle].data.PData.readCBs.add(cb)
update(sock, p.selector[sock.TSocketHandle].events + {EvRead}) update(sock, p.selector[sock.SocketHandle].events + {EvRead})
proc addWrite(sock: TAsyncFD, cb: TCallback) = proc addWrite(sock: TAsyncFD, cb: TCallback) =
let p = getGlobalDispatcher() let p = getGlobalDispatcher()
if sock.TSocketHandle notin p.selector: if sock.SocketHandle notin p.selector:
raise newException(EInvalidValue, "File descriptor not registered.") raise newException(EInvalidValue, "File descriptor not registered.")
p.selector[sock.TSocketHandle].data.PData.writeCBs.add(cb) p.selector[sock.SocketHandle].data.PData.writeCBs.add(cb)
update(sock, p.selector[sock.TSocketHandle].events + {EvWrite}) update(sock, p.selector[sock.SocketHandle].events + {EvWrite})
proc poll*(timeout = 500) = proc poll*(timeout = 500) =
let p = getGlobalDispatcher() let p = getGlobalDispatcher()
@ -808,7 +808,7 @@ else:
var lastError: TOSErrorCode var lastError: TOSErrorCode
var it = aiList var it = aiList
while it != nil: while it != nil:
var ret = connect(socket.TSocketHandle, it.ai_addr, it.ai_addrlen.TSocklen) var ret = connect(socket.SocketHandle, it.ai_addr, it.ai_addrlen.Socklen)
if ret == 0: if ret == 0:
# Request to connect completed immediately. # Request to connect completed immediately.
success = true success = true
@ -837,7 +837,7 @@ else:
proc cb(sock: TAsyncFD): bool = proc cb(sock: TAsyncFD): bool =
result = true result = true
let res = recv(sock.TSocketHandle, addr readBuffer[0], size.cint, let res = recv(sock.SocketHandle, addr readBuffer[0], size.cint,
flags.toOSFlags()) flags.toOSFlags())
#echo("recv cb res: ", res) #echo("recv cb res: ", res)
if res < 0: if res < 0:
@ -870,7 +870,7 @@ else:
result = true result = true
let netSize = data.len-written let netSize = data.len-written
var d = data.cstring var d = data.cstring
let res = send(sock.TSocketHandle, addr d[written], netSize.cint, let res = send(sock.SocketHandle, addr d[written], netSize.cint,
MSG_NOSIGNAL) MSG_NOSIGNAL)
if res < 0: if res < 0:
let lastError = osLastError() let lastError = osLastError()
@ -898,10 +898,10 @@ else:
client: TAsyncFD]]("acceptAddr") client: TAsyncFD]]("acceptAddr")
proc cb(sock: TAsyncFD): bool = proc cb(sock: TAsyncFD): bool =
result = true result = true
var sockAddress: Tsockaddr_in var sockAddress: SockAddr_in
var addrLen = sizeof(sockAddress).TSocklen var addrLen = sizeof(sockAddress).Socklen
var client = accept(sock.TSocketHandle, var client = accept(sock.SocketHandle,
cast[ptr TSockAddr](addr(sockAddress)), addr(addrLen)) cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
if client == osInvalidSocket: if client == osInvalidSocket:
let lastError = osLastError() let lastError = osLastError()
assert lastError.int32 notin {EWOULDBLOCK, EAGAIN} assert lastError.int32 notin {EWOULDBLOCK, EAGAIN}

View file

@ -125,16 +125,16 @@ when defined(ssl):
ErrLoadBioStrings() ErrLoadBioStrings()
OpenSSL_add_all_algorithms() OpenSSL_add_all_algorithms()
proc SSLError(s = "") = proc raiseSSLError(s = "") =
if s != "": if s != "":
raise newException(ESSL, s) raise newException(SSLError, s)
let err = ErrPeekLastError() let err = ErrPeekLastError()
if err == 0: if err == 0:
raise newException(ESSL, "No error reported.") raise newException(SSLError, "No error reported.")
if err == -1: if err == -1:
OSError(OSLastError()) raiseOSError(osLastError())
var errStr = ErrErrorString(err, nil) var errStr = ErrErrorString(err, nil)
raise newException(ESSL, $errStr) raise newException(SSLError, $errStr)
# http://simplestcodings.blogspot.co.uk/2010/08/secure-server-client-using-openssl-in-c.html # http://simplestcodings.blogspot.co.uk/2010/08/secure-server-client-using-openssl-in-c.html
proc loadCertificates(ctx: PSSL_CTX, certFile, keyFile: string) = proc loadCertificates(ctx: PSSL_CTX, certFile, keyFile: string) =
@ -146,23 +146,23 @@ when defined(ssl):
if certFile != "": if certFile != "":
var ret = SSLCTXUseCertificateChainFile(ctx, certFile) var ret = SSLCTXUseCertificateChainFile(ctx, certFile)
if ret != 1: if ret != 1:
SSLError() raiseSSLError()
# TODO: Password? www.rtfm.com/openssl-examples/part1.pdf # TODO: Password? www.rtfm.com/openssl-examples/part1.pdf
if keyFile != "": if keyFile != "":
if SSL_CTX_use_PrivateKey_file(ctx, keyFile, if SSL_CTX_use_PrivateKey_file(ctx, keyFile,
SSL_FILETYPE_PEM) != 1: SSL_FILETYPE_PEM) != 1:
SSLError() raiseSSLError()
if SSL_CTX_check_private_key(ctx) != 1: if SSL_CTX_check_private_key(ctx) != 1:
SSLError("Verification of private key file failed.") raiseSSLError("Verification of private key file failed.")
proc newContext*(protVersion = ProtSSLv23, verifyMode = CVerifyPeer, proc newContext*(protVersion = protSSLv23, verifyMode = CVerifyPeer,
certFile = "", keyFile = ""): PSSLContext = certFile = "", keyFile = ""): PSSLContext =
## Creates an SSL context. ## Creates an SSL context.
## ##
## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1 are ## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1 are
## are available with the addition of ``ProtSSLv23`` which allows for ## are available with the addition of ``protSSLv23`` which allows for
## compatibility with all of them. ## compatibility with all of them.
## ##
## There are currently only two options for verify mode; ## There are currently only two options for verify mode;
@ -189,14 +189,14 @@ when defined(ssl):
newCTX = SSL_CTX_new(TLSv1_method()) newCTX = SSL_CTX_new(TLSv1_method())
if newCTX.SSLCTXSetCipherList("ALL") != 1: if newCTX.SSLCTXSetCipherList("ALL") != 1:
SSLError() raiseSSLError()
case verifyMode case verifyMode
of CVerifyPeer: of CVerifyPeer:
newCTX.SSLCTXSetVerify(SSLVerifyPeer, nil) newCTX.SSLCTXSetVerify(SSLVerifyPeer, nil)
of CVerifyNone: of CVerifyNone:
newCTX.SSLCTXSetVerify(SSLVerifyNone, nil) newCTX.SSLCTXSetVerify(SSLVerifyNone, nil)
if newCTX == nil: if newCTX == nil:
SSLError() raiseSSLError()
discard newCTX.SSLCTXSetMode(SSL_MODE_AUTO_RETRY) discard newCTX.SSLCTXSetMode(SSL_MODE_AUTO_RETRY)
newCTX.loadCertificates(certFile, keyFile) newCTX.loadCertificates(certFile, keyFile)
@ -215,10 +215,10 @@ when defined(ssl):
socket.sslNoHandshake = false socket.sslNoHandshake = false
socket.sslHasPeekChar = false socket.sslHasPeekChar = false
if socket.sslHandle == nil: if socket.sslHandle == nil:
SSLError() raiseSSLError()
if SSLSetFd(socket.sslHandle, socket.fd) != 1: if SSLSetFd(socket.sslHandle, socket.fd) != 1:
SSLError() raiseSSLError()
proc socketError*(socket: Socket, err: int = -1, async = false, proc socketError*(socket: Socket, err: int = -1, async = false,
lastError = (-1).OSErrorCode) = lastError = (-1).OSErrorCode) =
@ -235,20 +235,20 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
var ret = SSLGetError(socket.sslHandle, err.cint) var ret = SSLGetError(socket.sslHandle, err.cint)
case ret case ret
of SSL_ERROR_ZERO_RETURN: of SSL_ERROR_ZERO_RETURN:
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") raiseSSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
if async: if async:
return return
else: SSLError("Not enough data on socket.") else: raiseSSLError("Not enough data on socket.")
of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ: of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_READ:
if async: if async:
return return
else: SSLError("Not enough data on socket.") else: raiseSSLError("Not enough data on socket.")
of SSL_ERROR_WANT_X509_LOOKUP: of SSL_ERROR_WANT_X509_LOOKUP:
SSLError("Function for x509 lookup has been called.") raiseSSLError("Function for x509 lookup has been called.")
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
SSLError() raiseSSLError()
else: SSLError("Unknown Error") else: raiseSSLError("Unknown Error")
if err == -1 and not (when defined(ssl): socket.isSSL else: false): if err == -1 and not (when defined(ssl): socket.isSSL else: false):
let lastE = if lastError.int == -1: osLastError() else: lastError let lastE = if lastError.int == -1: osLastError() else: lastError
@ -260,7 +260,7 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
else: else:
if lastE.int32 == EAGAIN or lastE.int32 == EWOULDBLOCK: if lastE.int32 == EAGAIN or lastE.int32 == EWOULDBLOCK:
return return
else: osError(lastE) else: raiseOSError(lastE)
else: raiseOSError(lastE) else: raiseOSError(lastE)
proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} = proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
@ -371,17 +371,17 @@ when false: #defined(ssl):
if err != SSL_ERROR_WANT_ACCEPT: if err != SSL_ERROR_WANT_ACCEPT:
case err case err
of SSL_ERROR_ZERO_RETURN: of SSL_ERROR_ZERO_RETURN:
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") raiseSSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE,
SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
client.sslNoHandshake = true client.sslNoHandshake = true
return AcceptNoHandshake return AcceptNoHandshake
of SSL_ERROR_WANT_X509_LOOKUP: of SSL_ERROR_WANT_X509_LOOKUP:
SSLError("Function for x509 lookup has been called.") raiseSSLError("Function for x509 lookup has been called.")
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
SSLError() raiseSSLError()
else: else:
SSLError("Unknown error") raiseSSLError("Unknown error")
client.sslNoHandshake = false client.sslNoHandshake = false
if client.isSSL and client.sslNoHandshake: if client.isSSL and client.sslNoHandshake:
@ -485,19 +485,19 @@ when defined(ssl):
var errret = SSLGetError(socket.sslHandle, ret) var errret = SSLGetError(socket.sslHandle, ret)
case errret case errret
of SSL_ERROR_ZERO_RETURN: of SSL_ERROR_ZERO_RETURN:
SSLError("TLS/SSL connection failed to initiate, socket closed prematurely.") raiseSSLError("TLS/SSL connection failed to initiate, socket closed prematurely.")
of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT, of SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT,
SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE: SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE:
return false return false
of SSL_ERROR_WANT_X509_LOOKUP: of SSL_ERROR_WANT_X509_LOOKUP:
SSLError("Function for x509 lookup has been called.") raiseSSLError("Function for x509 lookup has been called.")
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
SSLError() raiseSSLError()
else: else:
SSLError("Unknown Error") raiseSSLError("Unknown Error")
socket.sslNoHandshake = false socket.sslNoHandshake = false
else: else:
SSLError("Socket is not an SSL socket.") raiseSSLError("Socket is not an SSL socket.")
proc gotHandshake*(socket: PSocket): bool = proc gotHandshake*(socket: PSocket): bool =
## Determines whether a handshake has occurred between a client (``socket``) ## Determines whether a handshake has occurred between a client (``socket``)
@ -507,7 +507,7 @@ when defined(ssl):
if socket.isSSL: if socket.isSSL:
return not socket.sslNoHandshake return not socket.sslNoHandshake
else: else:
SSLError("Socket is not an SSL socket.") raiseSSLError("Socket is not an SSL socket.")
proc hasDataBuffered*(s: Socket): bool = proc hasDataBuffered*(s: Socket): bool =
## Determines whether a socket has data buffered. ## Determines whether a socket has data buffered.

View file

@ -246,7 +246,7 @@ proc BIO_get_ssl*(bio: PBIO, ssl: ptr PSSL): int =
proc BIO_set_conn_hostname*(bio: PBIO, name: cstring): int = proc BIO_set_conn_hostname*(bio: PBIO, name: cstring): int =
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, name) return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, name)
proc BIO_do_handshake*(bio: PBIO): int = proc BIO_do_handshake*(bio: PBIO): int =
return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NIL) return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, nil)
proc BIO_do_connect*(bio: PBIO): int = proc BIO_do_connect*(bio: PBIO): int =
return BIO_do_handshake(bio) return BIO_do_handshake(bio)
@ -448,11 +448,11 @@ type
{.pragma: ic, importc: "$1".} {.pragma: ic, importc: "$1".}
{.push callconv:cdecl, dynlib:DLLUtilName.} {.push callconv:cdecl, dynlib:DLLUtilName.}
proc MD5_Init*(c: var MD5_CTX): cint{.ic.} proc md5_Init*(c: var MD5_CTX): cint{.ic.}
proc MD5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.ic.} proc md5_Update*(c: var MD5_CTX; data: pointer; len: csize): cint{.ic.}
proc MD5_Final*(md: cstring; c: var MD5_CTX): cint{.ic.} proc md5_Final*(md: cstring; c: var MD5_CTX): cint{.ic.}
proc MD5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.ic.} proc md5*(d: ptr cuchar; n: csize; md: ptr cuchar): ptr cuchar{.ic.}
proc MD5_Transform*(c: var MD5_CTX; b: ptr cuchar){.ic.} proc md5_Transform*(c: var MD5_CTX; b: ptr cuchar){.ic.}
{.pop.} {.pop.}
from strutils import toHex,toLower from strutils import toHex,toLower
@ -463,7 +463,7 @@ proc hexStr (buf:cstring): string =
for i in 0 .. <16: for i in 0 .. <16:
result.add toHex(buf[i].ord, 2).toLower result.add toHex(buf[i].ord, 2).toLower
proc MD5_File* (file: string): string {.raises:[EIO,Ebase].} = proc md5_File* (file: string): string {.raises:[EIO,Ebase].} =
## Generate MD5 hash for a file. Result is a 32 character ## Generate MD5 hash for a file. Result is a 32 character
# hex string with lowercase characters (like the output # hex string with lowercase characters (like the output
# of `md5sum` # of `md5sum`
@ -483,7 +483,7 @@ proc MD5_File* (file: string): string {.raises:[EIO,Ebase].} =
result = hexStr(buf) result = hexStr(buf)
proc MD5_Str* (str:string): string {.raises:[EIO].} = proc md5_Str* (str:string): string {.raises:[EIO].} =
##Generate MD5 hash for a string. Result is a 32 character ##Generate MD5 hash for a string. Result is a 32 character
#hex string with lowercase characters #hex string with lowercase characters
var var