em-websocket-request 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitmodules CHANGED
@@ -1,3 +1,3 @@
1
1
  [submodule "lib/em-ws-request/vendor/web-socket-ruby"]
2
2
  path = lib/em-ws-request/vendor/web-socket-ruby
3
- url = git@github.com:rykov/web-socket-ruby.git
3
+ url = git://github.com/gimite/web-socket-ruby.git
@@ -79,7 +79,7 @@ class WebSocket
79
79
  end
80
80
 
81
81
  @path = (uri.path.empty? ? "/" : uri.path) + (uri.query ? "?" + uri.query : "")
82
- host = uri.host + (uri.port == default_port ? "" : ":#{uri.port}")
82
+ host = uri.host + ((!uri.port || uri.port == default_port) ? "" : ":#{uri.port}")
83
83
  origin = params[:origin] || "http://#{uri.host}"
84
84
  key1 = generate_key()
85
85
  key2 = generate_key()
@@ -186,47 +186,51 @@ class WebSocket
186
186
  if packet =~ /\A\x00(.*)\xff\z/nm
187
187
  return force_encoding($1, "UTF-8")
188
188
  elsif packet == "\xff" && read(1) == "\x00" # closing
189
- close(true)
189
+ close(1005, "", :peer)
190
190
  return nil
191
191
  else
192
192
  raise(WebSocket::Error, "input must be either '\\x00...\\xff' or '\\xff\\x00'")
193
193
  end
194
194
 
195
195
  else
196
- bytes = read(2).unpack("C*")
197
- fin = (bytes[0] & 0x80) != 0
198
- opcode = bytes[0] & 0x0f
199
- mask = (bytes[1] & 0x80) != 0
200
- plength = bytes[1] & 0x7f
201
- if plength == 126
202
- bytes = read(2)
203
- plength = bytes.unpack("n")[0]
204
- elsif plength == 127
205
- bytes = read(8)
206
- (high, low) = bytes.unpack("NN")
207
- plength = high * (2 ** 32) + low
208
- end
209
- if @server && !mask
210
- # Masking is required.
211
- @socket.close()
212
- raise(WebSocket::Error, "received unmasked data")
213
- end
214
- mask_key = mask ? read(4).unpack("C*") : nil
215
- payload = read(plength)
216
- payload = apply_mask(payload, mask_key) if mask
217
- case opcode
218
- when OPCODE_TEXT
219
- return force_encoding(payload, "UTF-8")
220
- when OPCODE_BINARY
221
- raise(WebSocket::Error, "received binary data, which is not supported")
222
- when OPCODE_CLOSE
223
- close(true)
224
- return nil
225
- when OPCODE_PING
226
- raise(WebSocket::Error, "received ping, which is not supported")
227
- when OPCODE_PONG
228
- else
229
- raise(WebSocket::Error, "received unknown opcode: %d" % opcode)
196
+ begin
197
+ bytes = read(2).unpack("C*")
198
+ fin = (bytes[0] & 0x80) != 0
199
+ opcode = bytes[0] & 0x0f
200
+ mask = (bytes[1] & 0x80) != 0
201
+ plength = bytes[1] & 0x7f
202
+ if plength == 126
203
+ bytes = read(2)
204
+ plength = bytes.unpack("n")[0]
205
+ elsif plength == 127
206
+ bytes = read(8)
207
+ (high, low) = bytes.unpack("NN")
208
+ plength = high * (2 ** 32) + low
209
+ end
210
+ if @server && !mask
211
+ # Masking is required.
212
+ @socket.close()
213
+ raise(WebSocket::Error, "received unmasked data")
214
+ end
215
+ mask_key = mask ? read(4).unpack("C*") : nil
216
+ payload = read(plength)
217
+ payload = apply_mask(payload, mask_key) if mask
218
+ case opcode
219
+ when OPCODE_TEXT
220
+ return force_encoding(payload, "UTF-8")
221
+ when OPCODE_BINARY
222
+ raise(WebSocket::Error, "received binary data, which is not supported")
223
+ when OPCODE_CLOSE
224
+ close(1005, "", :peer)
225
+ return nil
226
+ when OPCODE_PING
227
+ raise(WebSocket::Error, "received ping, which is not supported")
228
+ when OPCODE_PONG
229
+ else
230
+ raise(WebSocket::Error, "received unknown opcode: %d" % opcode)
231
+ end
232
+ rescue EOFError
233
+ return nil
230
234
  end
231
235
 
232
236
  end
@@ -259,16 +263,21 @@ class WebSocket
259
263
  end
260
264
 
261
265
  # Does closing handshake.
262
- def close(by_peer = false)
266
+ def close(code = 1005, reason = "", origin = :self)
263
267
  if !@closing_started
264
268
  case @web_socket_version
265
269
  when "hixie-75", "hixie-76"
266
270
  write("\xff\x00")
267
271
  else
268
- send_frame(OPCODE_CLOSE, "", false)
272
+ if code == 1005
273
+ payload = ""
274
+ else
275
+ payload = [code].pack("n") + force_encoding(reason.dup(), "ASCII-8BIT")
276
+ end
277
+ send_frame(OPCODE_CLOSE, payload, false)
269
278
  end
270
279
  end
271
- @socket.close() if by_peer
280
+ @socket.close() if origin == :peer
272
281
  @closing_started = true
273
282
  end
274
283
 
@@ -332,7 +341,11 @@ class WebSocket
332
341
  def read(num_bytes)
333
342
  str = @socket.read(num_bytes)
334
343
  $stderr.printf("recv> %p\n", str) if WebSocket.debug
335
- return str
344
+ if str && str.bytesize == num_bytes
345
+ return str
346
+ else
347
+ raise(EOFError)
348
+ end
336
349
  end
337
350
 
338
351
  def write(data)
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- WS_REQUEST_VERSION = "0.0.3"
2
+ WS_REQUEST_VERSION = "0.0.4"
3
3
  end
@@ -8,9 +8,9 @@ module EventMachine
8
8
  @web_socket_version = version
9
9
  end
10
10
 
11
- def send_frame(type, data)
12
- opcode = type_to_opcode(type)
13
- super(opcode, data, true)
11
+ def send_frame(opcode, data, mask = true)
12
+ opcode = type_to_opcode(opcode) if opcode.is_a?(Symbol)
13
+ super(opcode, data, mask)
14
14
  end
15
15
 
16
16
  def write(data)
@@ -29,8 +29,9 @@ module EventMachine
29
29
  end
30
30
 
31
31
  # Called on a CLOSE frame
32
- def close(by_peer = false)
33
- super(by_peer)
32
+ def close(code = 1005, reason = "", origin = :self)
33
+ origin = :self if origin == :peer # to skip @socket.close
34
+ super(code, reason, origin)
34
35
  @client.unbind
35
36
  end
36
37
 
@@ -13,7 +13,7 @@ describe EventMachine::WebsocketRequest do
13
13
 
14
14
  it "should invoke errback on failed upgrade" do
15
15
  EventMachine.run {
16
- http = EventMachine::WebsocketRequest.new('ws://127.0.0.1:8090/').get :timeout => 0
16
+ http = websocket_test_request(:timeout => 0)
17
17
 
18
18
  http.callback { failed(http) }
19
19
  http.errback {
@@ -27,14 +27,14 @@ describe EventMachine::WebsocketRequest do
27
27
  EventMachine.run {
28
28
  MSG = "hello bi-directional data exchange"
29
29
 
30
- EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8085, :debug => true) do |ws|
30
+ with_websocket_test_server do |ws|
31
31
  ws.onopen { p [:OPENED_WS, ws]}
32
32
  ws.onmessage {|msg| ws.send msg}
33
33
  ws.onerror {|e| p [:WS_ERROR, e]}
34
34
  ws.onclose { p [:WS_CLOSE, ws]}
35
35
  end
36
36
 
37
- http = EventMachine::WebsocketRequest.new('ws://127.0.0.1:8085/').get :keepalive => true
37
+ http = websocket_test_request
38
38
  http.errback { failed(http) }
39
39
  http.callback {
40
40
  http.response_header.status.should == 101
@@ -55,32 +55,61 @@ describe EventMachine::WebsocketRequest do
55
55
  # parser eats up the trailign data
56
56
  # [:receive, "HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nWebSocket-Origin: 127.0.0.1\r\nWebSocket-Location: ws://127.0.0.1:8085/\r\n\r\n\x001\xFF\x002\xFF", :keep_alive?, "#<HTTP::Parser:0x0000010132d000>"]
57
57
 
58
- xit "should split multiple messages from websocket server into separate stream callbacks" do
58
+ it "should split multiple messages from websocket server into separate stream callbacks" do
59
59
  EM.run do
60
60
  messages = %w[1 2]
61
61
  recieved = []
62
62
 
63
- EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8085) do |ws|
64
- ws.onopen {
65
- ws.send messages[0]
66
- ws.send messages[1]
67
- }
63
+ with_websocket_test_server do |ws|
64
+ ws.onopen do
65
+ EventMachine.add_timer(0.1) { ws.send messages[0] }
66
+ EventMachine.add_timer(0.2) { ws.send messages[1] }
67
+ end
68
68
  end
69
69
 
70
- EventMachine.add_timer(0.1) do
71
- http = EventMachine::WebsocketRequest.new('ws://127.0.0.1:8085/').get :keepalive => true
72
- http.errback { failed(http) }
73
- http.callback { http.response_header.status.should == 101; p 'WS CONNECTED' }
74
- http.stream {|msg|
75
- p ['GOT MSG ', msg]
76
- msg.should == messages[recieved.size]
77
- recieved.push msg
78
- p [:MULTI_MESAGE, recieved]
79
-
80
- EventMachine.stop if recieved.size == messages.size
81
- }
82
- end
70
+ http = websocket_test_request
71
+ http.errback { failed(http) }
72
+ http.callback { http.response_header.status.should == 101; p 'WS CONNECTED' }
73
+ http.stream {|msg|
74
+ p ['GOT MSG ', msg]
75
+ msg.should == messages[recieved.size]
76
+ recieved.push msg
77
+ p [:MULTI_MESAGE, recieved]
78
+ EventMachine.stop if recieved.size == messages.size
79
+ }
83
80
  end
84
81
  end
82
+
83
+ it "should process close on message correctly " do
84
+ EM.run {
85
+ MSG = "hello bi-directional data exchange"
86
+
87
+ with_websocket_test_server do |ws|
88
+ ws.onopen { p [:OPENED_WS, ws] }
89
+ ws.onmessage { |msg| ws.close_websocket }
90
+ ws.onerror {|e| p [:WS_ERROR, e] }
91
+ ws.onclose { p [:WS_CLOSE, ws] }
92
+ end
93
+
94
+ http = websocket_test_request
95
+ http.errback { failed(http) }
96
+ http.callback { http.send(MSG) }
97
+ http.stream { |chunk|
98
+ chunk.should be_nil
99
+ EventMachine.stop
100
+ }
101
+
102
+ }
103
+ end
104
+ end
105
+
106
+ def with_websocket_test_server(&block)
107
+ opts = { :host => "0.0.0.0", :port => 8085, :debug => true }
108
+ EventMachine::WebSocket.start(opts, &block)
109
+ end
110
+
111
+ def websocket_test_request(opts = {})
112
+ req = EventMachine::WebsocketRequest.new('ws://127.0.0.1:8085/')
113
+ req.get(opts.merge(:keepalive => true))
85
114
  end
86
115
  end
metadata CHANGED
@@ -1,38 +1,34 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: em-websocket-request
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
4
5
  prerelease:
5
- version: 0.0.3
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Michael Rykov
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-10-13 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
12
+ date: 2011-12-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
16
15
  name: em-http-request
17
- prerelease: false
18
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70226843904280 !ruby/object:Gem::Requirement
19
17
  none: false
20
- requirements:
18
+ requirements:
21
19
  - - ~>
22
- - !ruby/object:Gem::Version
20
+ - !ruby/object:Gem::Version
23
21
  version: 1.0.0
24
22
  type: :runtime
25
- version_requirements: *id001
23
+ prerelease: false
24
+ version_requirements: *70226843904280
26
25
  description: EventMachine WebSocket client
27
- email:
26
+ email:
28
27
  - mrykov@gmail.com
29
28
  executables: []
30
-
31
29
  extensions: []
32
-
33
30
  extra_rdoc_files: []
34
-
35
- files:
31
+ files:
36
32
  - .gitignore
37
33
  - .gitmodules
38
34
  - Gemfile
@@ -44,32 +40,29 @@ files:
44
40
  - lib/em-ws-request/wrapper.rb
45
41
  - spec/websocket_spec.rb
46
42
  - lib/em-ws-request/vendor/web-socket-ruby/lib/web_socket.rb
47
- homepage: ""
43
+ homepage: ''
48
44
  licenses: []
49
-
50
45
  post_install_message:
51
46
  rdoc_options: []
52
-
53
- require_paths:
47
+ require_paths:
54
48
  - lib
55
- required_ruby_version: !ruby/object:Gem::Requirement
49
+ required_ruby_version: !ruby/object:Gem::Requirement
56
50
  none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: "0"
61
- required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
56
  none: false
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: "0"
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
67
61
  requirements: []
68
-
69
62
  rubyforge_project:
70
63
  rubygems_version: 1.8.11
71
64
  signing_key:
72
65
  specification_version: 3
73
66
  summary: EventMachine WebSocket client
74
- test_files:
67
+ test_files:
75
68
  - spec/websocket_spec.rb