OpenSSL.jl/src/flow_control.jl

158 lines
4.0 KiB
Julia

function queue_encrypted_bytes(client, buf)
# println("Adding $(length(buf)) for a total of $(length(buf) + length(client.write_buf))")
append!(client.write_buf, buf)
end
function do_ssl_handshake(client)
n = SSL_handshake(client)
status = ssl_status(client, n)
if status in (SSL_WANT_READ, SSL_WANT_WRITE)
while true
(n, buf) = bio_read(client)
# println("bio_read: $(n)")
if n > 0
queue_encrypted_bytes(client, buf)
elseif !bio_should_retry(client.wbio)
return -1
else
break
end
end
end
# println("End of ssl handshake")
return status
end
function send_unencrypted_bytes(client, buf)
append!(client.encrypt_buf, buf)
end
function do_encrypt(client)
ssl_init_finished(client) || return 0
while length(client.encrypt_buf) > 0
n = ssl_write(client, client.encrypt_buf)
status = ccall((:SSL_get_error, libssl), SSL_ERRORS, (Ptr{Cvoid}, Cint),
client.ssl, n)
if n > 0
splice!(client.encrypt_buf, 1:n)
while true
(n, buf) = bio_read(client)
if n > 0
queue_encrypted_bytes(client, buf)
elseif !bio_should_retry(client.wbio)
return -1
else
break
end
end
end
if status in (SSL_ERROR, SSL_SYSCALL)
@warn "SSL ERROR"
return -1
end
if n == 0
break
end
end
return 0
end
function on_read_cb(client, buffer)
idx = 1
len = length(buffer)
while len > 0
n = bio_write!(client, buffer[idx:end])
if n <= 0
return -1
end
idx += n
len -= n
if ! ssl_init_finished(client)
# println("SSL not finished yet")
if (do_ssl_handshake(client) == -1)
return -1
end
if !ssl_init_finished(client)
return 0
end
end
# println("NOW IT FINISHED\n")
while true
(n, buf) = read(client)
if n > 0
client.io_on_read(buf[1:n])
else
break
end
end
status = ssl_status(client, n)
if status in (SSL_WANT_READ, SSL_WANT_WRITE)
while true
(n, buf) = bio_read(client)
if n > 0
queue_encrypted_bytes(client, buf)
elseif !bio_should_retry(client.wbio)
return -1
else
break
end
end
end
if status in (SSL_ERROR, SSL_SYSCALL)
return -1
end
end
return 0
end
function do_sock_read(client::SSLClient)
buf = readavailable(client.sock)
if length(buf) > 0
return on_read_cb(client, buf)
else
return -1
end
end
function do_sock_write(client::SSLClient)
n = write(client.sock, client.write_buf)
# println("Written to the client: $n")
if n > 0
splice!(client.write_buf, 1:n)
return 0
else
return -1
end
end
function do_ssl_shutdown(client)
n = shutdown(client)
status = ssl_status(client, n)
# Special case, do the shutdown again
if n == 0
n = shutdown(client)
@show status = ssl_status(client, n)
end
if status in (SSL_WANT_READ, SSL_WANT_WRITE)
while true
(n, buf) = bio_read(client)
if n > 0
queue_encrypted_bytes(client, buf)
elseif !bio_should_retry(client.wbio)
return -1
else
res = do_sock_write(client)
# TODO: Check res?
break
end
end
end
# Here, ssl_status(client, shutdown(client))
# still want read .-.,,
return status
end