Giter Site home page Giter Site logo

em-websocket's Introduction

https://metrics.lecoq.io/igrigorik

em-websocket's People

Contributors

at1as avatar bernerdschaefer avatar bkoski avatar christianl avatar codegoalie avatar danielpietzsch avatar danielwaterworth avatar fagiani avatar fxposter avatar gimite avatar grempe avatar iblue avatar igorw avatar igrigorik avatar imanel avatar jameshfisher avatar jamesvorder avatar janlelis avatar mattetti avatar mcolyer avatar miksago avatar mloughran avatar movitto avatar nv avatar patriciomacadden avatar richo avatar sishen avatar stve avatar vongruenigen avatar zimbatm 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  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

em-websocket's Issues

Frame size security

I'm not sure this is an issue or if I have misunderstood:

It seems that the 'framing76' implementation checks the size of each frame and allows a max of 10 MB:

https://github.com/igrigorik/em-websocket/blob/master/lib/em-websocket/framing76.rb#L44

However, none of the other framing implementations (framing05-03) do this check. Would it then be possible for a malicious user to write a client using another framing method and fill the server's memory with junk (the other framing implementations seem to allow for up to 4GB frames)?

Thanks for any answers!

Install on Windows

Oh.
Sorry for that. but i spent the whole day trying to go through but i'm stuck.
Maybe i'm a bit newbie so i downloaded and installed DevKit from rubyinstller.org then i tried to gem install eventmachine - no luck, then: gem install eventmachine-win32 - ok, but i still have the one error:


gem install em-websocket
Temporarily enhancing PATH to include DevKit...
Building native extensions. This could take a while...
ERROR: Error installing em-websocket:
ERROR: Failed to build gem native extension.

C:/Ruby192/bin/ruby.exe extconf.rb
checking for rb_trap_immediate in ruby.h,rubysig.h... no
checking for rb_thread_blocking_region()... yes
checking for inotify_init() in sys/inotify.h... no
checking for __NR_inotify_init in sys/syscall.h... no
checking for writev() in sys/uio.h... no
checking for rb_thread_check_ints()... yes
checking for rb_time_new()... yes
checking for windows.h... yes
checking for winsock.h... yes
checking for main() in -lkernel32... yes
checking for main() in -lrpcrt4... yes
checking for main() in -lgdi32... yes
checking for main() in -lssl... no
creating Makefile

make
g++ -I. -IC:/Ruby192/include/ruby-1.9.1/i386-mingw32 -I/C/Ruby192/include/ruby-1
.9.1/ruby/backward -I/C/Ruby192/include/ruby-1.9.1 -I. -DBUILD_FOR_RUBY -DHAVE_R
B_THREAD_BLOCKING_REGION -DHAVE_TBR -DHAVE_RB_THREAD_CHECK_INTS -DHAVE_RB_TIME_N
EW -DOS_WIN32 -DHAVE_WINDOWS_H -DHAVE_WINSOCK_H -DWITHOUT_SSL -DHAVE_MAKE_PAIR
-O3 -g -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-
strings -Wno-missing-field-initializers -Wno-long-long -o binder.o -c binder.c
pp
In file included from project.h:137:0,
from binder.cpp:20:
binder.h:35:34: warning: type qualifiers ignored on function return type
In file included from project.h:138:0,
from binder.cpp:20:
em.h:91:47: warning: type qualifiers ignored on function return type
em.h:92:76: warning: type qualifiers ignored on function return type
em.h:93:56: warning: type qualifiers ignored on function return type
em.h:95:57: warning: type qualifiers ignored on function return type
em.h:96:60: warning: type qualifiers ignored on function return type
em.h:97:58: warning: type qualifiers ignored on function return type
em.h:98:55: warning: type qualifiers ignored on function return type
em.h:99:36: warning: type qualifiers ignored on function return type
em.h:101:47: warning: type qualifiers ignored on function return type
em.h:106:42: warning: type qualifiers ignored on function return type
em.h:123:45: warning: type qualifiers ignored on function return type
em.h:132:36: warning: type qualifiers ignored on function return type
In file included from project.h:145:0,
from binder.cpp:20:
eventmachine.h:45:61: warning: type qualifiers ignored on function return type
eventmachine.h:46:112: warning: type qualifiers ignored on function return type
eventmachine.h:47:69: warning: type qualifiers ignored on function return type
eventmachine.h:49:73: warning: type qualifiers ignored on function return type
eventmachine.h:62:75: warning: type qualifiers ignored on function return type
eventmachine.h:63:74: warning: type qualifiers ignored on function return type
eventmachine.h:64:77: warning: type qualifiers ignored on function return type
eventmachine.h:65:41: warning: type qualifiers ignored on function return type
In file included from project.h:145:0,
from binder.cpp:20:
eventmachine.h:99:60: warning: type qualifiers ignored on function return type
eventmachine.h:100:58: warning: type qualifiers ignored on function return type
eventmachine.h:102:60: warning: type qualifiers ignored on function return type
eventmachine.h:105:41: warning: type qualifiers ignored on function return type
g++ -I. -IC:/Ruby192/include/ruby-1.9.1/i386-mingw32 -I/C/Ruby192/include/ruby-1
.9.1/ruby/backward -I/C/Ruby192/include/ruby-1.9.1 -I. -DBUILD_FOR_RUBY -DHAVE_R
B_THREAD_BLOCKING_REGION -DHAVE_TBR -DHAVE_RB_THREAD_CHECK_INTS -DHAVE_RB_TIME_N
EW -DOS_WIN32 -DHAVE_WINDOWS_H -DHAVE_WINSOCK_H -DWITHOUT_SSL -DHAVE_MAKE_PAIR
-O3 -g -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-
strings -Wno-missing-field-initializers -Wno-long-long -o cmain.o -c cmain.cpp

In file included from project.h:137:0,
from cmain.cpp:20:
binder.h:35:34: warning: type qualifiers ignored on function return type
In file included from project.h:138:0,
from cmain.cpp:20:
em.h:91:47: warning: type qualifiers ignored on function return type
em.h:92:76: warning: type qualifiers ignored on function return type
em.h:93:56: warning: type qualifiers ignored on function return type
em.h:95:57: warning: type qualifiers ignored on function return type
em.h:96:60: warning: type qualifiers ignored on function return type
em.h:97:58: warning: type qualifiers ignored on function return type
em.h:98:55: warning: type qualifiers ignored on function return type
em.h:99:36: warning: type qualifiers ignored on function return type
em.h:101:47: warning: type qualifiers ignored on function return type
em.h:106:42: warning: type qualifiers ignored on function return type
em.h:123:45: warning: type qualifiers ignored on function return type
em.h:132:36: warning: type qualifiers ignored on function return type
In file included from project.h:145:0,
from cmain.cpp:20:
eventmachine.h:45:61: warning: type qualifiers ignored on function return type
eventmachine.h:46:112: warning: type qualifiers ignored on function return type
eventmachine.h:47:69: warning: type qualifiers ignored on function return type
eventmachine.h:49:73: warning: type qualifiers ignored on function return type
eventmachine.h:62:75: warning: type qualifiers ignored on function return type
eventmachine.h:63:74: warning: type qualifiers ignored on function return type
eventmachine.h:64:77: warning: type qualifiers ignored on function return type
eventmachine.h:65:41: warning: type qualifiers ignored on function return type
In file included from project.h:145:0,
from cmain.cpp:20:
eventmachine.h:99:60: warning: type qualifiers ignored on function return type
eventmachine.h:100:58: warning: type qualifiers ignored on function return type
eventmachine.h:102:60: warning: type qualifiers ignored on function return type
eventmachine.h:105:41: warning: type qualifiers ignored on function return type
cmain.cpp:98:71: warning: type qualifiers ignored on function return type
cmain.cpp:109:122: warning: type qualifiers ignored on function return type
cmain.cpp:119:79: warning: type qualifiers ignored on function return type
cmain.cpp:129:83: warning: type qualifiers ignored on function return type
cmain.cpp:260:85: warning: type qualifiers ignored on function return type
cmain.cpp:270:84: warning: type qualifiers ignored on function return type
cmain.cpp:280:88: warning: type qualifiers ignored on function return type
cmain.cpp:290:51: warning: type qualifiers ignored on function return type
cmain.cpp:300:70: warning: type qualifiers ignored on function return type
cmain.cpp:320:55: warning: type qualifiers ignored on function return type
cmain.cpp:546:70: warning: type qualifiers ignored on function return type
cmain.cpp:669:68: warning: type qualifiers ignored on function return type
cmain.cpp: In function 'int evma_send_file_data_to_connection(long unsigned int,
const char_)':
cmain.cpp:752:6: error: cannot convert 'stat_' to 'stati64' for argument '2' t
o 'int _fstati64(int, stati64)'
make: *** [cmain.o] Error 1

Gem files will remain installed in C:/Ruby192/lib/ruby/gems/1.9.1/gems/eventmach
ine-0.12.10 for inspection.
Results logged to C:/Ruby192/lib/ruby/gems/1.9.1/gems/eventmachine-0.12.10/ext/g
em_make.out

Stopped working with Chrome

Looks like something has changed in the websockets implementation of Chrome.
I have a small em-websocket server, and it is not accepting connections from chrome a few days ago (on different machines, windows, and macos).
Still works with Safari.

(Chrome is up to date, and I also installed Chrome Canary - with no success.)

Differences between specification and implementation

I found few differences between actual specification and em-websocket implentation of some parts. Mostly it's in handshake part(for draft 75 and 5&6) and probably(but I'm not sure) in message framing for 5&6. Everything is described in this gist:

https://gist.github.com/1002083

Could you look at it and correct me if I'm wrong? If not then I can help with some parts.

UTF-8 conversion can lead to issues

I've been having some encoding issues. By default, messages coming in are ASCII-8BIT. When I use the json gem's to_json I get an error:

server.rb:18:in `encode': "\xC3" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError)

The solution to this is to force UTF-8 encoding on the message like so:

ws.onmessage { |msg|
  puts "Received message: #{msg}"
  msg = msg.force_encoding('UTF-8')
  msg = JSON.parse([msg].to_json)[0]
  ws.send msg
}

This however gives me:

em-websocket/lib/em-websocket/connection.rb:166:in `send': incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError)

Which is:

  def send(data)
    debug [:send, data]
    send_data("\x00#{data}\xff")
  end

I could solve the issue by replacing that with:

  def send(data)
    debug [:send, data]
    send_data("\x00".force_encoding('UTF-8') + data + "\xff".force_encoding('UTF-8'))
  end

But I am not sure if that could break other things.

Improve unmasking performance

In drafts 04 and above all data sent by browsers must be XORed with 4 random bytes which is described in http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-06#section-4.2

I wrote the simplest code that could possibly work to do this. It works, but the performance stinks. Unmasking 1MB (1000 1K strings) takes 1.75s on my laptop. Does anyone have any bright ideas about nice ways to rewrite the code in https://github.com/igrigorik/em-websocket/blob/draft5and6/lib/em-websocket/masking04.rb ?

Please contribute to https://gist.github.com/902183

Protocol version 13 not supported

Hi. I use crhome & it was work, but don't know why when I update em-websocket & faced wired problem.

[[:error,#<EventMachine::WebSocket::WebSocketError: Protocol version 13 not supported>]]

here is the extra information from header

[[:inbound_headers,"GET /private/e4153380bd79444d01f67689ed3ebbca HTTP/1.1\r\nUpgrade: websocket\r\nConnection: 
Upgrade\r\nHost: localhost:9002\r\nOrigin: http://localhost:8080\r\nSec-WebSocket-Key: jkNkOqF/nqA1QqjlTVJRLg==\r\nSec-WebSocket-Version:13\r\nCookie:_meetcliv_session=BAh7DEkiD3Nlc3Npb25faWQGOgZFRiIlMzUzMzZiYWIyMDA1MjBhNGJhNmY4NTBhMjI4YTQ5MmJJIhBfY3NyZl90b2tlbgY7AEZJIjFhdHZQS2JUdXR6UXB2YlRydHhlZDBmOWdJMc1Z3M5azAyeEFVci9zTDJJPQY7AEZJIhFhY2Nlc3NfdG9rZW4GOwBGSSJnQUFBQjBBbDdpcjRBQkFNQjBkSHBYRzRYU3p6U0p2eVg4WXhqZWhnU1pDOWJYbHdJbHZGZllaQlE0QWVudFpDUzJCSzg3ekhNV3psVnRTVjM2eGhuSDJpTjQ0SDdaQ2h3WkQGOwBGSSIKYWRtaW4GOwBGaQZJIgxhY2NvdW50BjsARkkiGGhpdGFrZWFuZUBnbWFpbC5jb20GOwBUSSIIbWlkBjsARmkC3gFJIglmYmlkBjsARkkiDjc1MjU4NzgwNwY7AFQ%3D--b7c3194be5b5a5fda5fa0cf5338f3a602f906b26\r\n\r\n"]]

any clue?

Draft 10 changes

  • Must fail the websocket connection if invalid opcode is received (changed from ignore)
  • Introduced new 1007 close error code if server received data which is not valid UTF8 (section 7.4.1). Let's implement this for ruby 1.9 at least.

Draft 09 changes

  • Should fail the web socket connection when receiving nonzero RSV* bits which are not understood (which means for now that any nonzero bits should fail the connection). Currently RSV* bits are simply ignored

Error: Connection and Upgrade headers required

I tried to use socket.io.js (https://github.com/LearnBoost/Socket.IO) in a web page and make it connect to a em-websocket server. There's a simple server implementation in the examples directory of https://github.com/igrigorik/em-websocket. The server said that Connection and upgrade headers were required, apparently in the handshake. These are the ruby output:

[[:initialize]]

[[:receive_data, "GET /socket.io/xhr-polling//1300861225825 HTTP/1.1\r\nHost: localhost:8080\r\nConnection: keep-alive\r\nOrigin: null\r\nUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16\r\nAccept: /\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\nAccept-Charset: GBK,utf-8;q=0.7,*;q=0.3\r\n\r\n"]]

[[:inbound_headers, "GET /socket.io/xhr-polling//1300861225825 HTTP/1.1\r\nHost: localhost:8080\r\nConnection: keep-alive\r\nOrigin: null\r\nUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16\r\nAccept: /\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: zh-CN,zh;q=0.8\r\nAccept-Charset: GBK,utf-8;q=0.7,*;q=0.3\r\n\r\n"]]

[[:error, #<EventMachine::WebSocket::HandshakeError: Connection and Upgrade headers required>]]

Error: Connection and Upgrade headers required
[[:unbind, :connection]]

Release 0.3.0

Any objections if I release the current master (0c94287) as 0.3.0?

There are a few optimisations we can make to the draft 6 support, but it's been running for a while on Pusher and seems solid enough.

Exceptions get swallowed

When debug is disabled, em-websocket will swallow all exceptions, even critical stuff like non-existent classes. I suspect that the rescue in EventMachine::WebSocket::Connection is causing this. It should only catch those exceptions that are relevant.

Yes, there is the debug option, but that includes too much information.

Flash port 843 doesn't response

Perhaps this issue already solved?

I use web-socket-js for IE which connect via flash.
but get no response, I asked web-socket-js and they said it should be support by default.

just wondering any body also face this problem?

memory leak in em-websocket for large number of connections

Hi,

For a large number of connections, em-websocket keeps leaking memory eventually reaching 100% memory usage.
The more connections and/or the large data, the faster this happens.

Below is a gist with a simple server, and a benchmark to simulate 10k concurrent connections, notice that you can reduce the number of connections and/or data, but the memory usage will still be going up (albeit slower).

https://gist.github.com/953250

ruby server.rb
ruby benchmark.rb

This was run in machine using Red Hat Enterprise 5.6.

I reviewed the code searching for the cause, but couldnt find it :( Is this a known issue or something that can be fixed?

Frame lengths should be limited to protect against malicious requests

It is currently possible to frame a request that would cause an arbitrarily large buffer to accumulate in memory. It is also possible to send a frame such as "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00" which would cause a "bignum too big to convert into `long'" exception to be raised. I have seen the latter type occur in the wild with pusherapp.

Currently the WebSocket spec does not specify a maximum message length, however it seems reasonable to limit this. The following commit limits the frame to 10MB and if triggered calls the onerror callback and closes the connection. This solves both issues.

http://github.com/mloughran/em-websocket/commit/e62f226fb6fdc6b6cee64080a82303eca05923c9

can I authenticate a connection to em-websocket?

I was trying to use em-websocket to do a chat program. Instead of letting everybody connect to the server, I would like to authenticate users when they try to make connections. I was wondering if that could be done when the user first tries to make a connection.

Is it possible to use a url with parameters to connect, like ws://localhost:8080/?param1=user&param2=password ?

Channels or Subscribers?

I want to be able to ws.send a message to a specific user vs all users. Should I create a EM::Channel for each websocket connection and keep track of the channels or create one channel and keep track of subscribers?

Problems with getting set up

Hey there, I really like this project and it got me excited enough to implement one of my ideas with it. Problem is, I wired everything up just fine (I think), but when running the server I get absolutely no output, and I can't connect from Chrome.

Here's the server, just a basic one (I run it with ruby server.rb, hope that's right):

require 'em-websocket'

puts "Starting server"
EventMachine.run {

  EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080, :debug => true) do |ws|
    ws.onopen { ws.send "Hello Client!" }
    ws.onmessage { |msg| ws.send "Pong: #{msg}" }
    ws.onclose { puts "WebSocket closed" }
  end

}

Now even though debug is true, all I get is

[root@dyno test]# ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]
[root@dyno test]# ruby server.rb
Starting server

Then it hangs with no output. The client code is also basic:

// Open the WebSocket connection
var ws = new WebSocket("ws://myserver.org:8080/");
ws.onopen = function(evt) { socketOpen(evt); }
ws.onclose = function(evt) { socketClose(evt); }
ws.onmessage = function(evt) { socketMessage(evt); }
ws.onerror = function(evt) { socketError(evt); }

This runs in Chrome 11.0.696 but can't establish a connection (trying to use the native Chrome implementation, no flash)

Using wss://

Hi,

I have an EM WebSocket running:

 EventMachine::WebSocket.start({
      :host => '0.0.0.0',
      :port => 443,
      :secure => true,
      :tls_options => {
        :private_key_file => 'tmp/server.key',
        :cert_chain_file => 'tmp/server.crt'
    }
  }) do |ws|
    ws.onopen {ws.send "connected to WebSocket with port 443, SSH"}
    ws.onmessage { |msg| puts "got message #{msg}"}
    ws.onclose { ws.send "Websocket was closed"}
  end

I can connect to this using a ws://192.168.2.2:443

 EventMachine.run {
   http = EventMachine::HttpRequest.new("ws://amazon:443").get :timeout => 0
   http.errback { puts "oops" }
   http.callback {
   puts "WebSocket connected!"
   http.send("Hello client")
  }

  http.stream { |msg|
  puts "Recieved: #{msg}"
  http.send "Pong: #{msg}"
 }
}

The Client connection code request and server response are noted on my console, but this is not a wss:// client connecting!! Uh oh... me thinks.

I switch to Javascript quickly to verify that wss:// using Chrome connects and this is re-assuring, whereas ws:// with Javascript did not, also reassuring that my SSL WebSocket server is functioning as intended.

With em-http-request sending wss:// I get the callback Websocket Connected! but the following send is ignored and nothing makes it to the server. Is there anything obvious that I am doing wrong here? I am hoping to get wss:// via a ruby client and I am also curious as to why ws:// seems to work on an SSL connection.

I suppose this is due to em-http-request not handling SSL directly and that I have to setup a tunnel to my websocket server using SSH or something??

I am confused now. Summary: Is there a clean nice way to use WSS:// with Ruby?
Any tips most appreciated..!!!!

support haproxy

Apparently, to support operating behind an haproxy you can't wait for the nonce string. see the gist: https://gist.github.com/729332

I'm not 100% sure about how this works but reading references in other servers: https://github.com/Worlize/Socket.IO-node/commit/b9bef2b2660526768c1cd21ad1ef77f72ec0fc62

and tornadoweb/tornado#153

It appears the nonce e.g. the request body is optional? From my gist it's clear that it's not included when proxied behind HAProxy... I'm just getting setup with em-* so will take a shot at a patch but thought it'd be helpful to get some more eyes on this...

I'm using the following to manage haproxy locally for testing: https://gist.github.com/729335

I've messed around with changing the websock from mode http and mode tcp - believe with the changes in the other mentioned servers mode http would/can work... i've also tested running on the same or different ports.

Strange skipping behavior when reloading client HTML

Hi Ilya,

I am doing a little testing with em-websocket and noticing a strange behavior. Here is my setup, and you can see the code here:

http://gist.github.com/264965

  • run rabbitmq in source dir with 'make run'
  • I start server.rb
  • I open client.html in my Chrome dev channel browser (also tested in todays nightly webkit)
  • do : ./msg-inject.rb "date" (I have backticks around the date command, but github message formatting is stripping that out)

Each time I run msg-inject.rb I see the current date show up in my browser client. All good.

Now here is the weirdness:

  • Reload the client.rb in the browser with a CMD-R without touching anything else. Now when I run msg-inject.rb I only see every second message show up in the browser.
  • Reload client.rb again, and I see every third message.

And so on... with the number of skips incrementing by one after each reload.

So if I reload the client.rb nine times, you guessed it, I only see every ninth message in the browser client. This behaves exactly the same in both chrome and webkit.

And if I restart the server.rb, It all resets, and I'll see every incoming message, until I reload client.html and get the incrementing 'skipping' behavior again.

Thoughts?

Invalid HTTP header

I'm getting this with some users when they try to connect. Works on some people's Firefox4, and doesn't work on other people's. Frustrating!

EventMachine::WebSocket::HandshakeError: Invalid HTTP header

[[:initialize]]

[[:receive_data,
  "GET /?room=ary_reads&p=KpQzawYSpbio&u=AJ Test HTTP/1.1\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nHost: myhost.org:4442\r\nOrigin: http://myhost.org:3001\r\nCookie: read_to=1300999519389; visits=_4196565__2427159__3877855__2196184__4467059__4489769__4610009__4613793__4616659__4618821__4635255__4640989__4652339__4655081__4658289__4668459__4676893__4705833__4714487__4734261__4737825__4758763__4763665__4; sdata=AJ+Morelli_okaa-true_p-g_okxx-true_JH-asdf; remember_me=asdf%3D%3D--asdf; clk=1\r\nSec-WebSocket-Key1: 21nd8 75 71 x: t      03  2%\r\nSec-WebSocket-Key2: 23 9_ 14@B9 N  29R U1 2G M\r\n\r\n\adsf\324\335\313"]]

[[:inbound_headers,
  "GET /?room=ary_reads&p=KpQzawYSpbio&u=AJ Test HTTP/1.1\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nHost: myhost.org:4442\r\nOrigin: http://myhost.org:3001\r\nCookie: read_to=1300999519389; visits=_4196565__2427159__3877855__2196184__4467059__4489769__4610009__4613793__4616659__4618821__4635255__4640989__4652339__4655081__4658289__4668459__4676893__4705833__4714487__4734261__4737825__4758763__4763665__4; sdata=AJ+Morelli_okaa-true_p-g_okxx-true_JH-asdf; remember_me=asdf%3D%3D--asdf; clk=1\r\nSec-WebSocket-Key1: 21nd8 75 71 x: t      03  2%\r\nSec-WebSocket-Key2: 23 9_ 14@B9 N  29R U1 2G asdf5\313"]]

[[:error, #<EventMachine::WebSocket::HandshakeError: Invalid HTTP header>]

I'm using https://github.com/gimite/web-socket-js on the JS side. Any suggestions?

HTTP headers matching must be case insensitive

em-websocket fails if a HTTP GET request contains "sec-websocket-key1" instead of "Sec-WebSocket-Key1". The same for ANY header involved in websocket handshake.

This is not correct, HTTP header names are case insensitive always.

Using EM-WebSocket w/ AMQP

I'm having some problems using AMQP (message queuing) with EM-WebSocket.

Here's the basic idea:

EventMachine.run {
  EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |socket|
    socket.onopen {
      puts "WS connection opened"
      AMQP.start(:host => "hostname") do
        exchange = MQ.topic("exchange.name", :durable => true)
        mq = MQ.new 
        mq.queue("queue.name").bind(exchange).subscribe do |m|
          puts "handling new message: #{m}"
          socket.send m
        end
      end
    }
  }
}

This works well enough, in that I see the browser (Chrome) connect to the socket server and that the socket server is able to consume messages from the AMQP queue. I run into problems though when multiple messages are waiting in the queue for pickup. Sometimes, it seems like all the messages are picked up, framed correctly, and sent through the socket to the browser. Other times, it seems like all the messages are picked up, but some number (1..n-1, n being the number of messages available) are framed correctly and sent through the socket to the browser.

In short, it seems like all the messages are correctly consumed from the queue, but not all are consistently sent to the browser (though the ones that are sent are framed correctly).

I have confirmed the actual data transmitted through the socket with a proxy, so I'm fairly confident this describes the real problem.

Examples

I ran "ruby multicast.rb" in examples/ and got "no such file to load -- lib/em-websocket". I suppose I could resolve it by running multicast.rb in parent dir instead but then what about the require of twitter/json_stream in there? Is it just non-working example code out of the box and I just need to require gems instead to make it work? Thanks.

Framing76::process_data(): section 4.2 of darft 76?

Hi, method Framing76::process_data() says:

# This algorithm comes straight from the spec
# http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76#section-4.2

But such section of the draft is about bytes sent fom the server to the client!:

4.2.  Data framing
  Once a WebSocket connection is established, the user agent must run
  through the following state machine for the bytes sent by the server.

Shouldn't such method implemente section 5.3?:

5.3.  Data framing
  The server must run through the following steps to process the bytes
  sent by the client.

Hardening / performance

This isn't really a specific issue, but I was playing around with making a badly behaved client and was sending the websocket server inappropriately large messages. The server uses minimal CPU when you send lots of small messages, but sending one large (hundreds of K) message per second maxes out the CPU.
I used the profiler to discover that over 99% of the time is spent in framing76.rb in line 66 which is String#slice! with a regexp argument...

I guess I'm wondering, how could we change the implementation so that it can handle arbitrarily large messages? Relatedly, I recall seeing a comment about limiting incoming messages to 10MB. Does that work, is it arbitrary, and could I lower it to protect against DOS from a rogue client?

Support sending ping and waiting for pong response

WebSocket drafts >= 03 support ping/pong request/responses that are initiated from both the client and the server (see http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-06#section-4.5.2). em-websocket already supports responding to ping requests with a pong, however there is no server side API to send a ping.

Sending the ping is trivial, but it's not entirely clear what should be done with the response. A simple API could be

ws.ping(optional_string)
ws.onpong { |response_string| ... }

However it is possible to send a body in a ping request which must be echoed in the pong response. Therefore it would be possible to match up pings and pongs and expose something like

ws.ping {
  # called on pong receipt
}

However as an application developer you're mostly concerned with the scenario when a pong does not arrive which suggests adding a timeout

ws.ping(10).errback {
  # pong not received after 10s
}

Thoughts appreciated!

checks

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to xxxxx.com.
Escape character is '^]'.
GET /

at irb:
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
from /opt/ruby-ee-1.8.7-2009.10/lib/ruby/gems/1.8/gems/em-websocket-0.0.5/lib/../lib/em-websocket/connection.rb:60:in new_request' from /opt/ruby-ee-1.8.7-2009.10/lib/ruby/gems/1.8/gems/em-websocket-0.0.5/lib/../lib/em-websocket/connection.rb:44:indispatch'
from /opt/ruby-ee-1.8.7-2009.10/lib/ruby/gems/1.8/gems/em-websocket-0.0.5/lib/../lib/em-websocket/connection.rb:31:in receive_data' from /opt/ruby-ee-1.8.7-2009.10/lib/ruby/gems/1.8/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:inrun_machine'
from /opt/ruby-ee-1.8.7-2009.10/lib/ruby/gems/1.8/gems/eventmachine-0.12.10/lib/eventmachine.rb:256:in run' from /opt/ruby-ee-1.8.7-2009.10/lib/ruby/gems/1.8/gems/em-websocket-0.0.5/lib/../lib/em-websocket/websocket.rb:6:instart'
from (irb):4

onclose proc is never called

the onclose proc is never called because there is a typo in the instance variable name @onclode = blk on lib/em-websocket/connection.rb

if @data[0] != 0x00 in framing76.rb

Hi,

I found that, using a recent build of Google Chrome with em-websocket, connections were closed unexpectedly when the client sent data.

On line 69 of framing76.rb

if @DaTa[0] != 0x00

will always evaluate to true under Ruby 1.9, seemingly because @DaTa[0] is a String and 0x00 is a Fixnum. We either need to use to_i on the left side or quotes on the right.

$ char break response

When Sec-WebSocket-Key1 or Sec-WebSocket-Key2 have $ char inside then request will have invalid response and connection fill fails. You can check this in code: lib/em-websocket/handler_factory.rb:5
HEADER = /^([^:]+):\s_([^$]+)/
Shouldn't it be:
HEADER = /^([^:]+):\s_(.+)$/
or $ character is forbidden? And if then please provide mi some link - http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 don't inform about anything about "$" character.

Question about multicast example

Hi,

I am trying out the idea of using channels in a simple app. I want my client to connect, establish a channel, and that way, I can be sure when I run a deferred task, the callback can send a message to the right channel.

I connect fine and logged the output from the server.

receive data
inbound headers
upgrade headers
send "connected"
receive data
message
send message
unbind connection

It is the last aspect of this handshake sequence that puzzles me. It looks as if the example unbinds and closes the connection once it has established the connection, received a message, sent a response.

I was thinking the connection would not close until either I explicitely sent a close from the server process, or the client actually disconnects.

Is there something I am reading into the example that is naive or mistaken? Any tips most appreciated. I really just want to establish a channel that persists as long as needed to complete some long running task on the server, alert the client when it is done, and then kill the connection. I am thinking this is how it probably already works, but I am not sure....

Thanks

Pass the Connection instance as block argument to onopen

I'd like to send messages only to particular connected computers (instead of to every computer using a EventMachine::Channel.new). Right now I'm monkey patching Connection#handshake to pass the connection instance as a block argument to the @onopen callback, mirroring the pattern of passing the connection to the @onclose callback.

Happy to submit a patch/tests if you think this is valuable in general.

Invalid gemspec

When running bundle install I get the following:

em-websocket at /Users/josh/.rvm/gems/ruby-1.9.2-p0/bundler/gems/em-websocket-96e85559334e did not have a valid gemspec.
This prevents bundler from installing bins or native extensions, but that may not affect its functionality.
The validation message from Rubygems was:
  ["README.rdoc"] are not files

Best way to integrate with Rails 3?

When I run the code within examples/echo.rb in a Rails 3 initializer, it errors out on the first message with a process_data error. The same code runs fine outside Rails in a standalone program. What could be the issue here ?

em-websocket/framing76.rb:67:in `process_data': 134217727: /\A\x00([^\xff]*)\xff/ (SyntaxError)

(The above is a simple test case. It actually needs to be done within a thread so that the rest of the rails 3 initialization proceeds. This was just a test case which was on jRuby; client was chrome running examples/test).

On a related note, what is the best practice to integrate em-websocket within Rails 3 for just sending notification messages via a web service?

Bad frame type receiving 3+ frames message

As followed the 07 draft to implement my own C++/Qt client, wich is working fine with your server.
But i think i spotted a little mistake in the draft interpretation, when sending more than 2 frame for the same packet,

  • The first should have an opcode > 0 and fin bit set to false
  • Every middle packet should have opcode = 0 (continuation) and fin set to false
  • The last packet should have opcode = 0 and fin bit set to true.

http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07#section-4.4

I realized that in your implementation, you replace the opcode for each frame excluding the last one:
https://github.com/igrigorik/em-websocket/blob/master/lib/em-websocket/framing07.rb#L92

This cause every multi-frame packet containing middle frame to be considered "continuation" instead of "text" or "binary".
Instead you should store the frame_type only the first time, maybe like this:

@frame_type ||= frame_type

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.