Giter Club home page Giter Club logo

websockets.jl's Introduction

WebSockets.jl

Coverage Status Appveyor

Server and client side Websockets protocol in Julia. WebSockets is a small overhead message protocol layered over TCP. It uses HTTP(S) for establishing the connections.

Upgrading to v. 1.6

Julia 1.8.2 or higher is now required due to some instabilities.

There are minor 'public API' changes in v. 1.6. We advise 'using' each function like below, except when experimenting.

This example tries typical 'old' code, shows errors, and shows replacement code.

julia> using WebSockets: serve, writeguarded, readguarded, @wslog, open, 
                  HTTP, Response, ServerWS, with_logger, WebSocketLogger
julia> begin
           function handler(req)
               @wslog "Somebody wants a http response"
               Response(200)
           end
           function wshandler(ws_server)
               @wslog "A client opened this websocket connection"
               writeguarded(ws_server, "Hello")
               readguarded(ws_server)
           end
           serverWS = ServerWS(handler, wshandler)
           servetask = @async with_logger(WebSocketLogger()) do
               serve(serverWS, port = 8000)
               "Task ended"
           end
       end
[ Info: Listening on: 127.0.0.1:8000
Task (runnable) @0x000001921cbd2ca0

The above would work on earlier versions. But now test in a browser: http://127.0.0.1:8000. The browser would show: Server never wrote a response, and the REPL would show:

julia> [ Wslog 11:08:09.957: Somebody wants a http response
[ Wslog 11:08:10.078: Somebody wants a http response

We had two requests from the browser - one was for the 'favicon' of our site. But something went wrong here. If you like long stacktraces, also try HTTP.get("http://127.0.0.1:8000");

Let's revise the http handler to match the new requirements:

julia> function handler(req)
               @wslog "HTTP.jl v1.0+ requires more of a response"
               Response(200, "Nothing to see here!")
       end

Reload the browser page to verify the server is updated and working!

Let us test the websockets!

julia> open("ws://127.0.0.1:8000") do ws_client
                  data, success = readguarded(ws_client)
                  if success
                      println(stderr, ws_client, " received: ", String(data))
                  end
              end;
[ LogLevel(50): A client opened this websocket connection
WebSocket(client, CONNECTED) received: Hello

That's it, we have upgraded by simply modifing the Response constructors. The websocket was closed at exiting the handler, and to close the running server:

julia> put!(serverWS.in, "close!")
[ Info: Server on 127.0.0.1:8000 closing
"close!"

julia> servetask
Task (done) @0x000001d6457a1180

Access inline documentation and have a look at the examples folder! The testing files also demonstrate a variety of uses. Benchmarks show examples of websockets and servers running on separate processes, as oposed to asyncronous tasks.

About this package

Originally from 2013 and Julia 0.2, the WebSockets API has remained largely unchanged. It now depends on HTTP.jl for establishing the http connections. That package is in ambitious development, and most functionality of this package is already implemented directly in HTTP.jl.

This more downstream package may lag behind the latest version of HTTP.jl, and in so doing perhaps avoid some borderline bugs. This is why the examples and tests do not import HTTP methods directly, but rely on the methods imported in this package. E.g. by using WebSockets.HTTP.listen instead of HTTP.listen you may possibly be using the previous release of package HTTP. The imported HTTP version is capped so as to avoid possible issues when new versions of HTTP are released.

We aim to replace code with similar code in HTTP when possible, reducing this package to a wrapper. Ideally, all top-level tests will continue to pass without change.

What can you do with it?

  • read and write between entities you can program or know about
  • serve an svg file to the web browser, containing javascript for connecting back through a websocket, adding two-way interaction with graphics
  • enjoy very low latency and high speed with a minimum of edge case coding
  • implement your own 'if X send this, Y do that' subprotocols. Typically, one subprotocol for sensor input, another for graphics or text to a display.
  • use registered websocket subprotocols for e.g. remote controlled hardware
  • relay user interaction to backend simulations
  • build a network including browser clients and long-running relay servers
  • use convenience functions for gatekeeping

WebSockets are well suited for user interactions via a browser or cross-platform applications like electron. Workload and development time can be moved off Julia resources, error checking code can be reduced. Preferably use websockets for passing arguments, not code, between compiled functions on both sides; it has both speed and security advantages over passing code for evaluation.

Other tips

  • Putting http handlers and websocket coroutines ('handlers') in the same process can be a security advantage. It is good practice to modify web page responses to include time-limited tokens in the address, the wsuri.
  • Since read and readguared are blocking functions, you can easily end up reading indefinitely from any side of the connection. See the close function code for an example of non-blocking read with a timeout.
  • Compression is not currenlty implemented, but easily adaptable. On local connections, there's probably not much to gain.
  • If you worry about milliseconds, TCP quirks like 'warm-up' time with low transmission speed after a pause can be avoided with heartbeats. High-performance examples are missing.
  • Garbage collection increases message latency at semi-random intervals, as is visible in benchmark plots. Benchmarks should include non-memory-allocating examples.
  • Time prefixes in e.g. @wslog are not accurate. To accurately track sequences of logging messages, include the time in your logging message, e.g. using 'time_ns()'
Debugging with WebSockets.ServeWS servers

Error messages from run-time are directed to a .out channel. See inline docs: ?Websockets.serve. When using readguarded or writeguarded, errors are logged with @debug statements. Set the logging level of the logger you use to 'Debug', as in 'examples/count_with_logger.jl'.

Debugging with WebSockets.HTTP.listen servers

If you prefer to write your own server coroutine with this approach, error messages may be sent as messages to the client. This may not be good practice if you're serving pages to the internet, but very nice while developing locally. There are some inline comments in the source code which may be of help.

Development, new features, comments

The issues section is used for planning development: Contributions are welcome.

  • Version 1.6 makes necessary changes to use HTTP 1.1.0 and limits the Julia versions to 1.8.2+.
  • Version 1.5 shows the current number of connections on ServerWS. ServerWS in itself is immutable.
  • Version 1.4 removes a ratelimiter function.
  • Version 1.3 integrates WebSocketLogger. It closely resembles ConsoleLogger from the Julia standard library. Additional features: see inline docs and 'examples/count_with_logger.jl'. With this closer integration with Julia's core logging functionality, we also introduce @debug statements in readguarded and writeguarded (as well as when receiving 'ping' or 'pong'). The functions still return a boolean to indicate failure, but return no reason except the logger messages.
  • The /benchmark folder contain some code that is not currently working, pending logging facilities.
  • Alternative Julia packages: DandelionWebSockets and the direct implementation in HTTP.jl.

Errors after updating?

To version 1.6

Updated to use HTTP 1.1.0-1.5 as a dependency.

In your code: Response(200) -> Response(200, "OK") Also see the example at the top.

To version 1.5.6

Updated to use HTTP 0.9 as a dependency.

To version 1.5.2/3

Julia 0.7 is dropped from testing, but the compatibility as stated in 'Project.toml' is kept, since HTTP is also claiming to be 0.7 compatible and we do not want to put too many restraints on the compatibility graph. The non-compatibility is that @wslog will not quite work.

To version 1.5.2

WebSockets.DEFAULTOPTIONS has changed to WebSockets.default_options() The previous behaviour is considered a bug, and might result in close(s1::ServerWS) or put!(s1::ServerWS.in, "close") also closing s2::ServerWS.

To version 1.5.0

If you don't call serve(::ServerWS, etc,) but write your own code including 'listen':

The 'listen... do' syntax example is removed. You now need to wrap the handler function: handler(req) = WebSockets.Response(200) handler_wrap = WebSockets.RequestHandlerFunction(handler)

The function that accepts RequestHandlerFunction is called handle. It replaces handle_request, which was more accepting.

Consider taking keyword option values from the new function WebSockets.default_options()

If you call WebSockets.serve(::ServerWS, etc,):

There are no changes if you're using syntax like examples/minimal_server.jl.

Keywords 'cert' and 'key' are no longer accepted. Instead, make sure you're using the same version of MbedTLS as WebSockets.HTTP this way:

sslconf = WebSockets.SSLConfig(cert, key)
ServerWS(h,w, sslconfig = sslconf)

The upgrade to using HTTP 0.8 changes the bevaviour of server options. Try not passing any options to ServerWS. If you do, they will overrule the list of options in WebSockets.DEFAULTOPTIONS.

Type ServerOptions is removed and the corresponding fields now reside in ServerWS.

The optional function 'tcpisvalid' used to take two arguments; it should now take only one.

Ratelimiting is now performed outside of optional user functions, if you pass keyword rate_limit โ‰  nothing.

Keyword logger is no longer supported. For redirecting logs, use Logging.with_logger

To version 1.4.0

We removed the default ratelimit! function, since the way it worked was counter-intuitive and slowed down most use cases. If you have not provided any ratelimit to SererOptions in the past, you may be able to notice a very tiny performance improvement. See issue #124 and the inline documentation.

To version 1.3.0

WebSockets additionaly exports WebSocketLogger, @wslog, Wslog.

To version 1.1.0

This version is driven by large restructuring in HTTP.jl. We import more functions and types into WebSockets, e.g., WebSockets.Request. The main interface does not, intentionally, change, except for 'origin', which should now be qualified as WebSockets.origin.

To version 0.5.0

The introduction of client side websockets to this package in version 0.5.0 may require changes in your code:

  • The WebSocket.id field is no longer supported. You can generate unique counters by code similar to 'bencmark/functions_open_browsers.jl' COUNTBROWSER.
  • You may want to modify you error handling code. Examine WebSocketsClosedError.message.
  • You may want to use readguarded and writeguarded to save on error handling code.
  • Server -> WebSockets.WSServer
  • WebSocketHandler -> WebSockets.WebsocketHandler (or just pass a function without wrapper)
  • HttpHandler-> HTTP.HandlerFunction (or just pass a function without wrapper)
  • run -> serve
  • Response -> HTTP.Response
  • Request -> HTTP.Response

You may also want to consider using target, orginand subprotocol, which are compatible with both of the types above.

::::::::::::::::
::            ::
::  Made at   ::
::            ::
::::::::::::::::
       ::
 Recurse Center
::::::::::::::::

websockets.jl's People

Contributors

albestro avatar astrieanna avatar aviks avatar bauglir avatar cmcaine avatar cmey avatar dcjones avatar despeset avatar ericforgy avatar hustf avatar iagobaapellaniz avatar iainnz avatar jebej avatar jiahao avatar juliatagbot avatar keno avatar malmaud avatar mikeinnes avatar quinnj avatar ranjanan avatar rened avatar rohitvarkey avatar shashi avatar simondanisch avatar staticfloat avatar stefankarpinski avatar westleyargentum avatar widged avatar wildart avatar zachallaun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

websockets.jl's Issues

Random sockets not opening

The randomness makes this hard to document, but it seems a httpsocket sometimes get assigned the same number and one of them basically stalls. For the current version of tests, the number of simultaneous sockets has been reduced to alleviate the problem.

This functionality comes from HtttpServer, which currently has some deprecation warnings and may have slower reaction than normally.

Of course, to debug, one needs to temporarily add some logs in HttpServer. But such logging takes more time than just opening a socket and is likely to increase the problem.

It may seem to be less of a problem on cygwin / julia compiled with 8 threads than on the downloaded binary. HttpServer opens sockets as async tasks, not threads or processes.

Memory Leaks

Hi,

I am trying to get this working, but figured out that the example might create memory leaks. I think the problem refers to Julia, since the while loop would not allow the garbage collector to invoke properly.
In consequence Julia memory usage will increase continously.

This could be avoided by adding a gc() inside the loop, but this also impacts performance.

using HttpServer
using WebSockets

wsh = WebSocketHandler() do req,client
    while true
        gc() # Explicit invocation of Julia's garbage collector
        msg = read(client)
        write(client, msg)
    end
  end

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

Are there other possibilities to code this in Julia, e.g. by using a callback?

Thanks,
Daniel

Path is too specific in /examples/server.jl

ERROR: could not open file ./examples/repl-client.html
 in open at io.jl:312
 in open at io.jl:332
 in readall at io.jl:207
 in include at boot.jl:238

Should generalize line 25 of server.jl

onepage = readall("./examples/repl-client.html")

Tag a new version with 0.4 compat fixes?

Maybe it is time to tag a new version so that new users on Julia 0.4 have better out-of-box experience? Current version you get from Pkg.add("WebSockets") produces some warnings on load, but all them are already fixed on master.

Improve test logs

Current test logs are quite verbose and prints to REPL only.
The summary is a bit misleading:

  • The presented averages are the average taken over messages. It may be better to present the performance min /max/average per message length.
  • Read times include waiting for sockets to open (htttpserver) and also javascript processing time.

Fix badges, also appveyor logs

It should be clear if badges refer to master or tagged version. Have a look at examples.

While a pull request is open, appveyor (windows) test logs are open, but there is no access (?) to logs after a pull requested is merged. This is ok for travis.

This is missed because the windows tests cover more browsers and hence could possibly use more initalization time.

IOString

I had to change IOString to IOBuffer to get the example repl-client to work in Julia 0.3.3. Just FYI

Error Handling

A major thing that WebSockets.jl currently lacks is a good way to generally communicate when things go wrong to the user-application.

Sometimes, we should fail the handshake (by sending 400 Bad Request), but the functions aren't set up to pass the knowledge of the failure back up.

Part of this is also communicating when a connection is being closed. We may need to close the WebSocket at any time (due to, for example, the other end sending an invalid frame). We would like to let the application find out why the WebSocket closed, if it wants to. The other question is what to do if the socket closes when we're in the middle of reading/writing a data message for the user. Should we stop in the middle? For reading, this is obviously yes, and the question becomes what to do with the partial message -- do we give it to the application or just drop it?

WebSocket Client

We have a server so how about a client?

Would this be easy to implement?

Add status code to close

Close messages should include a 2-byte status code in the body, if possible. Currently, the close function does not accept an argument to select the error code. It should be changed to accept a UInt8.

Non-blocking Read

Apologies if this is already supported and I have to admit that my network programming is a bit rusty, but as far as I can tell there is no way to perform a non-blocking read in WebSockets.jl.

using with ProtoBuf.jl

I want to send and receive data using protobuf.jl. The readproto(IO,type) and writeproto(IO,type) writes to a IO stream. I thought I could use the websocket for this but can't get it to work, neither with:

writeproto(client.socket.buffer,mytype()) or
writeproto(client.socket,mytype())

The only way I get it to work now is this uglyhack:

ion = PipeBuffer()
while true
    msg = read(client)
    write(iob,msg)
    test = readproto(iob,mytype())
    print(test)
    writeproto(iob,mytype())
    write(client,read(iob))
end

what I am trying to get working is:

while true
    test = readproto(client,mytype())
    print(test)
    writeproto(client,mytype())
end

Also, is anyone working on wss protocol?

Many thanks for any info and help

Convert in-file comments to 0.4 docs

Instead of comments, we should convert to the new documentation stuff. This could be an opportunity to add usage examples to the documentation for each function.

VERSION < v"0.4-" && using Docile

@doc doc"Documentation goes here."
function ping(ws::WebSocket)
end

Integrate w/ HTTP.jl

HTTP.jl is the consolidated, modernized, and currently actively maintained package for web functionality (uri parsing, content type detection, cookie handling, client requests, basic server functionality). It'd be great to have all the great work @hustf has done w/ this package lately work w/ that. Happy to discuss how to make that as easy as possible.

The version 0.3.3 is still buggy to binary data

I don't know why, but in the julia version 0.3.3, when I do "Pkg.add("WebSockets") I still get the older version, without the fix to accept binary data. When I manually copy the current version over the older, it works.

[PkgEval] WebSockets may have a testing issue on Julia 0.4 (2014-08-16)

PackageEvaluator.jl is a script that runs nightly. It attempts to load all Julia packages and run their tests (if available) on both the stable version of Julia (0.3) and the nightly build of the unstable version (0.4). The results of this script are used to generate a package listing enhanced with testing results.

On Julia 0.4

  • On 2014-08-15 the testing status was Tests pass.
  • On 2014-08-16 the testing status changed to Package doesn't load.

Tests pass. means that PackageEvaluator found the tests for your package, executed them, and they all passed.

Package doesn't load. means that PackageEvaluator did not find tests for your package. Additionally, trying to load your package with using failed.

This issue was filed because your testing status became worse. No additional issues will be filed if your package remains in this state, and no issue will be filed if it improves. If you'd like to opt-out of these status-change messages, reply to this message saying you'd like to and @IainNZ will add an exception. If you'd like to discuss PackageEvaluator.jl please file an issue at the repository. For example, your package may be untestable on the test machine due to a dependency - an exception can be added.

Test log:

>>> 'Pkg.add("WebSockets")' log
INFO: Installing BinDeps v0.3.0
INFO: Installing Calendar v0.4.2
INFO: Installing Codecs v0.1.2
INFO: Installing FactCheck v0.1.2
INFO: Installing GnuTLS v0.0.1
INFO: Installing HttpCommon v0.0.5
INFO: Installing HttpParser v0.0.9
INFO: Installing HttpServer v0.0.7
INFO: Installing ICU v0.4.1
INFO: Installing Nettle v0.1.4
INFO: Installing SHA v0.0.2
INFO: Installing URIParser v0.0.2
INFO: Installing WebSockets v0.0.6
INFO: Building ICU
=================================[ ERROR: ICU ]=================================

None of the selected providers can install dependency icu.
Use BinDeps.debug(package_name) to see available providers

while loading /home/idunning/pkgtest/.julia/v0.4/ICU/deps/build.jl, in expression starting on line 28

================================================================================
INFO: Building Nettle
INFO: Building GnuTLS
INFO: Building HttpParser

================================[ BUILD ERRORS ]================================

WARNING: ICU had build errors.

 - packages with build errors remain installed in /home/idunning/pkgtest/.julia/v0.4
 - build a package and all its dependencies with `Pkg.build(pkg)`
 - build a single package by running its `deps/build.jl` script

================================================================================
INFO: Package database updated
INFO: METADATA is out-of-date a you may not have the latest version of WebSockets
INFO: Use `Pkg.update()` to get the latest versions of your packages
 - Library "libhttp_parser"


>>> 'using WebSockets' log
ERROR: could not open file /home/idunning/pkgtest/.julia/v0.4/ICU/src/../deps/deps.jl
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:54
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:54
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:54
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:51
 in include at ./boot.jl:245
 in include_from_node1 at loading.jl:128
 in process_options at ./client.jl:285
 in _start at ./client.jl:354
 in _start_3B_3500 at /home/idunning/julia04/usr/bin/../lib/julia/sys.so
while loading /home/idunning/pkgtest/.julia/v0.4/ICU/src/ICU.jl, in expression starting on line 54
while loading /home/idunning/pkgtest/.julia/v0.4/Calendar/src/Calendar.jl, in expression starting on line 1
while loading /home/idunning/pkgtest/.julia/v0.4/HttpCommon/src/HttpCommon.jl, in expression starting on line 3
while loading /home/idunning/pkgtest/.julia/v0.4/WebSockets/src/WebSockets.jl, in expression starting on line 3
while loading /home/idunning/pkgtest/.julia/v0.4/WebSockets/testusing.jl, in expression starting on line 1


>>> test log
no tests to run
>>> end of log

Change_dependencies feedback

Due to the complexity of supporting both HTTP and HttpServer, we liberally merge PRs to this branch for easier experimentation. There's also issue #84, but that doesn't need to be cluttered with 'caps and tabs' details.

'Code review' and TO DO comments go here.

I'm working on a file-by-file list, but this is the most core. On branches HTTP/master and Websockets/Change_dependencies.

julia> begin
           using HTTP
           using WebSockets
           port = 8000
           @async HTTP.listen("127.0.0.1",UInt16(port)) do http
                  if WebSockets.is_upgrade(http.message)
                      WebSockets.upgrade(http) do ws
                          while ws.state == WebSockets.CONNECTED
                              msg = String(read(ws))
                              println("Echoing $msg") # Write the received message to the REPL
                              write(ws,msg)
                          end
                      end
                  end
            end
            sleep(2)
            WebSockets.open("ws://127.0.0.1:$(port)") do ws
                   write(ws, "Foo")
                   write(ws, "Bar")
                   println("Got back ", String(read(ws)) )
                   println("Got back ", String(read(ws)))
                   close(ws)
           end
       end
I- Listening on: 127.0.0.1:8000
I- Accept:  ๐Ÿ”—    0โ†‘     0โ†“    127.0.0.1:8000:8000 โ‰ฃ16
Echoing Foo
Got back Foo
Echoing Bar
Got back Bar
INFO: Server received OPCODE_CLOSE
Echoing
HTTP.MessagesE- .Error:   ๐Ÿ’€    1โ†‘     1โ†“๐Ÿ”’   127.0.0.1:8000:8000 โ‰ฃ16Response
:|
e = """read: connection reset by peer (ECONNRESET)

HTTP/1.1 101 Switching Protocols
|  Upgrade: websocket
catch_stacktrace() = Connection: Upgrade
StackFrame[]Sec-WebSocket-Accept: aWCLPwDjhD4k2F6In03w96kczvs=


I- """Closed:  ๐Ÿ’€    1โ†‘     1โ†“๐Ÿ”’   127.0.0.1:8000:8000 โ‰ฃ16

ERROR: SHA1 not defined

Every time I try to connect to the basic echo server example, I get the following... (using 0.2 on Windows 7 64bit)

*ERROR: SHA1 not defined *

Code as follow

using HttpServer
using WebSockets

wsh = WebSocketHandler() do req,client
    while true
        msg = read(client)
        write(client, msg)
    end
end

serv = Server(wsh)
run(serv, 8081)
C:\juliatest>julia server.jl
Listening on 8081...

ERROR: SHA1 not defined
 in websocket_handshake at C:\Users\keyle\.julia\v0.2\WebSockets\src\WebSockets.jl:266
 in handle at C:\Users\keyle\.julia\v0.2\WebSockets\src\WebSockets.jl:282
WARNING: backtraces on your platform are often misleading or partially incorrect

Tried both from command line and Julia Studio.

Any ideas?

My guess is
get_websocket_key or generate_websocket_key aren't quite right here

Thanks!
Nic

fix travis setup/build

The travis account linked to in the build badge in readme.md no longer exists. I suppose therefore the breaking unit test (introduced by changes in GnuTls) did not raise any alarms.

Better Logging

A major thing that WebSockets.jl currently lack is a good way to log errors and generally communicate when things go wrong to the user-application. This currently makes debugging changes frustrating (have to add println logging all over), but will also make debugging client applications potentially frustrating.

Logging Options

Since we're using HttpServer anyway, one option is to use its event system, which lets you trigger events and set functions to handle different "types" of events.

Actual logging package options include:

I think Logging.jl looks like the best option... mostly because I got to the bottom of the README and felt like I was ready to start using it. It does basically what I was looking for -- various levels of logging, some potential for making it easy to filter WebSocket level logs separately from application level logs.

Does anyone else have opinions of how we should do logging better?

Echo server receiving/sending UInt8's

Using Julia-0.4.0.app on my Mac, I try this Echo server:

using HttpServer
using WebSockets

wsh = WebSocketHandler() do req, client
  while true
    msg = read(client)
    write(client, msg)
    println("Did receive & send: $msg")
  end
end

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

When I send "aaa", I get this in the console:
Did receive & send: UInt8[0x61,0x61,0x61]
... and in my client I get nothing back.

I would also like to get rid of this:

WARNING: Base.TcpSocket is deprecated, use Base.TCPSocket instead.
  likely near /Users/jkleiser/.julia/v0.4/WebSockets/src/WebSockets.jl:36

Improve closing connections

Reporting the issue hopefully solved with PR#69. See the PR for a longer example. This was reconstructed using a different server implementation which handles both websockets and httpservers.

Websocket w opened in Chrome, server running on windows with Julia v6. Some lines in the stacktrace is from the implementation.

close(w)
ERROR (unhandled task failure): Error: client disconnected
Stacktrace:
 [1] handle_control_frame(::WebSockets.WebSocket, ::WebSockets.WebSocketFragment) at C:\Users\F\.julia\v0.6\WebSockets\src\WebSockets.jl:295
 [2] read(::WebSockets.WebSocket) at C:\Users\F\.julia\v0.6\WebSockets\src\WebSockets.jl:362
 [3] |>(::WebSockets.WebSocket, ::Base.#read) at .\operators.jl:862
 [4] wsmsg2msg(::WebSockets.WebSocket) at C:\\Users\\F\\j\\servecontent\\src\websockets_noprotocol.jl:56
 [5] websockethandle(::HttpCommon.Request, ::WebSockets.WebSocket) at C:\Users\F\j\servecontent\src\servewebsockets.jl:90
 [6] handle(::WebSockets.WebSocketHandler, ::HttpCommon.Request, ::HttpServer.Client{TCPSocket}) at C:\Users\F\.julia\v0.6\WebSockets\src\WebSockets.jl:457
 [7] (::HttpServer.#on_message_complete#14{HttpServer.Server,HttpServer.Client{TCPSocket},Bool})(::HttpCommon.Request) at C:\Users\F\.julia\v0.6\HttpServer\src\HttpServer.jl:420
 [8] on_message_complete(::Ptr{HttpParser.Parser}) at C:\Users\F\.julia\v0.6\HttpServer\src\RequestParser.jl:113
 [9] http_parser_execute(::HttpParser.Parser, ::HttpParser.ParserSettings, ::Array{UInt8,1}) at C:\Users\F\.julia\v0.6\HttpParser\src\HttpParser.jl:115
 [10] process_client(::HttpServer.Server, ::HttpServer.Client{TCPSocket}, ::Bool) at C:\Users\F\.julia\v0.6\HttpServer\src\HttpServer.jl:389
 [11] (::HttpServer.##7#8{HttpServer.Server,Bool})() at .\task.jl:335
ERROR: EOFError: read end of file
Stacktrace:
 [1] read at .\iobuffer.jl:131 [inlined]
 [2] read(::TCPSocket, ::Type{UInt8}) at .\stream.jl:776
 [3] read_frame(::TCPSocket) at C:\Users\F\.julia\v0.6\WebSockets\src\WebSockets.jl:307
 [4] close(::WebSockets.WebSocket) at C:\Users\F\.julia\v0.6\WebSockets\src\WebSockets.jl:231

Get rid of nยฒ complexity for read operations

Messages consist of frames.

The allocated memory currently has an nยฒ relation to the number of frames (and bytes read). Which limits the advantages of websockets in many ways. Only short frames really work well.

The current implementation of Base.read(ws::WebSocket) use recursion . There are various ways of fixing this.

Testing which includes performance indicators on small to large messages needs to be prioritized.

Initial thoughts on alternatives:

  • Improve the recursive algorithm by reducing allocation, change output of recursion to in-place.
  • Make an internal function for the recursion
  • Avoid recursion
  • Have a look at implementations languages that also do not excel at recursion
  • Check if any current dependent packages suffer especially
  • Is an increased overhead for very small messages acceptable?
  • Can one algorithm work well for small and large messages?
  • If not, can the user specify which algorithm to use for an existing websocket?

Julia 0.4: ERROR: LoadError: syntax: missing last argument

I try to run julia examples/chat.jl using Julia-0.4.0 on Mac OS X 10.9.5, and I get this:

WARNING: Base.IpAddr is deprecated, use Base.IPAddr instead.
  likely near /Users/me/.julia/v0.4/HttpServer/src/HttpServer.jl:429
WARNING: Base.IpAddr is deprecated, use Base.IPAddr instead.
  likely near /Users/me/.julia/v0.4/HttpServer/src/HttpServer.jl:430
WARNING: Base.TcpSocket is deprecated, use Base.TCPSocket instead.
  likely near /Users/me/.julia/v0.4/WebSockets/src/WebSockets.jl:36
WARNING: Base.TcpSocket is deprecated, use Base.TCPSocket instead.
  likely near /Users/me/.julia/v0.4/WebSockets/src/WebSockets.jl:36
WARNING: Base.String is deprecated, use AbstractString instead.
  likely near /Volumes/P3/Julia/WebSockets.jl/examples/chat.jl:6
ERROR: LoadError: syntax: missing last argument in "13:" range expression 
 in include at /Volumes/P3/Julia/Julia-0.4.0.app/Contents/Resources/julia/lib/julia/sys.dylib
 in include_from_node1 at /Volumes/P3/Julia/Julia-0.4.0.app/Contents/Resources/julia/lib/julia/sys.dylib
 in process_options at /Volumes/P3/Julia/Julia-0.4.0.app/Contents/Resources/julia/lib/julia/sys.dylib
 in _start at /Volumes/P3/Julia/Julia-0.4.0.app/Contents/Resources/julia/lib/julia/sys.dylib
while loading /Volumes/P3/Julia/WebSockets.jl/examples/chat.jl, in expression starting on line 20

My julia is defined by this script in ~/bin:
`

!/bin/sh

/Volumes/P3/Julia/Julia-0.4.0.app/Contents/Resources/julia/bin/julia "$@"
`

WS Server error, Julia 3.7, Fedora 21

Please, i need some help to with the server.

I got the following message after run a copy from the example code from the docs.
Can' t fix it, dont know whats wrong..

WARNING: Dict-based `@docstring` config is deprecated. Use keywords instead.
Listening on 34440...

signal (11): Segmentation fault
unknown function (ip: -1728454171)
write at /usr/bin/../lib64/julia/sys.so (unknown line)
write at ./iobuffer.jl:235
Segmentation fault

I am running Julia v.3.7 with Fedora 21

Thanks!

Nettle API breakage

Nettle has just broken its API significantly, in order to be much more precompile-friendly. The big takeaway is that methods such as md5_hash(data) should be mapped to digest("md5", data), there are no more auto-generated types for hashes, and internally the code is a little easier to grok. This new version of Nettle.jl has not been released yet, I will make every effort to ensure that dependent packages such as this one have a chance to adapt before releasing the new version.

Follow-up to pull request #62

That pull request got merged before I had a chance to improve it. I took the many forks as an indication that people use this package with their own fixes.

Quote tkelman:

what are you using that was first in 0.16? looks like 0.9.5 might be good enough for take!

A low Compat number may enable some combinations of packages and Julia. I can follow up with another PR to keep the version number as low as possible fora follow-up.

What about the badges? They say 0.6.1 fail. Why is that? And could we do something to indicate that this also works on Windows? I guess I need to get up to date on how the evaluation system works.

Discourage / examine use of localhost

It seems some browsers may default to calling the IPv6 version of localhost, then wait for a timeout before calling 127.0.0....

If that's the case it may explain seemingly random delays in establishing http connections. Examples and documentation should include a OS independent way of finding the responsive address.

How to get the IP address of the request?

Is it possible to get the IP address of the request, please?

With HttpServer it could be done like this:

http.events["connect"] = (http_client) -> handle_connect(http_client)

function handle_connect(client::HTTP.Client)
  try
    ip, port = getsockname(isa(client.sock, MbedTLS.SSLContext) ? client.sock.bio : client.sock)
  catch
  end
 end

Is this working?


julia> using WebSockets
Segmentation fault: 11

Similarly Meddle. The other pieces seem to be failing as well.

[PackageEvaluator.jl] Your package WebSockets may have a testing issue.

This issue is being filed by a script, but if you reply, I will see it.

PackageEvaluator.jl is a script that runs nightly. It attempts to load all Julia packages and run their test (if available) on both the stable version of Julia (0.2) and the nightly build of the unstable version (0.3).

The results of this script are used to generate a package listing enhanced with testing results.

The status of this package, WebSockets, on...

  • Julia 0.2 is 'Tests fail, but package loads.' PackageEvaluator.jl
  • Julia 0.3 is 'Tests pass.' PackageEvaluator.jl

'No tests, but package loads.' can be due to their being no tests (you should write some if you can!) but can also be due to PackageEvaluator not being able to find your tests. Consider adding a test/runtests.jl file.

'Package doesn't load.' is the worst-case scenario. Sometimes this arises because your package doesn't have BinDeps support, or needs something that can't be installed with BinDeps. If this is the case for your package, please file an issue and an exception can be made so your package will not be tested.

This automatically filed issue is a one-off message. Starting soon, issues will only be filed when the testing status of your package changes in a negative direction (gets worse). If you'd like to opt-out of these status-change messages, reply to this message.

ERROR: Could not load library gnutls. Try running Pkg2.fixup() to install missing dependencies!

I'm running Mac OSX 10.7 with all latest packages and julia build installed.

julia> using HttpServer
WARNING: BinDeps.find_library is deprecated, use Base.find_library instead.
in include_from_node1 at loading.jl:91
WARNING: add_library_mapping is deprecated, use push!(DL_LOAD_PATH,"/path/to/search") instead.
WARNING: delete!(a::Vector,x) is deprecated, use splice!(a,x) instead.
in library_dependency at /Users/ericjang/.julia/BinDeps/src/dependencies.jl:53
ERROR: Could not load library gnutls. Try running Pkg2.fixup() to install missing dependencies!
in error at error.jl:21
in include_from_node1 at loading.jl:91
in reload_path at loading.jl:114
in require at loading.jl:48
in include_from_node1 at loading.jl:91
in reload_path at loading.jl:114
in require at loading.jl:48
at /Users/ericjang/.julia/GnuTLS/src/GnuTLS.jl:487
at /Users/ericjang/.julia/HttpServer/src/HttpServer.jl:179

requiring GnuTls works but the build seems to be unsuccessful:
ericjang@system-process ~/.julia/GnuTLS (master)$ julia deps/build.jl
WARNING: delete!(a::Vector,x) is deprecated, use splice!(a,x) instead.
in library_dependency at /Users/ericjang/.julia/BinDeps/src/dependencies.jl:53
Array((DependencyProvider,Dict{Symbol,Any}),(5,)) [(RemoteBinaries(URI(ftp://ftp.gnutls.org/gcrypt/gnutls/w32/gnutls-3.2.1-w32.zip)),[:os=>:Windows]),(Homebrew(HomebrewInstall("gnutls",[],[])),[:validate=>true]),(AptGet("libgnutls28"),[:validate=>true]),(Yum("libgnutls"),[:validate=>true]),(Autotools(nothing,{:libtarget=>"lib/libgnutls.la",:lib_dirs=>["/Users/ericjang/Desktop/julia/usr//lib"],:env=>{"HOGWEED_LIBS"=>"-L/Users/ericjang/Desktop/julia/usr//lib -L/Users/ericjang/.julia/deps/usr/lib -lhogweed -lgmp","LIBS"=>"-lgmp ","LD_LIBRARY_PATH"=>"/Users/ericjang/Desktop/julia/usr//lib:/Users/ericjang/.julia/deps/usr/lib","NETTLE_LIBS"=>"-L/Users/ericjang/Desktop/julia/usr//lib -L/Users/ericjang/.julia/deps/usr/lib -lnettle -lgmp"},:include_dirs=>["/Users/ericjang/Desktop/julia/usr//include"]}),[:force_depends=>{BuildProcess=>LibraryDependency(nettle)}])]
{"HOGWEED_LIBS"=>"-L/Users/ericjang/Desktop/julia/usr//lib -L/Users/ericjang/.julia/deps/usr/lib -lhogweed -lgmp","LIBS"=>"-lgmp ","LD_LIBRARY_PATH"=>"/Users/ericjang/Desktop/julia/usr//lib:/Users/ericjang/.julia/deps/usr/lib","NETTLE_LIBS"=>"-L/Users/ericjang/Desktop/julia/usr//lib -L/Users/ericjang/.julia/deps/usr/lib -lnettle -lgmp"}
-L/Users/ericjang/.julia/deps/usr/lib -L/Users/ericjang/Desktop/julia/usr//lib -Wl,-rpath -Wl,/Users/ericjang/.julia/deps/usr/lib
MESSAGE: Attempting to Create directory /Users/ericjang/.julia/deps/downloads
MESSAGE: Directory /Users/ericjang/.julia/deps/downloads already created
MESSAGE: Downloading file ftp://ftp.gnutls.org/gcrypt/gnutls/v3.2/gnutls-3.2.1.tar.xz
MESSAGE: Done downloading file ftp://ftp.gnutls.org/gcrypt/gnutls/v3.2/gnutls-3.2.1.tar.xz
MESSAGE: Attempting to Create directory /Users/ericjang/.julia/deps/src
MESSAGE: Directory /Users/ericjang/.julia/deps/src already created
MESSAGE: Attempting to Create directory /Users/ericjang/.julia/deps
MESSAGE: Directory /Users/ericjang/.julia/deps already created
MESSAGE: Attempting to Create directory /Users/ericjang/.julia/deps/src/gnutls-3.2.1
ERROR: assertion failed: :((p.handle!=C_NULL))
in kill at process.jl:454
in wait_success at process.jl:556
in wait_success at process.jl:562
in run at process.jl:413
in run at /Users/ericjang/.julia/BinDeps/src/BinDeps.jl:416
in run at /Users/ericjang/.julia/BinDeps/src/BinDeps.jl:433
in satisfy! at /Users/ericjang/.julia/BinDeps/src/dependencies.jl:356
in anonymous at /Users/ericjang/.julia/BinDeps/src/dependencies.jl:370
in include_from_node1 at loading.jl:91
in process_options at client.jl:274
in _start at client.jl:350
at /Users/ericjang/.julia/GnuTLS/deps/build.jl:41

TcpSockets no longer exported by Base?

Should be an easy fix, too short for merge.

In line 20 of WebSockets.jl, should be Base.TcpSocket

as TcpSocket is no longer defined (short of an explicit import)

HTTPS SSL TLS Using websockets doesnt work

Line 381 in Websocket.jl:

sock = WebSocket(client.id, client.sock)

Receives a MbedTLS SSLContext in the client.sock value as per HttpServer.jl:

     sess = MbedTLS.SSLContext()
        MbedTLS.setup!(sess, ssl_config)
        # set_priority_string!(sess)
        # set_credentials!(sess, cert_store)
        client = accept(server.http.sock)
        try
            MbedTLS.set_bio!(sess, client)
            MbedTLS.handshake(sess)
            # associate_stream(sess, client)
            # handshake!(sess)
        catch e
            println("Error establishing SSL connection: ", e)
            close(client)
            continue
        end
        client = Client(id_pool += 1, sess)
        client.parser = ClientParser(message_handler(server, client, websockets_enabled))
        @async process_client(server, client, websockets_enabled)`

JuliaWeb/HttpServer.jl#87
As I'm not sure which project is better to help massage the socket into, I'm looking for help on this one. Please let me know what to do! Thanks

PS Here's more interesting debug info:

HttpServer.Client{MbedTLS.SSLContext}(14,MbedTLS.SSLContext(Ptr{Void} @0x0000000003245910,MbedTLS.SSLConfig(Ptr{Void} @0x0000000002dff880,MbedTLS.CtrDrbg(Ptr{Void} @0x0000000002ca2f00,Nullable(MbedTLS.Entropy(Ptr{Void} @0x0000000002e54c90,Any[]))),#undef,(anonymous function),cert. version : 3
serial number : DB:7E:D8:55:3E:F1:AB:AC
issuer name : C=US, ST=CA, L=San Francisco, O=BXI, CN=bxi.io, emailAddress=[email protected]
subject name : C=US, ST=CA, L=San Francisco, O=BXI, CN=bxi.io, emailAddress=[email protected]
issued on : 2016-02-21 07:47:43
expires on : 2017-02-20 07:47:43
signed using : RSA with SHA-256
RSA key size : 2048 bits
basic constraints : CA=true
,MbedTLS.PKContext(Ptr{Void} @0x0000000002cf1160)),true,TCPSocket(open, 0 bytes waiting)),HttpServer.ClientParser(HttpParser,HttpParser.ParserSettings(Ptr{Void} @0x00007fcb39e9ffc0,Ptr{Void} @0x00007fcb39ea35d0,Ptr{Void} @0x00007fcb39ea3810,Ptr{Void} @0x00007fcb39ea3850,Ptr{Void} @0x00007fcb39ea3a80,Ptr{Void} @0x00007fcb39ea4c80,Ptr{Void} @0x00007fcb39ea50a0,Ptr{Void} @0x00007fcb39ea5210)))WARNING: both Patchwork and Base export "Text"; uses of it in module Main must be qualified
ERROR (unhandled task failure): MethodError: convert has no method matching convert(::Type{TCPSocket}, ::MbedTLS.SSLContext)
This may have arisen from a call to the constructor TCPSocket(...),
since type constructors fall back to convert methods.
Closest candidates are:
TCPSocket(::Any)
call{T}(::Type{T}, ::Any)
convert{T}(::Type{T}, ::T)
...
in call at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:57
in handle at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:387
in on_message_complete at /home/a/.julia/v0.4/HttpServer/src/HttpServer.jl:393
in on_message_complete at /home/a/.julia/v0.4/HttpServer/src/RequestParser.jl:104

PPS This is what I tried (using client.sock.bio):
dioptre@3bb92d7

...and new error

handling websocket connection:
write: broken pipe (EPIPE)
in yieldto at ./task.jl:71
in wait at ./task.jl:371
in stream_wait at ./stream.jl:60
in uv_write at stream.jl:944
in flush at stream.jl:979
in locked_write at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:154
in write at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:168
in start_updates at /home/a/projects/bxi/server/www.jl:213
in anonymous at /home/a/projects/bxi/server/www.jl:274
in anonymous at /home/a/.julia/v0.4/Mux/src/Mux.jl:15
in anonymous at /home/a/.julia/v0.4/Mux/src/Mux.jl:8
in splitquery at /home/a/.julia/v0.4/Mux/src/basics.jl:28
in anonymous at /home/a/.julia/v0.4/Mux/src/Mux.jl:8
in wcatch at /home/a/.julia/v0.4/Mux/src/websockets_integration.jl:12
in anonymous at /home/a/.julia/v0.4/Mux/src/Mux.jl:8
in todict at /home/a/.julia/v0.4/Mux/src/basics.jl:21
in anonymous at /home/a/.julia/v0.4/Mux/src/Mux.jl:12 (repeats 2 times)
in anonymous at /home/a/.julia/v0.4/Mux/src/Mux.jl:8
in anonymous at /home/a/.julia/v0.4/Mux/src/server.jl:38
in handle at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:394
in on_message_complete at /home/a/.julia/v0.4/HttpServer/src/HttpServer.jl:393
in on_message_complete at /home/a/.julia/v0.4/HttpServer/src/RequestParser.jl:104ERROR (unhandled task failure): write: broken pipe (EPIPE)
in yieldto at ./task.jl:71
in wait at ./task.jl:371
in stream_wait at ./stream.jl:60
in uv_write at stream.jl:944
in flush at stream.jl:979
in locked_write at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:154
in close at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:197
in handle at /home/a/.julia/v0.4/WebSockets/src/WebSockets.jl:395
in on_message_complete at /home/a/.julia/v0.4/HttpServer/src/HttpServer.jl:393
in on_message_complete at /home/a/.julia/v0.4/HttpServer/src/RequestParser.jl:1

Is it possible to have a websocket server at a particular route?

Hi -- Based on the examples, it wasn't clear to me how create a websocket server which was attached to a particular "route" e.g. on the client side I would like the code to look like:
var ws = new WebSocket("ws://localhost:9998/echo");

rather than

var ws = new WebSocket("ws://localhost:9998");

and ideally I could have multiple websocket servers listening on different routes.

Does anyone know if this easily possible given the current architecture?

thanks!

how to handle prefix?

Is there anyway to specify and handle websocket prefix?

for example:
client side code: ws = new WebSocket("ws://localhost:8080/websocket")

how do I handle prefix = /websocket on julia websocket server?

Thank you!

Tag a new version + fix old version tags

I see one version, 0.0.4 tagged in the github repo, and up to version 0.0.6 tagged in metadata, but all of those are 2 years old at this point.

Is this stable enough that we can call it 1.0.0? Or maybe we should at least tag 0.1.0?

Opt-in on message compression

Compression extensions are standardized by now.
For local websockets, the current behaviour of not compressing messages is optimal.
For use over the internet, compression is a necessary feature for e.g. interactive pixel graphics.

On the client side, the negotiated message compression is available in javascript using
websocket.extensions. A similar interface ought to be available on the server side.

The http request for a websocket contains the possibilities, e.g. from Chrome:
Sec-WebSocket-Extensions => permessage-deflate; client_max_window_bits

Ref. issue #76 - compression would currently be very effective even on local connections.

[PkgEval] WebSockets may have a testing issue on Julia 0.3 (2014-08-16)

PackageEvaluator.jl is a script that runs nightly. It attempts to load all Julia packages and run their tests (if available) on both the stable version of Julia (0.3) and the nightly build of the unstable version (0.4). The results of this script are used to generate a package listing enhanced with testing results.

On Julia 0.3

  • On 2014-08-15 the testing status was Tests pass.
  • On 2014-08-16 the testing status changed to Package doesn't load.

Tests pass. means that PackageEvaluator found the tests for your package, executed them, and they all passed.

Package doesn't load. means that PackageEvaluator did not find tests for your package. Additionally, trying to load your package with using failed.

This issue was filed because your testing status became worse. No additional issues will be filed if your package remains in this state, and no issue will be filed if it improves. If you'd like to opt-out of these status-change messages, reply to this message saying you'd like to and @IainNZ will add an exception. If you'd like to discuss PackageEvaluator.jl please file an issue at the repository. For example, your package may be untestable on the test machine due to a dependency - an exception can be added.

Test log:

>>> 'Pkg.add("WebSockets")' log
 - Library "libhttp_parser"

INFO: Cloning cache of WebSockets from git://github.com/JuliaLang/WebSockets.jl.git
INFO: Installing BinDeps v0.3.0
INFO: Installing Calendar v0.4.2
INFO: Installing Codecs v0.1.2
INFO: Installing FactCheck v0.1.2
INFO: Installing GnuTLS v0.0.1
INFO: Installing HttpCommon v0.0.5
INFO: Installing HttpParser v0.0.9
INFO: Installing HttpServer v0.0.7
INFO: Installing ICU v0.4.1
INFO: Installing Nettle v0.1.4
INFO: Installing SHA v0.0.2
INFO: Installing URIParser v0.0.2
INFO: Installing WebSockets v0.0.6
INFO: Building ICU
=================================[ ERROR: ICU ]=================================

None of the selected providers can install dependency icu.
Use BinDeps.debug(package_name) to see available providers

while loading /home/idunning/pkgtest/.julia/v0.3/ICU/deps/build.jl, in expression starting on line 28

================================================================================
INFO: Building Nettle
INFO: Building GnuTLS
INFO: Building HttpParser

================================[ BUILD ERRORS ]================================

WARNING: ICU had build errors.

 - packages with build errors remain installed in /home/idunning/pkgtest/.julia/v0.3
 - build a package and all its dependencies with `Pkg.build(pkg)`
 - build a single package by running its `deps/build.jl` script

================================================================================
INFO: Package database updated
INFO: METADATA is out-of-date a you may not have the latest version of WebSockets
INFO: Use `Pkg.update()` to get the latest versions of your packages

>>> 'using WebSockets' log
ERROR: could not open file /home/idunning/pkgtest/.julia/v0.3/ICU/src/../deps/deps.jl
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:54
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:54
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:54
 in include at ./boot.jl:245
 in include_from_node1 at ./loading.jl:128
 in reload_path at loading.jl:152
 in _require at loading.jl:67
 in require at loading.jl:51
 in include at ./boot.jl:245
 in include_from_node1 at loading.jl:128
 in process_options at ./client.jl:285
 in _start at ./client.jl:354
 in _start_3B_1699 at /home/idunning/julia03/usr/bin/../lib/julia/sys.so
while loading /home/idunning/pkgtest/.julia/v0.3/ICU/src/ICU.jl, in expression starting on line 54
while loading /home/idunning/pkgtest/.julia/v0.3/Calendar/src/Calendar.jl, in expression starting on line 1
while loading /home/idunning/pkgtest/.julia/v0.3/HttpCommon/src/HttpCommon.jl, in expression starting on line 3
while loading /home/idunning/pkgtest/.julia/v0.3/WebSockets/src/WebSockets.jl, in expression starting on line 3
while loading /home/idunning/pkgtest/.julia/v0.3/WebSockets/testusing.jl, in expression starting on line 1


>>> test log
no tests to run
>>> end of log

small cosmetic bug:

in the chat example, in file chat.jl on line 32 change to:

write(v.client, (connections[id].name * ": " * content))

so it writes the right name to other clients

Confusing / not robust behaviour for unaccepted handshakes

The current behaviour for unaccepted handshakes is to call the handler with a Websocket already in a closing state.

The handler receives the WebScoket along with the request. This may be useful in checking what's wrong with the request, but this is also confusing. I believe it may also open a server more to an attack when we leave it to the browser to actually close the socket. With the current behaviour, we just send a "400" to the browser and expects it to continue with closing.

Submitted PR #71 which changes this behaviour. No log or errors warns about the unaccepted handshakes.

Extend handshake to allow for Websocket sub-protocols

We currently support webpages including
ws = new WebSocket("ws://localhost:8080");
...but not the useful subprotocol functionality
ws = new WebSocket("ws://localhost:8080", "json");

Users can write specific handlers for subprotocols, but we need to extend the handshake protocol slightly. Users would need to tell Websockets which subprotocols to accept.

Typical subprotocol names: "json", "websocket-ZMQ", "www.github.io/mypackage", "user-events".

From https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#Miscellaneous

Think of a subprotocol as a custom XML schema or doctype declaration. You're still using XML and its syntax, but you're additionally restricted by a structure you agreed on. WebSocket subprotocols are just like that. They do not introduce anything fancy, they just establish structure. Like a doctype or schema, both parties must agree on the subprotocol; unlike a doctype or schema, the subprotocol is implemented on the server and cannot be externally refered to by the client.

Also ref. #65 .

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.