Skip to content

Commit

Permalink
Change dependencies -> master (#94)
Browse files Browse the repository at this point in the history
* Use HTTP.jl (#87)

* Use HTTP.jl

* Support SSLContext

* Http.jl (#88)

* Use HTTP.jl

* Support SSLContext

* Get tests to pass

* Fix chat example

* examples/server.jl is working.

* Restrict tests to Julia v0.6 (v0.5 no longer supported).

* Almost done. Last test is nearly passing...

* Http.jl (#89)

* Use HTTP.jl

* Support SSLContext

* Get tests to pass

* Fix chat example

* examples/server.jl is working.

* Restrict tests to Julia v0.6 (v0.5 no longer supported).

* Almost done. Last test is nearly passing...

* Fix REQUIRE for appveyor / travis

* Add test/REQUIRE

* Update README, graceful close, add ping/pong. Temp tests. (#90)

* Update README

* Graceful close from client + run HTTP server HttpServer server simulataneously.

* Test ping, pong. Temp tests.

* new file:   examples/chat_explore.html
new file:   examples/chat_explore.jl

* modified:   appveyor.yml  - also test change_dependencies branch. Remove when merging to master.

* modified:   README.md - temporary badges for CI tests on appveyor.

* Http.jl (#92)

* Update README

* Graceful close from client + run HTTP server HttpServer server simulataneously.

* Test ping, pong. Temp tests.

* Add try, catch and close

Indent

WIP

* Fix String mask issue

* Minor: Fix an indent

* Update WebSockets.jl

Add a comment to remove the `copy` for v0.7.

* modified:   examples/chat_explore.jl - extended with HTTP server and a modifified upgrade function (get errors)

* Only copy String bytes if masked (#93)

* modified:   examples/chat_explore.jl - changed interface to gatekeeper, import functions where necessary.

* modified:   examples/chat_explore.html
modified:   examples/chat_explore.jl

* mod:    examples/chat-client.html
mod:    examples/chat_explore.html
mod:    examples/repl-client.html
mod:    test/browsertest.html
mod:    test/browsertest2.html
        - tightened html5 syntax, now enforced by Firefox
mod:    examples/chat_explore.jl
		- removed ad-hoc modification of WebSockets.upgrade
mod:    src/HTTP.jl
		- slightly quicker is_websocket_handshake, added comment
mod:    src/HttpServer.jl
		- slightly quicker is_upgrade, added comment
		- revised upgrade function, improved feedback on caught errors,
		  otherwise as previously in chat_explore.jl
		  This may be changed back again if we include more fields in the
		  WebSocket type.

* mod:   src/HTTP.jl
		Droppped some temporary debug code that remained by accident.
		Faster checking of
			Connection => "upgrade" || "keep alive, upgrade"
mod:   src/HttpServer.jl
		Faster checking of
			Connection => "upgrade" || "keep alive, upgrade"

* modified:   src/HTTP.jl    # Fix bug: HTTP.Request has no .status field.

* modified:   src/HTTP.jl        fixed last fix... Request-> Response of course.
                               upgrade: dropped calling handler taking the binary argument
modified:   src/HttpServer.jl  regexp matching "Connection => xxUPgradEx"

* 	modified:   src/HTTP.jl
	modified:   src/HttpServer.jl
	modified:   src/WebSockets.jl

* 	modified:   src/HTTP.jl       Expanced comment on 'upgrade', removed debug 'warn' lines, removed 'listen',
	                              removed 'binary' argument from functions upgrade and open.
	modified:   src/HttpServer.jl # Temporary comment on handshakes, removed double try-catch on close.
    modified:   src/WebSockets.jl # TODO comment on error handling

* 	modified:   README.md      Testing include a picture.
	new file:   examples/serve_verbose/svg/ws_neighborhood.svg

* mod:   README.md     Image experiment
mod:   examples/serve_verbose/svg/ws_neighborhood.svg  Smaller size

* modified:   README.md      Took away temporary network graph (github stylesheets mess with inlined svg)
modified:   src/HttpServer.jl  Reinstated try-catch after ci failure (this works locally)

* new file:   benchmark/REQUIRE			No direct effect, lists
										extra requirements for
										benchmark
new file:   benchmark/bce.html			Browser Client Echo definition
new file:   benchmark/benchmark.jl		Comment lines only, so far
new file:   benchmark/benchmark_prepare.jl
										Bandwidth tests, all clients
new file:   benchmark/favicon.ico		Tab icon for bce.html
new file:   benchmark/functions_benchmark.jl
										Included in benchmark_prepare.jl
new file:   benchmark/functions_open_browsers.jl
										Improved functionality, will replace
										test/functions_open_browsers.jl
new file:   benchmark/logs/benchmark_results_readable.log
										Manual copy-paste from generated
										benchmark_results.log
										...since the utf8-encoding to file
										is not working well.
new file:   benchmark/phantom.js		Definitions for phantomjs browser
new file:   benchmark/ws_hts.jl			Server for HTTP, websockets, bce.html
new file:   benchmark/ws_jce.jl			Julia Client Echo
new file:   logutils/log_http.jl		Included in logutils_ws, HTTP types
new file:   logutils/log_httpserver.jl	Included in logutils_ws, HttpServer types
new file:   logutils/log_ws.jl			Included in logutils_ws, WebSocket types
new file:   logutils/logutils_ws.jl		Logging utilities, included in
										benchmark_prepare.
modified:   src/HTTP.jl					Added help text examples.
										In open(), add own error handling
										(to be improved). upgrade() error
										handling is also temporary.
modified:   src/WebSockets.jl			Non-blocking read while closing.
										Added a reasonable closing handshake
										timeout
										Commented out WebSocketClosedError (this
										must be considered more): Breaks some test
										code.
										Rewriting comments (not finished)
										In read(ws), ignore most easy-to-trigger errors
										which have to do with opening / closing /
										scheduling/ browser behaviour.
modified:   test/runtests.jl			Sleep a little longer, CI is slow.

* modified:   benchmark/functions_benchmark.jl    Improved explanations,
                                                dropped dead code densityplot
modified:   benchmark/ws_hts.jl                 Added testing for pre-existing
                                                sockets.
modified:   benchmark/ws_jce.jl                 Added explanation for currently unused 'delay' code
modified:   examples/chat_explore.jl            Added reference to alternative close-down method

* Do not return control frames like ping.
Recurse to the next frame like in master.

modified:   src/WebSockets.jl

 Reintroduce recursion on control frames:376. Returning control codes
 would crash String(msg). Multi-frame messages are also possible.
 Add WebSocketClosedError messages :47, for underlying exceptions.
 Propagate unrecognized errors.

 Remove INFO message when closing. Readguarded() informs better.

 Added functions:
  readguarded          return tuple: data and success indication
                       incomplete messages are always empty
  writeguarded         return success indication
  subprotocol(request) common for Httpserver and HTTP
  target(request)      common for Httpserver and HTTP
  origin(request)      common for Httpserver and HTTP

modified:   src/HTTP.jl

 make upgrade(ws) call websocket handler with full request.
     Origin can now be determined, as per recommendations.
 call showerror with catch_stacktrace(). backtrace was less interesting.
 add method target(request)
 add method origin(request)
 add method subprotocol(request)
 add ServerWS
     WebsocketHandler
     serve(::ServerWS, etc..)
     The intententions is user code brevity, access to HTTP
     keyword options, more similar interface with HttpServer,
     can save the user from distinguishing Stream and Message.

modified:   src/HttpServer.jl

 add method target(request)
 add method origin(request)
 add method subprotocol(request)
 improve inline doc for WebSocketHandler

modified:   examples/chat_explore.jl
 demonstrate new functions, improve readability

modified:   benchmark/functions_benchmark.jl
 capture WebSocketClosedError with readguarded(ws)

modified:   logutils/log_httpserver.jl
 explicitly import Request and Response from HttpServer

modified:   test/functions_server.jl
 rephrase inline docs, use subprotocol(request)

modified:   test/runtests.jl
 not rely on pong returning read(ws) call

* 	modified:   src/WebSockets.jl    reinstate check for present mask with error message

* Status codes implemented for closing handshake

	modified:   benchmark/ws_hts.jl
isclosed -> !isopen

	modified:   src/HTTP.jl
remove dead code 'browserclient'::bool

	modified:   src/HttpServer.jl
reshuffle order of handshake checks, now similar to HTTP.jl

	modified:   src/WebSockets.jl
close a socket with handshake and 1002: ProtocolError when incorrect
mask received.
include status code for sending close
include received status codes for receiving close
update inline doc introduction
remove implemented TODO comments

* 	modified:   benchmark/logs/benchmark_results_readable.log
 document an overall reduction in bandwidths, 15% since last
 benchmark result commit. More than expected.

    modified:   src/HttpServer.jl
 bugfix remaining since last commit

    modified:   src/WebSockets.jl
 improve inline doc maskswitch!
 close: bugfix statuscode 0, use hton instead of reverse

    modified:   test/runtests.jl
 reintroduce unit tests from master, now including client
 add close status code test
 add varying message length

* Expand HttpServer tests to HTTP

    modified:   src/HTTP.jl
 change req.resource -> req.target

	modified:   test/runtests.jl
 add testset  "Test length typemax(UInt16) + 1"
 include HTTP in handshake testsets

* Unit tests 93%, excluding browsertests

	modified:   src/HTTP.jl
separate _openstream(..) from open for test access
	modified:   src/WebSockets.jl
future improvements
	modified:   test/runtests.jl
	deleted:    test/HTTP.jl
	new file:   test/client_server_test.jl
	new file:   test/client_test.jl
	new file:   test/error_test.jl
	new file:   test/frametest.jl
	new file:   test/handshaketest.jl

* 	modified:   src/WebSockets.jl
	dead code remove

* Add sleep(3) after start async server for travis-test
	modified:   test/client_test.jl
	modified:   test/error_test.jl

* Server channels for exceptions and traces
More tests

mod: src/WebSockets.jl
  export WebSocketClosedError
  close keyword argument 'freereason'
  received close handshake throws WebSocketClosedError
  improve criterion for bad mask error
  include reasons in forced close handshakes

mod: src/HTTP.jl
 use channels for error handling on server side
 removed invisible exception warnings in 'listen'

mod: benchmark/logs/benchmark_results_readable.log
add:   benchmark/logs/benchmark_results_readable_previous.log
   12% slower client side, 10% faster server side

mod: benchmark/ws_hts.jl
mod: benchmark/ws_jce.jl
  import clog_notime

mod: logutils/log_http.jl
mod: logutils/log_httpserver.jl
mod: logutils/log_ws.jl
mod: test/handler_functions_events.jl
 remove dead code, tabs

mod: test/client_server_test.jl
  wait for istaskstarted
mod: test/client_test.jl
 less console info, more sleep
mod: test/error_test.jl
 test all exceptions and exception interfaces

mod: test/frametest.jl
 add unknown opcodes, multi-frame message,
 bad mask errors, peerless close, close frames

mod: test/handshaketest.jl
 reduce console info
mod: test/runtests.jl
 add sleep and total group

* Info during tests, more sleeping
mod:   test/client_test.jl
mod:   test/error_test.jl
mod:   test/runtests.jl

* mod:   README.md          Large rewrite
mod:   src/WebSockets.jl  Add 'end' in example

* modified:   README.md            Another spin
modified:   src/HTTP.jl          Improve inline docs
modified:   src/WebSockets.jl    RSV1 compression bit remarks
  • Loading branch information
hustf authored Jun 6, 2018
1 parent c3da21f commit 5134187
Show file tree
Hide file tree
Showing 45 changed files with 6,562 additions and 678 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ os:
- linux
- osx
julia:
- 0.5
- 0.6
sudo: false
notifications:
Expand Down
206 changes: 149 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,184 @@
WebSockets.jl
=============
# WebSockets.jl


[![Build Status](https://travis-ci.org/JuliaWeb/WebSockets.jl.png)](https://travis-ci.org/JuliaWeb/WebSockets.jl)
[![Coverage Status](https://img.shields.io/coveralls/JuliaWeb/WebSockets.jl.svg)](https://coveralls.io/r/JuliaWeb/WebSockets.jl)

[![WebSockets](http://pkg.julialang.org/badges/WebSockets_0.5.svg)](http://pkg.julialang.org/?pkg=WebSockets&ver=0.5)
[![WebSockets](http://pkg.julialang.org/badges/WebSockets_0.6.svg)](http://pkg.julialang.org/?pkg=WebSockets&ver=0.6)

This is a server-side implementation of the WebSockets protocol in Julia. If you want to write a web app in Julia that uses WebSockets, you'll need this package.

This package works with [HttpServer.jl](https://github.com/JuliaWeb/HttpServer.jl), which is what you use to set up a server that accepts HTTP(S) connections.
Server and client side [Websockets](https://tools.ietf.org/html/rfc6455) protocol in Julia. WebSockets is a small overhead message protocol layered over [TCP](https://tools.ietf.org/html/rfc793). It uses HTTP(S) for establishing the connections.

## Getting started
WebSockets.jl must be used with either HttpServer.jl or HTTP.jl, but neither is a dependency of this package. You will need to first add one or both, i.e.:

```julia
julia> Pkg.add("HttpServer")
julia> Pkg.add("HTTP")
julia> Pkg.add("WebSockets")
```
### Open a client side connection
Client side websockets are created by calling `WebSockets.open` (with a server running). Client side websockets require [HTTP.jl](https://github.com/JuliaWeb/HttpServer.jl).

### Accept server side connections

Server side websockets are asyncronous [tasks](https://docs.julialang.org/en/stable/stdlib/parallel/#Tasks-1), spawned by either
[HttpServer.jl](https://github.com/JuliaWeb/HttpServer.jl) or HTTP.jl.

##### Using HttpServer
Call `run`, which is a wrapper for calling `listen`. See inline docs.

##### Using HTTP
Call `WebSockets.serve`, which is a wrapper for `HTTP.listen`. See inline docs.

## What does `WebSockets.jl` enable?

- reading and writing between entities you can program or know about
- low latency messaging
- implement your own 'if X send this, Y do that' subprotocols
- implement registered [websocket subprotocols](https://www.iana.org/assignments/websocket/websocket.xml#version-number)
- heartbeating, relaying
- build a network including browser clients
- convenience functions for gatekeeping with a common interface for HttpServer and HTTP
- writing http handlers and websockets 'handlers' in the same process can be an advantage. Exchanging unique tokens via http(s)
before accepting websockets is recommended for improved security.

WebSockets are well suited for user interactions via a browser. By calling compiled Javascript functions in browsers and using parallel workers,
user interaction and graphics workload, even development time can be moved off Julia resources.

The /logutils folder contains some logging functionality that is quite fast and can make working with multiple asyncronous tasks easier. This functionality may be moved out of WebSockets in the future, depending on how other logging capabilities develop.

You should also have a look at Julia packages [DandelionWebSockets](https://github.com/dandeliondeathray/DandelionWebSockets.jl) or the implementation currently part of HTTP.jl.

## What are the main downsides to WebSockets (in Julia)?

- Logging. We need customizable and very fast logging for building networked applications.
- Security. Julia's Http(s) servers are currently not working to our knowledge.
- Non-compliant proxies on the internet, company firewalls. Commercial applications often use competing technologies for this reason, according to some old articles at least. HTTP.jl lets you use such techniques.
- 'Warm-up', i.e. compilation when a method is first used. These are excluded from current benchmarks.
- Garbage collection, which increases message latency at semi-random intervals. See benchmark plots.
- If a connection is closed improperly, the connection task will throw uncaught ECONNRESET and similar messages.
- TCP quirks, including 'warm-up' time with low transmission speed after a pause. Heartbeats can alleviate.
- Neither HTTP.jl or HttpServer.jl are made just for connecting WebSockets. You may need strong points from both.
- The optional dependencies increases load time compared to fixed dependencies.
- Since 'read' is a blocking function, you can easily end up reading indefinetely from both sides.

As a first example, we can create a WebSockets echo server:
## Server side example

As a first example, we can create a WebSockets echo server. We use named function arguments for more readable stacktraces while debugging.

```julia
using HttpServer
using WebSockets

wsh = WebSocketHandler() do req,client
while true
msg = read(client)
write(client, msg)
function coroutine(ws)
while isopen(ws)
data, = readguarded(ws)
s = String(data)
if s == ""
break
end
println(s)
if s[1] == "P"
writeguarded(ws, "No, I'm not!")
else
writeguarded(ws, "Why?")
end
end
end
end

server = Server(wsh)
run(server,8080)
```
function gatekeeper(req, ws)
if origin(req) == "http://127.0.0.1:8080" || origin(req) == "http://localhost:8080"
coroutine(ws)
else
println(origin(req))
end
end

This sets up a server running on localhost, port 8080.
It will accept WebSockets connections.
The function in `wsh` will be called once per connection; it takes over that connection.
In this case, it reads each `msg` from the `client` and then writes the same message back: a basic echo server.
handle(req, res) = Response(200)

The function that you pass to the `WebSocketHandler` constructor takes two arguments:
a `Request` from [HttpCommon.jl](https://github.com/JuliaWeb/HttpCommon.jl/blob/master/src/HttpCommon.jl#L142),
and a `WebSocket` from [here](https://github.com/JuliaWeb/WebSockets.jl/blob/master/src/WebSockets.jl#L17).
server = Server(HttpHandler(handle),
WebSocketHandler(gatekeeper))

## What can you do with a `WebSocket`?
You can:
run(server, 8080)
```

* `write` data to it
* `read` data from it
* send `ping` or `pong` messages
* `close` the connection
Now open a browser on http://127.0.0.1:8080/ and press F12. In the console, type the lines following ≫:
```javascript
≫ws = new WebSocket("ws://127.0.0.1:8080")
WebSocket { url: "ws://127.0.0.1:8080/", readyState: 0, bufferedAmount: 0, onopen: null, onerror: null, onclose: null, extensions: "", protocol: "", onmessage: null, binaryType: "blob" }
ws.send("Peer, you're lying!")
undefined
ws.onmessage = function(e){console.log(e.data)}
function onmessage()
≫ws.send("Well, then.")
← undefined
Why? debugger eval code:1:28
```

## Installation/Setup
If you now navigate or close the browser, this happens:
1. the client side of the websocket connection will quickly send a close request and go away.
2. Server side `readguarded(ws)` has been waiting for messages, but instead closes 'ws' and returns ("", false)
3. `coroutine(ws)` is finished and the task's control flow returns to HttpServer
4. HttpServer does nothing other than exit this task. In fact, it often crashes because
somebody else (the browser) has closed the underlying TCP stream. If you had replaced the last Julia line with '@async run(server, 8080', you would see some long error messages.
5. The server, which spawned the task, continues to listen for incoming connections, and you're stuck. Ctrl + C!

~~~julia
julia> Pkg.add("WebSockets")
~~~
You could replace 'using HttpServer' with 'using HTTP'. Also:
Serve -> ServeWS
HttpHandler -> HTTP.Handler
WebSocketHandler -> WebSockets.WebsocketHandler

At this point, you can use the examples below to test that it all works.

## [Chat client/server example](https://github.com/JuliaWeb/WebSockets.jl/blob/master/examples/chat.jl):
## Client side

1. Move to the `~/.julia/<version>/WebSockets` directory
2. Run `julia examples/chat.jl`
3. In a web browser, open `localhost:8000`
4. You should see a basic IRC-like chat application
You need to use [HTTP.jl](https://github.com/JuliaWeb/HttpServer.jl).

What you can't do is use a browser as the server side. The server side can be the example above, running in an asyncronous task. The server can also be running in a separate REPL, or in a a parallel task. The benchmarks puts the `client` side on a parallel task.

## Echo server example:
The following example
- runs server in an asyncronous task, client in the REPL control flow
- uses [Do-Block-Syntax](https://docs.julialang.org/en/v0.6.3/manual/functions/#Do-Block-Syntax-for-Function-Arguments-1), which is a style choice
- the server `ugrade` skips checking origin(req)`
- the server is invoked with `listen(..)` instead of `serve()`
- read(ws) and write(ws, msg) instead of readguarded(ws), writeguarded(ws)

~~~julia
using HttpServer
```julia

using HTTP
using WebSockets

wsh = WebSocketHandler() do req,client
while true
msg = read(client)
write(client, msg)
const PORT = 8080

# Server side
@async HTTP.listen("127.0.0.1", PORT) do http
if WebSockets.is_upgrade(http.message)
WebSockets.upgrade(http) do req, ws
while isopen(ws)
msg = String(read(ws))
write(ws, msg)
end
end
end
end
end

sleep(2)


WebSockets.open("ws://127.0.0.1:$PORT") do ws
write(ws, "Peer, about your hunting")
println("echo received:" * String(read(ws)))
end
```

The output in a console session is barely readable, which is irritating. To build real-time applications, we need more code.

Some logging utilties for a running relay server are available in /logutils.




server = Server(wsh)
run(server,8080)
~~~

To play with a WebSockets echo server, you can:

1. Paste the above code in to the Julia REPL
2. Open `localhost:8080` in Chrome
3. Open the Chrome developers tools console
4. Type `ws = new WebSocket("ws://localhost:8080");` into the console
5. Type `ws.send("hi")` into the console.
6. Switch to the 'Network' tab; click on the request; click on the 'frames' tab.
7. You will see the two frames containing "hi": one sent and one received.

~~~~
::::::::::::::::
Expand Down
7 changes: 2 additions & 5 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
julia 0.5
Compat 0.28.0
HttpCommon
HttpServer
Codecs
julia 0.6
MbedTLS
Requires
7 changes: 3 additions & 4 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe"
# HttpCommon not building yet - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
# HttpCommon not building yet - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
branches:
only:
- change_dependencies
- master
- /release-.*/

Expand Down Expand Up @@ -35,7 +34,7 @@ build_script:
- IF EXIST .git\shallow (git fetch --unshallow)
- ps: |
Write-Host "This is PowerShell - STDERR output will be red. Redirect! "
$env:PATH+=";C:\projects\julia\bin\"
$env:PATH+=";C:\projects\julia\bin\"
julia -e 'versioninfo();redirect_stderr(STDOUT);println(STDOUT, \"stdout\"); println(STDERR, \"stderr\")'
julia -e 'redirect_stderr(STDOUT);Pkg.init()'
julia --depwarn=no -e 'redirect_stderr(STDOUT);Pkg.add(\"HttpServer\");using HttpServer;'
Expand All @@ -44,4 +43,4 @@ build_script:
test_script:
- ps: |
Write-Host "This is PS"
julia -e 'redirect_stderr(STDOUT);info(\"Local websockets directory:\", Pkg.dir(\"WebSockets\"));Pkg.test(\"WebSockets\")'
julia -e 'redirect_stderr(STDOUT);info(\"Local websockets directory:\", Pkg.dir(\"WebSockets\"));Pkg.test(\"WebSockets\")'
5 changes: 5 additions & 0 deletions benchmark/REQUIRE
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Being placed in the benchmark folder, this file has no effect on Julia.
# To run benchmarks, you may need to Pkg.add("..package below...")
HTTP
IndexedTables
UnicodePlots
97 changes: 97 additions & 0 deletions benchmark/bce.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>WS text</title>
</head>
<body>
<p>BCE echoing websocket.
</p>
<ul>
<li> ws1 </li>
</ul>
<p>|
Initiates a websocket connection.
For every received websocket message, sends one empty message and then the received message. The websocket is closed by
the server, or when user navigates away.<br>
<p>
<p id = "init"></p>
<p>&nbsp;&nbsp;This is <b id = "browserid"> ... </b></p>
<div id = "ws1" style="border:thick solid black;"><p>ws1 Websocket</p></div>
<script>

window.onload= function(){
plog("init", "<p>:window.onload</p>");
ws1 = addwebsocket("ws1");
}

// log to DOM element ws
function plog(ws, shtm){
document.getElementById(ws).innerHTML += shtm
}

function addwebsocket(instancename, subprotocol){
var wsuri = document.URL.replace("http:","ws:");
if (typeof subprotocol === "undefined") {
var ws = new WebSocket(wsuri)
} else {
var ws = new WebSocket(wsuri, subprotocol)
}
ws.mynam = instancename;
ws.onclose = function(e){
plog(e.target.mynam, "<p>: " + e.target.mynam + ".onclose:" +
"wasClean: " + e.wasClean + "; " +
"code: " + e.code + "; " + codeDesc[e.code] + "; " +
"reason: " + e.reason + "; " +
"<br>&nbsp;&nbsp;Websocket state is now " + e.target.readyState +
" " + readystateDesc[e.target.readyState] + ".</p>");
}
ws.onerror = function(e){
plog(e.target.mynam, "<p>: " + e.target.mynam + ".onerror: " +
"<br>&nbsp;&nbsp;Websocket state is now " + e.target.readyState +
" " + readystateDesc[e.target.readyState] + ".</p>");
}
ws.onopen = function(e){
ws.binaryType = "arraybuffer";
plog(e.target.mynam, "<p>: " + e.target.mynam + ".onopen: " +
"<br>&nbsp;&nbsp;Websocket state is now " + e.target.readyState +
" " + readystateDesc[e.target.readyState] +
" reading messages as binary arraybuffers"
)
}
ws.onmessage = function (e){
var msg = e.data;
ws.send("")
ws.send(msg)
}
plog(instancename, "<p>" + instancename + " created with event handlers.</p>");
return ws
} // addwebsocket


var codeDesc ={1000:"Normal",
1001:"Going Away",
1002:"Protocol Error",
1003:"Unsupported Data",
1004:"Reserved",
1005:"No Status Recvd- reserved",
1006:"Abnormal Closure- reserved",
1007:"Invalid frame payload data",
1008:"Policy Violation",
1009:"Message too big",
1010:"Missing Extension",
1011:"Internal Error",
1012:"Service Restart",
1013:"Try Again Later",
1014:"Bad Gateway",
1015:"TLS Handshake"};

var readystateDesc ={0:"CONNECTING",
1:"OPEN",
2:"CLOSING",
3:"CLOSED"};
</script>
</body>
</html>
Loading

0 comments on commit 5134187

Please sign in to comment.