em-websocket-request 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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