From 495c372335508437d96a633615a49fb31cfbbfda Mon Sep 17 00:00:00 2001 From: Eric Forgy Date: Sun, 11 Feb 2018 23:31:02 +0800 Subject: [PATCH] Under construction... --- src/WebSockets.jl | 51 ++++++++++++++++++++++++++++++++++++---------- test/WebSockets.jl | 44 +++++++++++++++++++-------------------- test/runtests.jl | 26 +++++++++++------------ 3 files changed, 75 insertions(+), 46 deletions(-) diff --git a/src/WebSockets.jl b/src/WebSockets.jl index ecc0c3bd3..d0c59faa6 100644 --- a/src/WebSockets.jl +++ b/src/WebSockets.jl @@ -36,6 +36,7 @@ struct WebSocketHeader mask::UInt32 end +@enum ReadyState CONNECTED=0x1 CLOSING=0x2 CLOSED=0x3 mutable struct WebSocket{T <: IO} <: IO io::T @@ -43,13 +44,13 @@ mutable struct WebSocket{T <: IO} <: IO server::Bool rxpayload::Vector{UInt8} txpayload::Vector{UInt8} - txclosed::Bool - rxclosed::Bool + txstate::ReadyState + rxstate::ReadyState end function WebSocket(io::T; server=false, binary=false) where T <: IO WebSocket{T}(io, binary ? WS_BINARY : WS_TEXT, server, - UInt8[], UInt8[], false, false) + UInt8[], UInt8[], CONNECTED, CONNECTED) end @@ -168,12 +169,25 @@ function Base.write(ws::WebSocket, x1, x2, xs...) end -function IOExtras.closewrite(ws::WebSocket) - @require !ws.txclosed +function closewrite(ws::WebSocket) + # println("(closewrite) server: $(ws.server), rxstate: $(ws.rxstate), txstate: $(ws.txstate)") + @require ws.txstate == CONNECTED opcode = WS_FINAL | WS_CLOSE @debug 1 "WebSocket ⬅️ $(WebSocketHeader(opcode, 0x00))" - write(ws.io, opcode, 0x00) - ws.txclosed = true + isopen(ws.io) && write(ws.io, opcode, 0x00) + ws.txstate = CLOSING +end + + +function closeread(ws::WebSocket) + # println("(closeread) server: $(ws.server), rxstate: $(ws.rxstate), txstate: $(ws.txstate)") + @require ws.rxstate == CONNECTED + opcode = WS_FINAL | WS_CLOSE + @debug 1 "WebSocket ⬅️ $(WebSocketHeader(opcode, 0x00))" + # println("(closeread) Send close opcode") + isopen(ws.io) && write(ws.io, opcode, 0x00) + # println("(closeread) Close opcode sent") + ws.rxstate = CLOSING end @@ -218,16 +232,23 @@ end function Base.close(ws::WebSocket) - if !ws.txclosed + # println("(close) server: $(ws.server), rxstate: $(ws.rxstate), txstate: $(ws.txstate)") + # println("Check CONNECTED") + if ws.txstate == CONNECTED closewrite(ws) end - while !ws.rxclosed + ws.rxstate = CLOSING + # println("Check CLOSING") + while !eof(ws) && ws.rxstate == CLOSING readframe(ws) end + # println("(close) Close") + isopen(ws.io) && close(ws.io) + # println("(close) Closed") end -Base.isopen(ws::WebSocket) = !ws.rxclosed +Base.isopen(ws::WebSocket) = (ws.rxstate == CONNECTED) && isopen(ws.io) @@ -264,7 +285,8 @@ function readframe(ws::WebSocket) end if h.opcode == WS_CLOSE - ws.rxclosed = true + # println("Received a close opcode") + # println("(readframe) server: $(ws.server), rxstate: $(ws.rxstate), txstate: $(ws.txstate)") if h.length >= 2 status = UInt16(ws.rxpayload[1]) << 8 | ws.rxpayload[2] if status != 1000 @@ -272,6 +294,13 @@ function readframe(ws::WebSocket) throw(WebSocketError(status, message)) end end + if ws.rxstate == CONNECTED + closeread(ws) + end + if ws.rxstate == CLOSING + ws.rxstate = CLOSED + isopen(ws.io) && close(ws.io) + end return UInt8[] elseif h.opcode == WS_PING write(ws.io, [WS_PONG, 0x00]) diff --git a/test/WebSockets.jl b/test/WebSockets.jl index 3aba8c21a..16fdce27b 100644 --- a/test/WebSockets.jl +++ b/test/WebSockets.jl @@ -4,26 +4,26 @@ using HTTP.IOExtras @testset "WebSockets" begin -for s in ["ws", "wss"] +# for s in ["ws", "wss"] - HTTP.WebSockets.open("$s://echo.websocket.org") do ws - write(ws, HTTP.bytes("Foo")) - @test !eof(ws) - @test String(readavailable(ws)) == "Foo" +# HTTP.WebSockets.open("$s://echo.websocket.org") do ws +# write(ws, HTTP.bytes("Foo")) +# @test !eof(ws) +# @test String(readavailable(ws)) == "Foo" - write(ws, HTTP.bytes("Hello")) - write(ws, " There") - write(ws, " World", "!") - closewrite(ws) +# write(ws, HTTP.bytes("Hello")) +# write(ws, " There") +# write(ws, " World", "!") +# closewrite(ws) - io = IOBuffer() - write(io, ws) - @test String(take!(io)) == "Hello There World!" +# io = IOBuffer() +# write(io, ws) +# @test String(take!(io)) == "Hello There World!" - close(ws) - end +# close(ws) +# end -end +# end p = 8000 @@ -46,15 +46,15 @@ HTTP.WebSockets.open("ws://127.0.0.1:$(p)") do ws @test !eof(ws) @test String(readavailable(ws)) == "Foo" - write(ws, HTTP.bytes("Hello")) - write(ws, " There") - write(ws, " World", "!") + # write(ws, HTTP.bytes("Hello")) + # write(ws, " There") + # write(ws, " World", "!") - closewrite(ws) + # closewrite(ws) - io = IOBuffer() - write(io, ws) - @test String(take!(io)) == "Hello There World!" + # io = IOBuffer() + # write(io, ws) + # @test String(take!(io)) == "Hello There World!" close(ws) end diff --git a/test/runtests.jl b/test/runtests.jl index cb5bd5ed8..c2be59115 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,7 @@ @static if VERSION >= v"0.7.0-DEV.2915" using Distributed end -addprocs(5) +# addprocs(5) using HTTP using HTTP.Dates @@ -9,20 +9,20 @@ using HTTP.Test @testset "HTTP" begin - include("utils.jl"); - include("sniff.jl"); - include("uri.jl"); - include("url.jl"); - include("cookies.jl"); - include("parser.jl"); + # include("utils.jl"); + # include("sniff.jl"); + # include("uri.jl"); + # include("url.jl"); + # include("cookies.jl"); + # include("parser.jl"); - include("loopback.jl"); + # include("loopback.jl"); include("WebSockets.jl"); - include("messages.jl"); - include("client.jl"); + # include("messages.jl"); + # include("client.jl"); - include("handlers.jl") - include("server.jl") + # include("handlers.jl") + # include("server.jl") - include("async.jl"); + # include("async.jl"); end;