websocket_parser 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ .rbx
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+ - rbx-19mode
7
+ script: bundle exec rspec spec
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # WebSocketParser
2
+ [![Build Status](https://secure.travis-ci.org/afcapel/websocket_parser.png)](http://travis-ci.org/afcapel/websocket_parser)
2
3
 
3
4
  WebsocketParser is a RFC6455 compliant parser for websocket messages written in Ruby. It
4
5
  is intended to write websockets servers in Ruby, but it only handles the parsing of the
@@ -1,31 +1,44 @@
1
1
  require 'digest/sha1'
2
+ require 'base64'
2
3
 
3
4
  module WebSocket
4
5
  class ClientHandshake < Http::Request
5
6
 
6
7
  def self.accept_token_for(websocket_key)
7
- Digest::SHA1.base64digest(websocket_key.strip + GUID)
8
+ Base64.encode64(Digest::SHA1.digest(websocket_key.strip + GUID)).strip
8
9
  end
9
10
 
10
- def initialize(method, uri, headers = {}, proxy = {}, body = nil, version = "1.1")
11
- @method = method.to_s.downcase.to_sym
12
- @uri = uri.is_a?(URI) ? uri : URI(uri.to_s)
13
-
14
- @headers = headers
15
- @proxy, @body, @version = proxy, body, version
11
+ def errors
12
+ @errors ||= []
16
13
  end
17
14
 
18
15
  def valid?
19
- headers['Connection'] == 'Upgrade' &&
20
- headers['Upgrade'] == 'websocket' &&
21
- headers['Sec-WebSocket-Version'].to_i == PROTOCOL_VERSION
16
+ if headers['Connection'].downcase != 'upgrade'
17
+ errors << 'Not connection upgrade'
18
+ return false
19
+ end
20
+
21
+ if headers['Upgrade'].downcase != 'websocket'
22
+ errors << 'Connection upgrade is not for websocket'
23
+ return false
24
+ end
25
+
26
+ # Careful: Http gem changes header capitalization,
27
+ # so Sec-WebSocket-Version becomes Sec-Websocket-Version
28
+ if headers['Sec-Websocket-Version'].to_i != PROTOCOL_VERSION
29
+ errors << "Protocol version not supported '#{headers['Sec-Websocket-Version']}'"
30
+ return false
31
+ end
32
+
33
+ return true
22
34
  end
23
35
 
24
36
  def accept_response
37
+ websocket_key = headers['Sec-Websocket-Key']
25
38
  response_headers = {
26
39
  'Upgrade' => 'websocket',
27
40
  'Connection' => 'Upgrade',
28
- 'Sec-WebSocket-Accept' => ClientHandshake.accept_token_for(headers['Sec-WebSocket-Key'])
41
+ 'Sec-WebSocket-Accept' => ClientHandshake.accept_token_for(websocket_key)
29
42
  }
30
43
 
31
44
  ServerHandshake.new(101, '1.1', response_headers)
@@ -44,16 +44,6 @@ module WebSocket
44
44
  @payload = WebSocket.mask(@payload, @mask_key)
45
45
  end
46
46
 
47
- def message_size
48
- if payload_length < 126
49
- :small
50
- elsif payload_length < 65_536 # fits in 2 bytes
51
- :medium
52
- else
53
- :large
54
- end
55
- end
56
-
57
47
  def payload_length
58
48
  @payload ? @payload.length : 0
59
49
  end
@@ -62,10 +52,6 @@ module WebSocket
62
52
  second_byte & 0b10000000 != 0
63
53
  end
64
54
 
65
- def extended_payload_length
66
- message_size == :small ? nil : payload_length
67
- end
68
-
69
55
  def to_data
70
56
  to_a.pack(pack_format)
71
57
  end
@@ -92,6 +78,20 @@ module WebSocket
92
78
  WebSocket.frame_format(payload_length, masked?)
93
79
  end
94
80
 
81
+ def message_size
82
+ if payload_length < 126
83
+ :small
84
+ elsif payload_length < 65_536 # fits in 2 bytes
85
+ :medium
86
+ else
87
+ :large
88
+ end
89
+ end
90
+
91
+ def extended_payload_length
92
+ message_size == :small ? nil : payload_length
93
+ end
94
+
95
95
  def first_byte
96
96
  @first_byte ||= if type == :continuation
97
97
  OPCODE_VALUES[type]
@@ -27,27 +27,6 @@ module WebSocket
27
27
  class Parser
28
28
  def initialize
29
29
  @data = ''.force_encoding("ASCII-8BIT")
30
-
31
- @on_message = Proc.new do |msg|
32
- puts "Received message: #{msg}"
33
- end
34
-
35
- @on_error = Proc.new do |error|
36
- puts "WebSocket error: #{error}"
37
- end
38
-
39
- @on_close = Proc.new do |status, message|
40
- puts "Should close connection. Status: #{status} Message: #{message}"
41
- end
42
-
43
- @on_ping = Proc.new do
44
- puts "Ping received"
45
- end
46
-
47
- @on_pong = Proc.new do
48
- puts "Pong received"
49
- end
50
-
51
30
  @state = :header
52
31
  end
53
32
 
@@ -84,6 +63,8 @@ module WebSocket
84
63
 
85
64
  alias_method :<<, :receive
86
65
 
66
+ private
67
+
87
68
  def read_header
88
69
  return unless @data.length >= 2 # Not enough data
89
70
 
@@ -157,18 +138,18 @@ module WebSocket
157
138
  def process_message
158
139
  case opcode
159
140
  when :text
160
- @on_message.call(@current_message.force_encoding("UTF-8"))
141
+ @on_message.call(@current_message.force_encoding("UTF-8")) if @on_message
161
142
  when :binary
162
- @on_message.call(@current_message)
143
+ @on_message.call(@current_message) if @on_message
144
+ when :ping
145
+ @on_ping.call if @on_ping
146
+ when :pong
147
+ @on_pong.call if @on_ping
163
148
  when :close
164
149
  status_code, message = @current_message.unpack('S<a*')
165
150
  status = STATUS_CODES[status_code]
166
151
 
167
- @on_close.call(status, message)
168
- when :ping
169
- @on_ping.call
170
- when :pong
171
- @on_pong.call
152
+ @on_close.call(status, message) if @on_close
172
153
  end
173
154
 
174
155
  @current_message = nil
@@ -1,5 +1,6 @@
1
1
  module WebSocket
2
2
  class ServerHandshake < Http::Response
3
+ CRLF = "\r\n"
3
4
 
4
5
  def initialize(status = 101, version = "1.1", headers = {}, body = nil, &body_proc)
5
6
  @status, @version, @body, @body_proc = status, version, body, body_proc
@@ -7,17 +8,20 @@ module WebSocket
7
8
  end
8
9
 
9
10
  def render(out)
10
- response_header = "#{@version} #{@status} #{@reason}#{CRLF}"
11
+ out << to_data
12
+ end
13
+
14
+ def to_data
15
+ data = "#{@version} #{@status} #{@reason}#{CRLF}"
11
16
 
12
17
  unless @headers.empty?
13
- response_header << @headers.map do |header, value|
18
+ data << @headers.map do |header, value|
14
19
  "#{header}: #{value}"
15
20
  end.join(CRLF) << CRLF
16
21
  end
17
22
 
18
- response_header << CRLF
19
-
20
- out << response_header
23
+ data << CRLF
24
+ data
21
25
  end
22
26
  end
23
27
  end
@@ -1,3 +1,3 @@
1
1
  module WebSocket
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,3 +1,5 @@
1
+ require "http"
2
+
1
3
  require "websocket/version"
2
4
  require "websocket/client_handshake"
3
5
  require "websocket/server_handshake"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: websocket_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-08 00:00:00.000000000 Z
12
+ date: 2012-08-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http
@@ -67,6 +67,7 @@ extensions: []
67
67
  extra_rdoc_files: []
68
68
  files:
69
69
  - .gitignore
70
+ - .travis.yml
70
71
  - Gemfile
71
72
  - LICENSE
72
73
  - README.md
@@ -96,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
97
  version: '0'
97
98
  segments:
98
99
  - 0
99
- hash: -3359756691541156568
100
+ hash: 2288242846946475689
100
101
  required_rubygems_version: !ruby/object:Gem::Requirement
101
102
  none: false
102
103
  requirements:
@@ -105,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
106
  version: '0'
106
107
  segments:
107
108
  - 0
108
- hash: -3359756691541156568
109
+ hash: 2288242846946475689
109
110
  requirements: []
110
111
  rubyforge_project:
111
112
  rubygems_version: 1.8.23