Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for close_notify message in Base.isopen(ctx::SSLContext) #145

Merged
merged 3 commits into from
Apr 18, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions src/ssl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,16 @@ function handshake(ctx::SSLContext)
wait(ctx)
end
ctx.isopen = true

@schedule while isopen(ctx)
# Ensure that libuv is reading data from the socket in case the peer
# has sent a close_notify message on an otherwise idle connection.
# https://tools.ietf.org/html/rfc5246#section-7.2.1
Base.start_reading(ctx.bio)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base.start_reading should always be very cheap:

    elseif stream.status == StatusPaused
        stream.status = StatusActive
        return Int32(0)
    elseif stream.status == StatusActive
        return Int32(0)

https://github.com/JuliaLang/julia/blob/master/base/stream.jl#L651-L655

wait(ctx.bio.readnotify)
yield()
end

return
end

Expand Down Expand Up @@ -223,7 +233,7 @@ function Base.unsafe_read(ctx::SSLContext, buf::Ptr{UInt8}, nbytes::UInt; err=tr
ctx.data, buf + nread, nbytes - nread)
end
if n == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY || n == 0
ctx.isopen = false
close(ctx)
err ? throw(EOFError()) : return nread
elseif n == MBEDTLS_ERR_SSL_WANT_READ
wait(ctx)
Expand Down Expand Up @@ -270,7 +280,35 @@ function Base.close(ctx::SSLContext)
nothing
end

Base.isopen(ctx::SSLContext) = ctx.isopen && isopen(ctx.bio)
function Base.isopen(ctx::SSLContext)

if !ctx.isopen || !isopen(ctx.bio)
return false
end

decrypt_available_bytes(ctx)

return ctx.isopen && isopen(ctx.bio)
end

function decrypt_available_bytes(ctx::SSLContext)

# Zero-byte read causes MbedTLS to call f_recv (always non-blocking)
# and decrypt any bytes that are already in the LibuvStream read buffer.
# https://esp32.com/viewtopic.php?t=1101#p4884
n = @lockdata ctx begin
ccall((:mbedtls_ssl_read, libmbedtls), Cint,
(Ptr{Cvoid}, Ptr{Cvoid}, Csize_t),
ctx.data, C_NULL, 0)
end
if n == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY
close(ctx)
elseif n == MBEDTLS_ERR_SSL_WANT_READ
# ignore
elseif n < 0
mbed_err(n)
end
end

function get_peer_cert(ctx::SSLContext)
data = ccall((:mbedtls_ssl_get_peer_cert, libmbedtls), Ptr{Cvoid}, (Ptr{Cvoid},), ctx.data)
Expand Down Expand Up @@ -299,15 +337,9 @@ end

function _bytesavailable(ctx::SSLContext)

@lockdata ctx begin
decrypt_available_bytes(ctx)

# First do a zero-byte read.
# This causes MbedTLS to call f_recv (which is always non-blocking)
# and decrypt any bytes that are already in the LibuvStream read buffer.
# https://esp32.com/viewtopic.php?t=1101#p4884
ccall((:mbedtls_ssl_read, libmbedtls), Cint,
(Ptr{Cvoid}, Ptr{Cvoid}, Csize_t),
ctx.data, C_NULL, 0)
@lockdata ctx begin

# Now that the bufferd bytes have been processed, find out how many
# decrypted bytes are available.
Expand Down