diff --git a/docs/examples/cors_server.jl b/docs/examples/cors_server.jl index 2275b3619..ad6765cbc 100644 --- a/docs/examples/cors_server.jl +++ b/docs/examples/cors_server.jl @@ -39,7 +39,7 @@ const CORS_RES_HEADERS = ["Access-Control-Allow-Origin" => "*"] #= JSONMiddleware minimizes code by automatically converting the request body to JSON to pass to the other service functions automatically. JSONMiddleware -recieves the body of the response from the other service funtions and sends +receives the body of the response from the other service funtions and sends back a success response code =# function JSONMiddleware(handler) @@ -65,9 +65,9 @@ function JSONMiddleware(handler) end #= CorsMiddleware: handles preflight request with the OPTIONS flag -If a request was recieved with the correct headers, then a response will be +If a request was received with the correct headers, then a response will be sent back with a 200 code, if the correct headers were not specified in the request, -then a CORS error will be recieved on the client side +then a CORS error will be received on the client side Since each request passes throught the CORS Handler, then if the request is not a preflight request, it will simply go to the JSONMiddleware to be passed to the diff --git a/src/Servers.jl b/src/Servers.jl index 17fa5955c..2012e3361 100644 --- a/src/Servers.jl +++ b/src/Servers.jl @@ -83,10 +83,22 @@ accept(s::Listener{SSLConfig}) = getsslcontext(Sockets.accept(s.server), s.ssl) function getsslcontext(tcp, sslconfig) try + handshake_done = Ref{Bool}(false) ssl = MbedTLS.SSLContext() MbedTLS.setup!(ssl, sslconfig) MbedTLS.associate!(ssl, tcp) + thistask = current_task() + # this task is meant to be super small while the handshake remains on the main task + @async begin + timedwait(2.0) do + handshake_done[] || istaskdone(thistask) + end + if !handshake_done[] && !istaskdone(thistask) + Base.throwto(thistask, Base.IOError("SSL handshake timed out", Base.ETIMEDOUT)) + end + end MbedTLS.handshake!(ssl) + handshake_done[] = true return ssl catch e @try Base.IOError close(tcp) @@ -369,26 +381,32 @@ function listenloop(f, listener, conns, tcpisvalid, while isopen(listener) try Base.acquire(sem) - io = accept(listener) - if io === nothing - @warnv 1 "unable to accept new connection" - continue - elseif !tcpisvalid(io) - @warnv 1 "!tcpisvalid: $io" - close(io) - continue - end - conn = Connection(io) - conn.state = IDLE - push!(conns, conn) - conn.host, conn.port = listener.hostname, listener.hostport - @async try - handle_connection(f, conn, listener, readtimeout, access_log) - finally - # handle_connection is in charge of closing the underlying io - delete!(conns, conn) - Base.release(sem) - end + io = Sockets.accept(listener.server) + @async begin + local conn = nothing + try + if io === nothing + @warnv 1 "unable to accept new connection" + return + end + if !isnothing(listener.ssl) + io = getsslcontext(io, listener.ssl) + end + if !tcpisvalid(io) + close(io) + return + end + conn = Connection(io) + conn.state = IDLE + push!(conns, conn) + conn.host, conn.port = listener.hostname, listener.hostport + handle_connection(f, conn, listener, readtimeout, access_log) + finally + # handle_connection is in charge of closing the underlying io, but it may not get there + !isnothing(conn) && delete!(conns, conn) + Base.release(sem) + end + end # Task.@spawn catch e if e isa Base.IOError && e.code == Base.UV_ECONNABORTED verbose >= 0 && @infov 1 "Server on $(listener.hostname):$(listener.hostport) closing" @@ -445,7 +463,7 @@ function handle_connection(f, c::Connection, listener, readtimeout, access_log) request.response.status = 200 try - # invokelatest becuase the perf is negligible, but this makes live-editing handlers more Revise friendly + # invokelatest because the perf is negligible, but this makes live-editing handlers more Revise friendly @debugv 1 "invoking handler" Base.invokelatest(f, http) # If `startwrite()` was never called, throw an error so we send a 500 and log this diff --git a/src/WebSockets.jl b/src/WebSockets.jl index ab9e532da..53bb008bc 100644 --- a/src/WebSockets.jl +++ b/src/WebSockets.jl @@ -589,7 +589,7 @@ function Base.close(ws::WebSocket, body::CloseFrameBody=CloseFrameBody(1000, "") ws.readclosed = true end end - # we either recieved the responding CLOSE frame and readclosed was set + # we either received the responding CLOSE frame and readclosed was set # or there was an error/timeout reading it; in any case, readclosed should be closed now @assert ws.readclosed # if we're the server, it's our job to close the underlying socket