From e69a981c50273ab0aa5890e177b628db81f2fb65 Mon Sep 17 00:00:00 2001 From: hustf Date: Sat, 18 Nov 2017 13:50:24 +0100 Subject: [PATCH] Binary browser test, performance logging (#80) ``` mod: test/browsertest.jl Removed ws writing from main thread to handlers. Prints a performance summary at the end. Increased expected number of messages. mod: test/browsertest.html Less code duplication, simplified conversation. Navigates to browsertest2.html when exitmsg is received. new: test/browsertest2.html Adds one binary socket. Sends binary image data with increasing image size. Displays received images. Logs conversation on page. mod: test/functions_log_test.jl clog now returns nothing, for type stability. mod: test/functions_server.jl Also serves browsertest2.html. localhost -> 127.0.0.1 Specify closing http sockets in responses, "Connection" =>"close". mod: test/handler_functions_events.jl Removed accidentally returned string, ev_listen. mod: test/functions_open_browsers.jl PhantomJS is now 'run' async, not spawned, for console feedback. Introduce sleeping time 8 s between launching browsers, for more readable output and less server congestion. mod: test/handler_functions_websockets_general_test.jl Added text message performance logging, changed ws test conversation. Include a request for a ping from browser (pongs are not output). mod: test/handler_functions_websockets_subprotocol_test.jl Added performance logging. Changed ws test conversation. Added binary handler, which modifies images before sending back to browser. ``` --- test/browsertest.html | 256 ++++++++---------- test/browsertest.jl | 171 +++++++++--- test/browsertest2.html | 239 ++++++++++++++++ test/functions_log_test.jl | 5 +- test/functions_open_browsers.jl | 11 +- test/functions_server.jl | 49 +++- test/handler_functions_events.jl | 3 +- ...ndler_functions_websockets_general_test.jl | 53 ++-- ...r_functions_websockets_subprotocol_test.jl | 102 +++++-- 9 files changed, 641 insertions(+), 248 deletions(-) create mode 100644 test/browsertest2.html diff --git a/test/browsertest.html b/test/browsertest.html index d51ec6b..63216ff 100644 --- a/test/browsertest.html +++ b/test/browsertest.html @@ -1,167 +1,105 @@ - - WebSockets browsertest.html + WS text + -

Test tries to open some websockets, browser says hello from browser, and continues to echo messages from server.

+

Test tries to open three different websockets. +

+ +

+Websocket initiates with sending "Ping me!" with signature.
+
They echo received messages, but react to: +
  "" +

  This is ...

ws1 Websocket

ws2 Websocket: websocket-testprotocol

ws3 Websocket: server_denies_protocol

- - + diff --git a/test/browsertest.jl b/test/browsertest.jl index cfd3b6e..1115bc3 100644 --- a/test/browsertest.jl +++ b/test/browsertest.jl @@ -1,60 +1,143 @@ # Included in runtests at the end. +# Can also be run directly. +# Launches available browsers on browsertest.html. +# Websockets are intiated by the browser / web page. +# Handler_functions_websockets respond and store allocations & etc. +# After a successfull exchange, the browsers navigate to a second html page +# for binary performance tests. In the end, all websockets are closed +# and a summary is output. +cd(Pkg.dir("WebSockets","test")) +using Compat +using WebSockets +using Base.Test const WEBSOCKETS = Dict{Int, WebSockets.WebSocket}() +const RECEIVED_WS_MSGS_TIME = Dict{Int, Vector{Float64}}() +const RECEIVED_WS_MSGS_ALLOCATED = Dict{Int, Vector{Int64}}() +const RECEIVED_WS_MSGS_LENGTH = Dict{Int, Vector{Int64}}() const WEBSOCKETS_SUBPROTOCOL = Dict{Int, WebSockets.WebSocket}() +const WEBSOCKETS_BINARY = Dict{Int, WebSockets.WebSocket}() +# Note that only text messages are stored. Binary messages are discarded. const RECEIVED_WS_MSGS = Dict{Int, Vector{String}}() -global noofresponders = 0 +# Logs from travis indicate it takes 7 s to fire up Safari and +# have the first websocket open. This can easily increase if more +# browsers become available. +const FIRSTWAIT = Base.Dates.Second(2) +const MAXWAIT = Base.Dates.Second(60*15) +global n_responders = 0 include("functions_server.jl") - +closeall() server = start_ws_server_async() +include("functions_open_browsers.jl") +info("This OS is $(string(Sys.KERNEL))\n") +n_browsers = 0 +#n_browsers += open_testpage("firefox") +n_browsers += open_all_browsers() + +# Control flow passes to async handler functions -# Give the server 5 seconds to get going. -sleep(5) -info("We waited 5 seconds after starting the server.") -for (ke, va) in WEBSOCKETS - if isopen(va) - info("Somebody opened a websocket during that time. Closing it now.") - close(va) +if n_browsers > 0 + info("Sleeping main thread for an initial minimum of $FIRSTWAIT\n") + t0 = now() + while now()-t0 < FIRSTWAIT + sleep(1) + end + contwait = true + while contwait && now()-t0 < MAXWAIT + # All websockets close briefly when navigating from browsertest.html to browsertest2.html + # So we require two consecutive checks for websockets before exiting, with 2 seconds between. + contwait = count_open_websockets() > 0 + if !contwait + sleep(2) + passedtime = now() - t0 + exitlatestin = MAXWAIT + t0- now() + info("$(div(passedtime.value, 1000)) s passed. Max remaining test time $(div(exitlatestin.value, 1000)) s\n") + end + sleep(.5) + contwait = contwait && count_open_websockets() > 0 end end +n_opensockets = count_open_websockets() -info("This OS is ", Sys.KERNEL) -include("functions_open_browsers.jl") -noofbrowsers = open_all_browsers() -const CLOSEAFTER = Base.Dates.Second(15) -t0 = now() -while now()-t0 < CLOSEAFTER && length(keys(RECEIVED_WS_MSGS)) < noofbrowsers * 2 - sleep(1) -end -info("Received messages on ", length(keys(RECEIVED_WS_MSGS)), " sockets.") -info("Tell the special sockets to initiate a close.") -for (ke, va) in WEBSOCKETS_SUBPROTOCOL - writeto(ke, "YOU hang up!") +closeall() +info(Dates.format(now(), "HH:MM:SS"), "\tClosed web sockets and servers.") +# sum up +allocs = Vector{Int64}() +times = Vector{Float64}() +lengths = Vector{Int64}() +n_msgs = 0 +n_text = 0 +n_ws = 0 +for ke in keys(WEBSOCKETS) + n_ws += 1 + for msgno = 1:length(RECEIVED_WS_MSGS_LENGTH[ke]) + if RECEIVED_WS_MSGS_LENGTH[ke][msgno] > 0 + n_msgs += 1 + push!(allocs, RECEIVED_WS_MSGS_ALLOCATED[ke][msgno]) + push!(times, RECEIVED_WS_MSGS_TIME[ke][msgno]) + push!(lengths, RECEIVED_WS_MSGS_LENGTH[ke][msgno]) + if haskey(RECEIVED_WS_MSGS, ke) + n_text += 1 + end + end + end end +n_binary = n_msgs - n_text + +# print summary +info("Spawned $n_browsers browsers. $n_browsers made requests. Opened $n_ws sockets, $n_opensockets did not close as intended.") +info("Received $n_msgs messages, $n_text text and $n_binary binary, $(round(sum(lengths)/ 1000 / 1000,3)) Mb, sent a similar amount.") + + + + -sleep(10) -info("Closing down after ", now()-t0, " including 10 seconds pause.") -countstillopen = 0 -for (ke, va) in WEBSOCKETS - if isopen(va) - info(" Websocket to close: ", va) - countstillopen +=1 - close(va) +if n_msgs > 0 + maxlength = maximum( lengths ) + minlength = minimum( va -> va > 0.0 ? va:typemax(va), lengths ) + avglength = sum(lengths) / n_msgs + + maxaloc = maximum( va -> va < Inf ? va:0.0, allocs ./ lengths ) + minaloc = minimum( va -> va > 0.0 ? va:typemax(va), allocs ./ lengths ) + avgaloc = sum(allocs) / sum(lengths) + + maxtime = maximum(va -> va < Inf ? va:0.0, times) + mintime = minimum(va -> va > 0.0 ? va:typemax(va), times) + avgtime = sum(times) / n_msgs + + maxspeed = maximum(va -> va < Inf ? va:0.0, lengths ./ times) + minspeed = minimum(va -> va > 0.0 ? va:typemax(va), lengths ./ times) + avgspeed = sum(lengths) / sum(times) + + info("Length of messages received\n", + "\t\tAverage length:\t\t", round(avglength / 1000, 3), " kB\n", + "\t\t\Minimum :\t\t", minlength , " b\n", + "\t\t\Maximum :\t\t", round(maxlength / 1000 / 1000 , 3), " Mb\n") + + info("Time spent reading and waiting for received messages\n", + "\t\tAverage time:\t\t", round(avgtime, 4), " s\n", + "\t\t\Minimum :\t\t", mintime , " s\n", + "\t\t\Maximum :\t\t", maxtime, " s\n") + + info("Reading speed (strongly affected by the active browsers)\n", + "\t\tAverage speed:\t", round(avgspeed / 1000 / 1000, 3), " Mb/s\n", + "\t\t\Minimum :\t", round(minspeed / 1000 / 1000 , 10), " Mb/s\n", + "\t\t\Maximum :\t", round(maxspeed / 1000 / 1000, 3), " Mb/s\n") + + info("Allocations for reading, bytes allocated per byte received\n", + "\t\tAverage allocation:\t", round(avgaloc, 3), "\n", + "\t\t\Minimum :\t\t", round(minaloc, 3), "\n", + "\t\t\Maximum :\t\t", round(maxaloc, 3), "\n",) + + info("Text messages received per websocket:") + for m in RECEIVED_WS_MSGS + display(m) end + +else + info("Failure on speed / allocation test.") end -sleep(5) -close(server) -server = nothing -info("Openened $noofbrowsers, from which $noofresponders requested the HTML page.") -info("Received messages for each websocket:") -display(RECEIVED_WS_MSGS) -println() -@test countstillopen == noofresponders -countmessages = 0 -for (ke, va) in RECEIVED_WS_MSGS - countmessages += length(va) -end -@test length(keys(RECEIVED_WS_MSGS)) == noofresponders * 2 -@test countmessages == noofresponders * 6 -nothing + +@test n_opensockets == 0 +@test n_msgs == n_responders * 37 \ No newline at end of file diff --git a/test/browsertest2.html b/test/browsertest2.html new file mode 100644 index 0000000..9f2136e --- /dev/null +++ b/test/browsertest2.html @@ -0,0 +1,239 @@ + + + + WS binary + + + +

This second test page

+ + +

+

+

  This is ... +

+
+

Source image

+Canvas +

+

+
+

Destination image

+Canvas +
+

ws10 Websocket

+ + + + diff --git a/test/functions_log_test.jl b/test/functions_log_test.jl index 54e8dd0..f95f7e6 100644 --- a/test/functions_log_test.jl +++ b/test/functions_log_test.jl @@ -14,9 +14,9 @@ import WebSockets.WebSocketHandler import WebSockets.WebSocket import Base.print "Date time group string" -dtg() = Dates.format(now(), "d u yy HH:MM:SS") +dtg() = Dates.format(now(), "HH:MM:SS") """ -Console log with a heading, buffer and no mixing with output from other simultaneous tasks. +Console log with a heading, buffer and no mixing with output from other tasks. We may, of course, be interrupting other tasks like stacktrace output. """ function clog(args...) @@ -25,6 +25,7 @@ function clog(args...) lock(STDERR) print(STDERR, String(take!(buf))) unlock(STDERR) + nothing end "Print with 'color' arguments Base.text_colors placed anywhere. Color_normal is set after the call is finished. " function pwc(io::IO, args...) diff --git a/test/functions_open_browsers.jl b/test/functions_open_browsers.jl index 54222ff..98ef031 100644 --- a/test/functions_open_browsers.jl +++ b/test/functions_open_browsers.jl @@ -82,7 +82,7 @@ function browser_path_windows(shortname) return "" end function launch_command(shortbrowsername) - url = "http://localhost:8080/browsertest.html" + url = "http://127.0.0.1:8080/browsertest.html" if Sys.is_windows() pt = browser_path_windows(shortbrowsername) else @@ -117,7 +117,13 @@ function open_testpage(shortbrowsername) return false else try - spawn(dmc) + if shortbrowsername == "phantomjs" + # Run enables text output of phantom messages in the REPL. In Windows + # standalone REPL, run will freeze the main thread if not run async. + @async run(dmc) + else + spawn(dmc) + end catch info("\tFailed to spawn " * shortbrowsername) return false @@ -131,6 +137,7 @@ function open_all_browsers() openbrowsers = 0 for b in brs openbrowsers += open_testpage(b) + sleep(8) # Reduce simultaneous connections to server. This is not a httpserver stress test. width: end info("Out of google chrome, firefox, iexplore, safari and phantomjs, tried to spawn ", openbrowsers) openbrowsers diff --git a/test/functions_server.jl b/test/functions_server.jl index 406750e..e685450 100644 --- a/test/functions_server.jl +++ b/test/functions_server.jl @@ -10,20 +10,25 @@ the types defined in HttpServer references to the functions. More commonly, anon are used. """ function httphandle(request::Request, response::Response) - global noofresponders + global n_responders id = "server_functions.httphandle\t" clog(id, :cyan, request, "\n") if request.method=="GET" if request.resource =="/favicon.ico" response = HttpServer.FileResponse(joinpath(@__DIR__, "favicon.ico")) + elseif startswith(request.resource, "/browser") + response = HttpServer.FileResponse(joinpath(@__DIR__, splitdir(request.resource)[2])) + if request.resource == "/browsertest.html" + n_responders += 1 + end else - response = HttpServer.FileResponse(joinpath(@__DIR__, "browsertest.html")) - noofresponders += 1 + response = Response(404, "$id, can't serve $request.resource.") end else response = Response(404, "$id, unexpected request.") end clog(id, response, "\n") + push!(response.headers, "Connection" => "close") return response end @@ -37,19 +42,15 @@ function websockethandle(wsrequest::Request, websocket::WebSocket) id = "server_functions.websockethandle\t" clog(id, :cyan, wsrequest, "\t", :yellow, websocket, "\n") if haskey(wsrequest.headers,"Sec-WebSocket-Protocol") - clog(id, "subprotocol spec: \n\t\t\t", - :yellow, "Sec-WebSocket-Protocol => ", wsrequest.headers["Sec-WebSocket-Protocol"],"\n") - if wsrequest.headers["Sec-WebSocket-Protocol"] == "websocket-testprotocol" - clog(id, "Websocket-testprotocol, calling handler\n") + if wsrequest.headers["Sec-WebSocket-Protocol"] == "websocket-testprotocol" ws_test_protocol(websocket) - clog(id, "Websocket-testprotocol, exiting handler\n") + elseif wsrequest.headers["Sec-WebSocket-Protocol"] == "websocket-test-binary" + ws_test_binary(websocket) else - clog(id, :red, "Unknown sub protocol let through WebSockets.jl, not responding further. \n") + clog(id, :red, "Unknown sub protocol let through, not responding further to #$(websocket.id). \n") end else - clog(id, "General websocket, calling handler\n") ws_general(websocket) - clog(id, "General websocket, exiting handler\n") end clog(id, "Exiting \n") nothing @@ -60,6 +61,7 @@ function start_ws_server_async() id = "server_functions.start_ws_server\t" # Specify this subprotocol is to be let through to websockethandle: WebSockets.addsubproto("websocket-testprotocol") + WebSockets.addsubproto("websocket-test-binary") # Tell HttpHandler which functions to spawn when something happens. httpha = HttpHandler(httphandle) httpha.events["error"] = ev_error @@ -73,6 +75,29 @@ function start_ws_server_async() server = Server(httpha, wsh ) clog(id, "Server to be started:\n", server ) servertask = @async run( server, 8080) - clog(id, "Server listening on localhost:8080\n") + clog(id, "Server listening on 127.0.0.1:8080\n") server end +"Closes websockets and server; other existing sockets, if any, remain open." +function closeall() + if isdefined(:WEBSOCKETS) + for va in values(WEBSOCKETS) + if isopen(va) + close(va) + end + end + if isdefined(:server) + close(server) + end + end +end +"Counts the number of open websocket in WEBSOCKETS dictionary" +function count_open_websockets() + count = 0 + for w in values(WEBSOCKETS) + if isopen(w) + count += 1 + end + end + count +end diff --git a/test/handler_functions_events.jl b/test/handler_functions_events.jl index 3cd2ad3..2f1bd37 100644 --- a/test/handler_functions_events.jl +++ b/test/handler_functions_events.jl @@ -6,6 +6,7 @@ end function ev_listen(port, args...) id = "events.ev_listen\t" #clog(id, :yellow, " from port ", :bold, port , :normal, " ", args..., " that was all I think. \n") + nothing end function ev_connect(client::Client, args...) id = "events.ev_connect\t" @@ -17,7 +18,7 @@ function ev_close(client::Client, args...) end function ev_write(client::Client, response::Response) id = "events.ev_write\t" - #clog(id, "to ",:yellow, client , :bold, client , :normal, "\n", response, "\n") + clog(id, "to ", :yellow, :bold, client , :normal, "\n", response, "\n") end function ev_reset(client::Client, response::Response) id = "events.ev_reset\t" diff --git a/test/handler_functions_websockets_general_test.jl b/test/handler_functions_websockets_general_test.jl index 9448eea..0248c16 100644 --- a/test/handler_functions_websockets_general_test.jl +++ b/test/handler_functions_websockets_general_test.jl @@ -3,20 +3,30 @@ function ws_general(ws::WebSockets.WebSocket) - id = "ws_general #$(ws.id)\t" + id = "ws_general $(ws.id)\t" WEBSOCKETS[ws.id] = ws RECEIVED_WS_MSGS[ws.id] = String[] - clog(id, " Entering to read websocket.\n") - stri = wsmsg_general(ws) - clog(id, " Send a message\n") - push!(RECEIVED_WS_MSGS[ws.id], stri) - writeto(ws.id, "Here, have a message!") - clog(id, " Continue to listen for message\n") + RECEIVED_WS_MSGS_LENGTH[ws.id] = Vector{Int64}() + RECEIVED_WS_MSGS_TIME[ws.id] = Vector{Float64}() + RECEIVED_WS_MSGS_ALLOCATED[ws.id] = Vector{Int64}() + sendmsg = "Welcome, general websocket. Our ref.: $(ws.id)" + clog(id, " Send: $sendmsg\n") while isopen(ws) - stri = wsmsg_general(ws) + stri = wsmsg_listen(ws) push!(RECEIVED_WS_MSGS[ws.id], stri) + clog(id, "Received: \n", :yellow, :bold, stri, "\n") + if startswith(stri, "Ping me!") + send_ping(ws) + sendmsg = "Your browser just got pinged (and presumably ponged back). Our ref.: $(ws.id)" + clog(id, " Sending: $sendmsg\n") + writeto(ws.id, sendmsg) + elseif startswith(stri, "ws1 echo: Your browser just got pinged ") + sendmsg = "Close, wait, and navigate to: browsertest2.html" + clog(id, " Sending: $sendmsg\n") + writeto(ws.id, sendmsg) + end end - clog(id, "Websocket was closed; exiting read loop\n") + clog(id, "Websocket $(ws.id) was closed; exits handler.\n") nothing end @@ -24,22 +34,26 @@ function writeto(wsid::Int, message) if haskey(WEBSOCKETS, wsid) write(WEBSOCKETS[wsid], message) end + return nothing end """ Listens for the next websocket message """ -function wsmsg_general(ws::WebSockets.WebSocket) - id = "wsmsg_general #$(ws.id)\t" - clog(id, " Entering to read websocket.\n") +function wsmsg_listen(ws::WebSockets.WebSocket) + id = "wsmsg_listen $(ws.id)\t" + clog(id, " Listening...\n") stri = "" + data = Vector{UInt8}() + t = 0.0 + allocbytes = 0 try - # Holding here. Cleanup code could work with InterruptException and Base.throwto. - # This is not considered necessary for the test (and doesn't really work well). - # So, this may continue running after the test is finished. - stri = ws|> read |> String - clog(id, "Received: \n", :yellow, :bold, stri, "\n") - # push! + # Holding here. + data , t, allocbytes = @timed ws|> read + push!(RECEIVED_WS_MSGS_LENGTH[ws.id], length(data)) + push!(RECEIVED_WS_MSGS_TIME[ws.id], t) + push!(RECEIVED_WS_MSGS_ALLOCATED[ws.id], allocbytes) + stri = data |> String catch e if typeof(e) == WebSockets.WebSocketClosedError clog(id, :green, " Websocket was or is being closed.\n") @@ -51,7 +65,6 @@ function wsmsg_general(ws::WebSockets.WebSocket) end end end - - clog(id, "Exiting\n") return stri end +return nothing \ No newline at end of file diff --git a/test/handler_functions_websockets_subprotocol_test.jl b/test/handler_functions_websockets_subprotocol_test.jl index eb1801c..3d66e5a 100644 --- a/test/handler_functions_websockets_subprotocol_test.jl +++ b/test/handler_functions_websockets_subprotocol_test.jl @@ -1,38 +1,102 @@ # These functions deal with specified websocket protocols. # Included in server_functions.jl + function ws_test_protocol(ws::WebSockets.WebSocket) - id = "ws_test_protocol #$(ws.id)\t" + id = "ws_test_protocol $(ws.id)\t" WEBSOCKETS[ws.id] = ws WEBSOCKETS_SUBPROTOCOL[ws.id] = ws + WEBSOCKETS[ws.id] = ws RECEIVED_WS_MSGS[ws.id] = String[] - clog(id, " Entering to read websocket.\n") - stri = wsmsg_general(ws) - clog(id, " Send a message\n") - push!(RECEIVED_WS_MSGS[ws.id], stri) - writeto(ws.id, "Here, have a message!") - clog(id, " Continue to listen for message\n") + RECEIVED_WS_MSGS_LENGTH[ws.id] = Vector{Int64}() + RECEIVED_WS_MSGS_TIME[ws.id] = Vector{Float64}() + RECEIVED_WS_MSGS_ALLOCATED[ws.id] = Vector{Int64}() + sendmsg = "Special welcome. Our ref.: $(ws.id)" + clog(id, " Sending: $sendmsg\n") + writeto(ws.id, sendmsg) while isopen(ws) - stri = wsmsg_testprotocol(ws) + stri = wsmsg_listen(ws) push!(RECEIVED_WS_MSGS[ws.id], stri) + clog(id, "Received: \n", :yellow, :bold, stri, "\n") + if startswith(stri, "Ping me!") + sendmsg = "No ping for you. Our ref.: $(ws.id). Will close on next received message." + clog(id, " Sending: $sendmsg\n") + writeto(ws.id, sendmsg) + elseif startswith(stri, "ws2 echo: No ping for you.") + clog(id, "Closing from server\n") + close(ws) + end end - clog(id, "Websocket was closed; exiting read loop\n") + clog(id, "Websocket on subprotocol $(ws.id) was closed; exits handler.\n") nothing end +function ws_test_binary(ws::WebSockets.WebSocket) + id = "ws_test_binary $(ws.id)\t" + WEBSOCKETS[ws.id] = ws + WEBSOCKETS_BINARY[ws.id] = ws + RECEIVED_WS_MSGS_LENGTH[ws.id] = Vector{Int64}() + RECEIVED_WS_MSGS_TIME[ws.id] = Vector{Float64}() + RECEIVED_WS_MSGS_ALLOCATED[ws.id] = Vector{Int64}() + width = Int16(0) + height = Int16(0) + byteperpixel = Int16(4) + ub = 0 + clog(id, " Handler is running \n") + while isopen(ws) + data = wsmsg_listen_binary(ws) + ub = length(data) + if ub == 6 + # Don't do this like this at home perhaps. Dealing with net endianness by reversing the order of bytes AND arguments.. + byteperpixel, height, width = reinterpret(Int16, reverse(data)) + clog(id, "Received 6 bytes = 3xInt16 custom header: \n\t\t\t\t\t" + , :yellow, " height: ", :bold, height + , :normal, :yellow, " width: ", :bold, width + , :normal, :yellow, " byteperpixel: ", byteperpixel, "\n") + elseif ub == Int(width) * height * byteperpixel + clog(id, "Received image data for manipulation, ", div(length(data), 1024), " kB\n") + tic() + ired = 1:4:ub + igreen = 2:4:ub + iblue = 3:4:ub + ialpha = 4:4:ub + itpquarter = 1:div(ub,4) + fill!(view(data, ialpha), 0xee) + fill!(view(data, iblue), 0xff) + fill!(view(data, intersect(itpquarter, ired)), 0x88) + rand!(view(data, ired), [0x00, 0x88, 0xff]) + hedata = UInt16.([height, width, 4]) + clog(id, "Manipulated image and made ready in $(toq()*1000) ms. \n\t\tSending header, then image.\n") + writeto(ws.id, reinterpret(UInt8, hedata)) + writeto(ws.id, data) + else + clog(id, "Received unexpected data: \t", :yellow, :bold, length(data), "-element ", typeof(data), "\n") + clog(id, "expected length: ", Int(width) * height * byteperpixel + , :yellow, " height: ", :bold, height + , :normal, :yellow, " width: ", :bold, width + , :normal, :yellow, " byteperpixel: ", byteperpixel, "\n") + end + end + clog(id, "Websocket on subprotocol $(ws.id) was closed; exits handler.\n") + nothing +end """ -Listens for the next websocket message. +Listens for the next binary websocket message """ -function wsmsg_testprotocol(ws::WebSockets.WebSocket) - id = "wsmsg_testprotocol #$(ws.id)\t" - clog(id, " Entering to read websocket.\n") - stri = "" +function wsmsg_listen_binary(ws::WebSockets.WebSocket) + id = "wsmsg_listen_binary $(ws.id)\t" + clog(id, " Binary listening...\n") + data = Vector{UInt8}() + t = 0.0 + allocbytes = 0 try # Holding here. Cleanup code could work with InterruptException and Base.throwto. # This is not considered necessary for the test (and doesn't really work well). # So, this may continue running after the test is finished. - stri = ws|> read |> String - clog(id, "Received: \n", :yellow, :bold, stri, "\n") + data , t, allocbytes = @timed ws|> read + push!(RECEIVED_WS_MSGS_LENGTH[ws.id], length(data)) + push!(RECEIVED_WS_MSGS_TIME[ws.id], t) + push!(RECEIVED_WS_MSGS_ALLOCATED[ws.id], allocbytes) catch e if typeof(e) == WebSockets.WebSocketClosedError clog(id, :green, " Websocket was or is being closed.\n") @@ -44,11 +108,7 @@ function wsmsg_testprotocol(ws::WebSockets.WebSocket) end end end - clog(id, "Exiting\n") - return stri + return data end - - - return nothing