Skip to content

Commit 95d25a9

Browse files
nitelynarimiran
authored andcommitted
revert #24896; asyncnet ssl overhaul (#25033)
revert #24896 Partially reverting #24896 in #25024 broke CI. So better revert it completely so the CI is green. I'll investigate the issue later. (cherry picked from commit 08642ff)
1 parent 137fb97 commit 95d25a9

File tree

2 files changed

+54
-123
lines changed

2 files changed

+54
-123
lines changed

lib/pure/asyncnet.nim

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ type
126126
when defineSsl:
127127
sslHandle: SslPtr
128128
sslContext: SslContext
129+
bioIn: BIO
130+
bioOut: BIO
129131
sslNoShutdown: bool
130132
domain: Domain
131133
sockType: SockType
@@ -208,7 +210,7 @@ when defineSsl:
208210
proc raiseSslHandleError =
209211
raiseSSLError("The SSL Handle is closed/unset")
210212

211-
proc getSslError(socket: AsyncSocket, flags: set[SocketFlag], err: cint): cint =
213+
proc getSslError(socket: AsyncSocket, err: cint): cint =
212214
assert socket.isSsl
213215
assert err < 0
214216
var ret = SSL_get_error(socket.sslHandle, err.cint)
@@ -221,49 +223,47 @@ when defineSsl:
221223
return ret
222224
of SSL_ERROR_WANT_X509_LOOKUP:
223225
raiseSSLError("Function for x509 lookup has been called.")
224-
of SSL_ERROR_SYSCALL:
225-
socket.sslNoShutdown = true
226-
let osErr = osLastError()
227-
if not flags.isDisconnectionError(osErr):
228-
var errStr = "IO error has occurred"
229-
let sslErr = ERR_peek_last_error()
230-
if sslErr == 0 and err == 0:
231-
errStr.add ' '
232-
errStr.add "because an EOF was observed that violates the protocol"
233-
elif sslErr == 0 and err == -1:
234-
errStr.add ' '
235-
errStr.add "in the BIO layer"
236-
else:
237-
let errStr = $ERR_error_string(sslErr, nil)
238-
raiseSSLError(errStr & ": " & errStr)
239-
raiseOSError(osErr, errStr)
240-
else:
241-
return ret
242-
of SSL_ERROR_SSL:
226+
of SSL_ERROR_SYSCALL, SSL_ERROR_SSL:
243227
socket.sslNoShutdown = true
244228
raiseSSLError()
245229
else: raiseSSLError("Unknown Error")
246230

247-
proc handleSslFailure(socket: AsyncSocket, flags: set[SocketFlag], sslError: cint): Future[bool] =
231+
proc sendPendingSslData(socket: AsyncSocket,
232+
flags: set[SocketFlag]) {.async.} =
233+
if socket.sslHandle == nil:
234+
raiseSslHandleError()
235+
let len = bioCtrlPending(socket.bioOut)
236+
if len > 0:
237+
var data = newString(len)
238+
let read = bioRead(socket.bioOut, cast[cstring](addr data[0]), len)
239+
assert read != 0
240+
if read < 0:
241+
raiseSSLError()
242+
data.setLen(read)
243+
await socket.fd.AsyncFD.send(data, flags)
244+
245+
proc appeaseSsl(socket: AsyncSocket, flags: set[SocketFlag],
246+
sslError: cint): owned(Future[bool]) {.async.} =
248247
## Returns `true` if `socket` is still connected, otherwise `false`.
249-
let retFut = newFuture[bool]("asyncnet.handleSslFailure")
248+
result = true
250249
case sslError
251-
of SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT:
252-
addWrite(socket.fd.AsyncFD, proc (sock: AsyncFD): bool =
253-
retFut.complete(true)
254-
return true
255-
)
250+
of SSL_ERROR_WANT_WRITE:
251+
await sendPendingSslData(socket, flags)
256252
of SSL_ERROR_WANT_READ:
257-
addRead(socket.fd.AsyncFD, proc (sock: AsyncFD): bool =
258-
retFut.complete(true)
259-
return true
260-
)
261-
of SSL_ERROR_SYSCALL:
262-
assert flags.isDisconnectionError(osLastError())
263-
retFut.complete(false)
253+
var data = await recv(socket.fd.AsyncFD, BufferSize, flags)
254+
if socket.sslHandle == nil:
255+
raiseSslHandleError()
256+
let length = len(data)
257+
if length > 0:
258+
let ret = bioWrite(socket.bioIn, cast[cstring](addr data[0]), length.cint)
259+
if ret < 0:
260+
raiseSSLError()
261+
elif length == 0:
262+
# connection not properly closed by remote side or connection dropped
263+
SSL_set_shutdown(socket.sslHandle, SSL_RECEIVED_SHUTDOWN)
264+
result = false
264265
else:
265-
raiseSSLError("Cannot handle SSL failure.")
266-
return retFut
266+
raiseSSLError("Cannot appease SSL.")
267267

268268
template sslLoop(socket: AsyncSocket, flags: set[SocketFlag],
269269
op: untyped) =
@@ -274,12 +274,20 @@ when defineSsl:
274274
ErrClearError()
275275
# Call the desired operation.
276276
opResult = op
277+
let err =
278+
if opResult < 0:
279+
getSslError(socket, opResult.cint)
280+
else:
281+
SSL_ERROR_NONE
282+
# Send any remaining pending SSL data.
283+
await sendPendingSslData(socket, flags)
284+
277285
# If the operation failed, try to see if SSL has some data to read
278286
# or write.
279287
if opResult < 0:
280-
let err = getSslError(socket, flags, opResult.cint)
281-
let connected = await handleSslFailure(socket, flags, err.cint)
282-
if not connected:
288+
let fut = appeaseSsl(socket, flags, err.cint)
289+
yield fut
290+
if not fut.read():
283291
# Socket disconnected.
284292
if SocketFlag.SafeDisconn in flags:
285293
opResult = 0.cint
@@ -315,7 +323,8 @@ proc connect*(socket: AsyncSocket, address: string, port: Port) {.async.} =
315323
discard SSL_set_tlsext_host_name(socket.sslHandle, address)
316324

317325
let flags = {SocketFlag.SafeDisconn}
318-
sslLoop(socket, flags, SSL_connect(socket.sslHandle))
326+
sslSetConnectState(socket.sslHandle)
327+
sslLoop(socket, flags, sslDoHandshake(socket.sslHandle))
319328

320329
template readInto(buf: pointer, size: int, socket: AsyncSocket,
321330
flags: set[SocketFlag]): int =
@@ -452,6 +461,7 @@ proc send*(socket: AsyncSocket, buf: pointer, size: int,
452461
when defineSsl:
453462
sslLoop(socket, flags,
454463
sslWrite(socket.sslHandle, cast[cstring](buf), size.cint))
464+
await sendPendingSslData(socket, flags)
455465
else:
456466
await send(socket.fd.AsyncFD, buf, size, flags)
457467

@@ -465,6 +475,7 @@ proc send*(socket: AsyncSocket, data: string,
465475
var copy = data
466476
sslLoop(socket, flags,
467477
sslWrite(socket.sslHandle, cast[cstring](addr copy[0]), copy.len.cint))
478+
await sendPendingSslData(socket, flags)
468479
else:
469480
await send(socket.fd.AsyncFD, data, flags)
470481

@@ -765,8 +776,9 @@ when defineSsl:
765776
if socket.sslHandle == nil:
766777
raiseSSLError()
767778
768-
if SSL_set_fd(socket.sslHandle, socket.fd) != 1:
769-
raiseSSLError()
779+
socket.bioIn = bioNew(bioSMem())
780+
socket.bioOut = bioNew(bioSMem())
781+
sslSetBio(socket.sslHandle, socket.bioIn, socket.bioOut)
770782
771783
socket.sslNoShutdown = true
772784
@@ -783,8 +795,6 @@ when defineSsl:
783795
##
784796
## **Disclaimer**: This code is not well tested, may be very unsafe and
785797
## prone to security vulnerabilities.
786-
if socket.isSsl:
787-
return
788798
wrapSocket(ctx, socket)
789799
790800
case handshake

tests/async/t24895.nim

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)