libwebsocket 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,215 +0,0 @@
1
- module LibWebSocket
2
- #Construct or parse a WebSocket response.
3
- class Response < Message
4
-
5
- attr_accessor :location, :secure, :resource_name, :cookies, :key1, :key2
6
-
7
- # Parse a WebSocket response.
8
- # @see Message#parse
9
- # @example Parser
10
- # res = LibWebSocket::Response.new;
11
- # res.parse("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a")
12
- # res.parse("Upgrade: WebSocket\x0d\x0a")
13
- # res.parse("Connection: Upgrade\x0d\x0a")
14
- # res.parse("Sec-WebSocket-Origin: file://\x0d\x0a")
15
- # res.parse("Sec-WebSocket-Location: ws://example.com/demo\x0d\x0a")
16
- # res.parse("\x0d\x0a")
17
- # res.parse("0st3Rl&q-2ZU^weu")
18
- def parse(string)
19
- super
20
- end
21
-
22
- # Construct a WebSocket response in string format.
23
- # @example Construct
24
- # res = LibWebSocket::Response.new(
25
- # :host => 'example.com',
26
- # :resource_name => '/demo',
27
- # :origin => 'file://',
28
- # :number1 => 777_007_543,
29
- # :number2 => 114_997_259,
30
- # :challenge => "\x47\x30\x22\x2D\x5A\x3F\x47\x58"
31
- # )
32
- # res.to_s # HTTP/1.1 101 WebSocket Protocol Handshake
33
- # # Upgrade: WebSocket
34
- # # Connection: Upgrade
35
- # # Sec-WebSocket-Origin: file://
36
- # # Sec-WebSocket-Location: ws://example.com/demo
37
- # #
38
- # # 0st3Rl&q-2ZU^weu
39
- def to_s
40
- string = ''
41
-
42
- string += "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"
43
-
44
- string += "Upgrade: WebSocket\x0d\x0a"
45
- string += "Connection: Upgrade\x0d\x0a"
46
-
47
- raise 'host is required' unless self.host
48
-
49
- location = self.build_url(
50
- :host => self.host,
51
- :secure => self.secure,
52
- :resource_name => self.resource_name
53
- )
54
- origin = self.origin || 'http://' + location.host
55
-
56
- if self.version <= 75
57
- string += 'WebSocket-Protocol: ' + self.subprotocol + "\x0d\x0a" if self.subprotocol
58
- string += 'WebSocket-Origin: ' + origin + "\x0d\x0a"
59
- string += 'WebSocket-Location: ' + location.to_s + "\x0d\x0a"
60
- else
61
- string += 'Sec-WebSocket-Protocol: ' + self.subprotocol + "\x0d\x0a" if self.subprotocol
62
- string += 'Sec-WebSocket-Origin: ' + origin + "\x0d\x0a"
63
- string += 'Sec-WebSocket-Location: ' + location.to_s + "\x0d\x0a"
64
- end
65
-
66
- unless self.cookies.empty?
67
- string += 'Set-Cookie: '
68
- string += self.cookies.collect(&:to_s).join(',')
69
- string += "\x0d\x0a"
70
- end
71
-
72
- string += "\x0d\x0a"
73
-
74
- string += self.checksum if self.version > 75
75
-
76
- return string
77
- end
78
-
79
- # Construct a WebSocket response in rack format.
80
- # @example Construct
81
- # res = LibWebSocket::Response.new(
82
- # :host => 'example.com',
83
- # :resource_name => '/demo',
84
- # :origin => 'file://',
85
- # :number1 => 777_007_543,
86
- # :number2 => 114_997_259,
87
- # :challenge => "\x47\x30\x22\x2D\x5A\x3F\x47\x58"
88
- # )
89
- # res.to_rack # [ 101,
90
- # # {
91
- # # 'Upgrade' => 'WebSocket'
92
- # # 'Connection' => 'Upgrade'
93
- # # 'Sec-WebSocket-Origin' => 'file://'
94
- # # 'Sec-WebSocket-Location' => 'ws://example.com/demo'
95
- # # 'Content-Length' => 16
96
- # # },
97
- # # [ 0st3Rl&q-2ZU^weu ] ]
98
- def to_rack
99
- status = 101
100
- hash = {}
101
- body = ''
102
-
103
- hash = {'Upgrade' => 'WebSocket', 'Connection' => 'Upgrade'}
104
-
105
- raise 'host is required' unless self.host
106
-
107
- location = self.build_url(
108
- :host => self.host,
109
- :secure => self.secure,
110
- :resource_name => self.resource_name
111
- )
112
- origin = self.origin || 'http://' + location.host
113
-
114
- if self.version <= 75
115
- hash.merge!('WebSocket-Protocol' => self.subprotocol) if self.subprotocol
116
- hash.merge!('WebSocket-Origin' => origin)
117
- hash.merge!('WebSocket-Location' => location.to_s)
118
- else
119
- hash.merge!('Sec-WebSocket-Protocol' => self.subprotocol) if self.subprotocol
120
- hash.merge!('Sec-WebSocket-Origin' => origin)
121
- hash.merge!('Sec-WebSocket-Location' => location.to_s)
122
- end
123
-
124
- unless self.cookies.empty?
125
- hash.merge!('Set-Cookie' => self.cookies.collect(&:to_s).join(','))
126
- end
127
-
128
- body = self.checksum if self.version > 75
129
-
130
- hash.merge!('Content-Length' => body.length.to_s)
131
-
132
- return [ status, hash, [ body ]]
133
- end
134
-
135
- # Build cookies from hash
136
- # @see LibWebSocket::Cookie
137
- def cookie=(hash)
138
- self.cookies.push self.build_cookie(hash)
139
- end
140
-
141
- # Draft 76 number 1 reader
142
- def number1
143
- self.number('number1','key1')
144
- end
145
- # Draft 76 number 1 writter
146
- def number1=(val)
147
- self.number('number1','key1',val)
148
- end
149
- # Draft 76 number 2 reader
150
- def number2
151
- self.number('number2','key2')
152
- end
153
- # Draft 76 number 2 writter
154
- def number2=(val)
155
- self.number('number2','key2',val)
156
- end
157
-
158
- protected
159
-
160
- def parse_first_line(line)
161
- unless line =~ /\AHTTP\/1.1 101 .+/
162
- self.error = 'Wrong response line'
163
- return
164
- end
165
-
166
- return self
167
- end
168
-
169
- def parse_body
170
- if self.field('Sec-WebSocket-Origin')
171
- return true if @buffer.length < 16
172
-
173
- self.version = 76
174
-
175
- checksum = @buffer.slice!(0..15)
176
- self.checksum = checksum
177
- else
178
- self.version = 75
179
- end
180
-
181
- return self if self.finalize
182
-
183
- self.error = 'Not a valid response'
184
- return
185
- end
186
-
187
- def finalize
188
- location = self.field('Sec-WebSocket-Location') || self.field('WebSocket-Location')
189
- return unless location
190
- self.location = location
191
-
192
- url = self.build_url
193
- return unless url.parse(self.location)
194
-
195
- self.secure = url.secure
196
- self.host = url.host
197
- self.resource_name = url.resource_name
198
-
199
- self.origin = self.field('Sec-WebSocket-Origin') || self.field('WebSocket-Origin')
200
-
201
- self.subprotocol = self.field('Sec-WebSocket-Protocol') || self.field('WebSocket-Protocol')
202
-
203
- return true
204
- end
205
-
206
- def build_url(hash = {})
207
- URL.new(hash)
208
- end
209
-
210
- def build_cookie(hash = {})
211
- Cookie::Response.new(hash)
212
- end
213
-
214
- end
215
- end
@@ -1,24 +0,0 @@
1
- module LibWebSocket
2
- # Base class for all classes with states
3
- module Stateful
4
-
5
- attr_accessor :state
6
-
7
- # Return true if current state match given state
8
- def state?(val)
9
- @state == val
10
- end
11
-
12
- # Change state to 'done'
13
- def done
14
- @state = 'done'
15
- true
16
- end
17
-
18
- # Check if current state is done
19
- def done?
20
- @state == 'done'
21
- end
22
-
23
- end
24
- end
@@ -1,68 +0,0 @@
1
- require 'addressable/uri'
2
-
3
- module LibWebSocket
4
- # Construct or parse a WebSocket URL.
5
- class URL
6
-
7
- attr_accessor :secure, :host, :port, :resource_name
8
-
9
- def initialize(hash = {})
10
- hash.each do |k,v|
11
- instance_variable_set("@#{k}",v)
12
- end
13
-
14
- @secure ||= false
15
- end
16
-
17
- # Parse a WebSocket URL.
18
- # @example Parse
19
- # url = LibWebSocket::URL.new
20
- # url.parse('wss://example.com:3000')
21
- # url.host # => example.com
22
- # url.port # => 3000
23
- # url.secure # => true
24
- def parse(string)
25
- return nil unless string.is_a?(String)
26
-
27
- uri = Addressable::URI.parse(string)
28
-
29
- scheme = uri.scheme
30
- return nil unless scheme
31
-
32
- self.secure = true if scheme.match(/ss\Z/m)
33
-
34
- host = uri.host
35
- host = '/' unless host && host != ''
36
- self.host = host
37
- self.port = uri.port.to_s if uri.port
38
-
39
- request_uri = uri.path
40
- request_uri = '/' unless request_uri && request_uri != ''
41
- request_uri += "?" + uri.query if uri.query
42
- self.resource_name = request_uri
43
-
44
- return self
45
- end
46
-
47
- # Construct a WebSocket URL.
48
- # @example Construct
49
- # url = LibWebSocket::URL.new
50
- # url.host = 'example.com'
51
- # url.port = '3000'
52
- # url.secure = true
53
- # url.to_s # => 'wss://example.com:3000'
54
- def to_s
55
- string = ''
56
-
57
- string += 'ws'
58
- string += 's' if self.secure
59
- string += '://'
60
- string += self.host
61
- string += ':' + self.port.to_s if self.port
62
- string += self.resource_name || '/'
63
-
64
- return string
65
- end
66
-
67
- end
68
- end
@@ -1,37 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestCookieRequest < Test::Unit::TestCase
4
-
5
- def test_parse
6
- cookie = LibWebSocket::Cookie::Request.new
7
- cookies = cookie.parse('$Version=1; foo=bar; $Path=/; $Domain=.example.com')
8
- assert_equal 'foo', cookies[0].name
9
- assert_equal 'bar', cookies[0].value
10
- assert_equal 1, cookies[0].version
11
- assert_equal '/', cookies[0].path
12
- assert_equal '.example.com', cookies[0].domain
13
-
14
- cookie = LibWebSocket::Cookie::Request.new
15
- cookies = cookie.parse('$Version=1; foo=bar')
16
- assert_equal 'foo', cookies[0].name
17
- assert_equal 'bar', cookies[0].value
18
- assert_equal 1, cookies[0].version
19
- assert_equal nil, cookies[0].path
20
- assert_equal nil, cookies[0].domain
21
-
22
- cookie = LibWebSocket::Cookie::Request.new
23
- cookies = cookie.parse('$Version=1; foo="hello\"there"')
24
- assert_equal 'foo', cookies[0].name
25
- assert_equal 'hello"there', cookies[0].value
26
-
27
- cookie = LibWebSocket::Cookie::Request.new
28
- cookies = cookie.parse('$Version=1; foo="bar"; $Path=/; bar=baz; $Domain=.example.com')
29
- assert_equal 'foo', cookies[0].name
30
- assert_equal 'bar', cookies[0].value
31
- assert_equal '/', cookies[0].path
32
- assert_equal 'bar', cookies[1].name
33
- assert_equal 'baz', cookies[1].value
34
- assert_equal '.example.com', cookies[1].domain
35
- end
36
-
37
- end
@@ -1,32 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestCookieResponse < Test::Unit::TestCase
4
-
5
- def test_to_s
6
- cookie = LibWebSocket::Cookie::Response.new(:name => 'foo', :value => 'bar')
7
- assert_equal 'foo=bar; Version=1', cookie.to_s
8
-
9
- cookie = LibWebSocket::Cookie::Response.new(
10
- :name => 'foo',
11
- :value => 'bar',
12
- :discard => 1,
13
- :max_age => 0
14
- )
15
- assert_equal 'foo=bar; Discard; Max-Age=0; Version=1', cookie.to_s
16
-
17
- cookie = LibWebSocket::Cookie::Response.new(
18
- :name => 'foo',
19
- :value => 'bar',
20
- :portlist => 80
21
- )
22
- assert_equal 'foo=bar; Port="80"; Version=1', cookie.to_s
23
-
24
- cookie = LibWebSocket::Cookie::Response.new(
25
- :name => 'foo',
26
- :value => 'bar',
27
- :portlist => [80, 443]
28
- )
29
- assert_equal 'foo=bar; Port="80 443"; Version=1', cookie.to_s
30
- end
31
-
32
- end
@@ -1,22 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestCookie < Test::Unit::TestCase
4
-
5
- def test_parse
6
- cookie = LibWebSocket::Cookie.new
7
- assert_nil cookie.parse
8
- assert_nil cookie.parse('')
9
- assert cookie.parse('foo=bar; baz = zab; hello= "the;re"; here')
10
- assert_equal [['foo', 'bar'], ['baz', 'zab'], ['hello', 'the;re'], ['here', nil]], cookie.pairs
11
- assert_equal 'foo=bar; baz=zab; hello="the;re"; here', cookie.to_s
12
-
13
- cookie = LibWebSocket::Cookie.new
14
- cookie.parse('$Foo="bar"')
15
- assert_equal [['$Foo', 'bar']], cookie.pairs
16
-
17
- cookie = LibWebSocket::Cookie.new
18
- cookie.parse('foo=bar=123=xyz')
19
- assert_equal [['foo', 'bar=123=xyz']], cookie.pairs
20
- end
21
-
22
- end
@@ -1,16 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestMessage < Test::Unit::TestCase
4
-
5
- def test_parse
6
- m = LibWebSocket::Message.new
7
- assert m.parse("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a")
8
- assert m.parse("Upgrade: WebSocket\x0d\x0a")
9
- assert m.parse("Connection: Upgrade\x0d\x0a")
10
- assert m.parse("Sec-WebSocket-Origin: file://\x0d\x0a")
11
- assert m.parse("Sec-WebSocket-Location: ws://example.com/demo\x0d\x0a")
12
- assert m.parse("\x0d\x0a0st\x0d\x0al&q-2ZU^weu")
13
- assert m.done?
14
- end
15
-
16
- end
@@ -1,145 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestRequest75 < Test::Unit::TestCase
4
-
5
- def test_parse
6
- req = LibWebSocket::Request.new
7
- assert !req.done?
8
- assert req.parse('')
9
- assert req.parse("GET /demo HTTP/1.1\x0d\x0a")
10
- assert_equal 'fields', req.state
11
-
12
- assert req.parse("Upgrade: WebSocket\x0d\x0a")
13
- assert_equal 'fields', req.state
14
- assert req.parse("Connection: Upgrade\x0d\x0a")
15
- assert_equal 'fields', req.state
16
- assert req.parse("Host: example.com\x0d\x0a")
17
- assert_equal 'fields', req.state
18
- assert req.parse("Origin: http://example.com\x0d\x0a")
19
- assert_equal 'fields', req.state
20
- assert req.parse("\x0d\x0a")
21
- assert_equal 'done', req.state
22
-
23
- assert_equal 75, req.version
24
- assert_equal '/demo', req.resource_name
25
- assert_equal 'example.com', req.host
26
- assert_equal 'http://example.com', req.origin
27
-
28
- req = LibWebSocket::Request.new
29
- assert req.parse("GET /demo HTTP/1.1\x0d\x0a")
30
- assert req.parse("Upgrade: WebSocket\x0d\x0a")
31
- assert req.parse("Connection: Upgrade\x0d\x0a")
32
- assert req.parse("Host: example.com:3000\x0d\x0a")
33
- assert req.parse("Origin: null\x0d\x0a")
34
- assert req.parse("\x0d\x0a")
35
- assert_equal 75, req.version
36
- assert_equal 'done', req.state
37
-
38
- req = LibWebSocket::Request.new
39
- assert req.parse("GET /demo HTTP/1.1\x0d\x0a")
40
- assert req.parse("UPGRADE: WebSocket\x0d\x0a")
41
- assert req.parse("CONNECTION: Upgrade\x0d\x0a")
42
- assert req.parse("HOST: example.com:3000\x0d\x0a")
43
- assert req.parse("ORIGIN: null\x0d\x0a")
44
- assert req.parse("\x0d\x0a")
45
- assert_equal 75, req.version
46
- assert_equal 'done', req.state
47
-
48
- req = LibWebSocket::Request.new
49
- assert req.parse("GET /demo HTTP/1.1\x0d\x0a")
50
- assert req.parse("Upgrade: WebSocket\x0d\x0a")
51
- assert req.parse("Connection: Upgrade\x0d\x0a")
52
- assert req.parse("Host: example.com:3000\x0d\x0a")
53
- assert req.parse("Origin: null\x0d\x0a")
54
- assert req.parse("WebSocket-Protocol: sample\x0d\x0a")
55
- assert req.parse("\x0d\x0a")
56
- assert_equal 75, req.version
57
- assert_equal 'done', req.state
58
- assert_equal 'sample', req.subprotocol
59
-
60
- req = LibWebSocket::Request.new
61
- message = "GET /demo HTTP/1.1\x0d\x0a" +
62
- "Upgrade: WebSocket\x0d\x0a" +
63
- "Connection: Upgrade\x0d\x0a"
64
- assert req.parse(message)
65
- message = "Host: example.com:3000\x0d\x0a" + "Origin: null\x0d\x0a" + "\x0d\x0a"
66
- assert req.parse(message)
67
- assert_equal 75, req.version
68
- assert req.done?
69
-
70
- req = LibWebSocket::Request.new
71
- assert req.parse("GET /demo HTTP/1.1\x0d\x0a")
72
- assert req.parse("Upgrade: WebSocket\x0d\x0a")
73
- assert req.parse("Connection: Upgrade\x0d\x0a")
74
- assert req.parse("Host: example.com\x0d\x0a")
75
- assert req.parse("Origin: null\x0d\x0a")
76
- assert req.parse("cookie: \$Version=1; foo=bar; \$Path=/\x0d\x0a")
77
- assert req.parse("\x0d\x0a")
78
- assert req.done?
79
-
80
- assert_equal req.cookies[0].version, '1'
81
- assert_equal req.cookies[0].name, 'foo'
82
- assert_equal req.cookies[0].value, 'bar'
83
-
84
- req = LibWebSocket::Request.new
85
- assert req.parse("GET /demo HTTP/1.1\x0d\x0a")
86
- assert req.parse("Upgrade: WebSocket\x0d\x0a")
87
- assert req.parse("Connection: Bar\x0d\x0a")
88
- assert req.parse("Host: example.com\x0d\x0a")
89
- assert req.parse("Origin: http://example.com\x0d\x0a")
90
- assert_nil req.parse("\x0d\x0a")
91
- assert_equal 'error', req.state
92
- assert_equal 'Not a valid request', req.error
93
-
94
- req = LibWebSocket::Request.new
95
- assert req.parse("GET /demo HTTP/1.1\x0d\x0a")
96
- assert req.parse("Upgrade: WebSocket\x0d\x0a")
97
- assert req.parse("Connection: Upgrade\x0d\x0a")
98
- assert req.parse("Host: example.com\x0d\x0a")
99
- assert req.parse("Origin: http://example.com\x0d\x0a")
100
- assert_nil req.parse("\x0d\x0afoo")
101
- assert_equal 'error', req.state
102
- assert_equal 'Leftovers', req.error
103
- end
104
-
105
- def test_to_s
106
- req = LibWebSocket::Request.new(
107
- :version => 75,
108
- :host => 'example.com',
109
- :resource_name => '/demo'
110
- )
111
- assert_equal req.to_s, "GET /demo HTTP/1.1\x0d\x0a" +
112
- "Upgrade: WebSocket\x0d\x0a" +
113
- "Connection: Upgrade\x0d\x0a" +
114
- "Host: example.com\x0d\x0a" +
115
- "Origin: http://example.com\x0d\x0a" +
116
- "\x0d\x0a"
117
-
118
- req = LibWebSocket::Request.new(
119
- :version => 75,
120
- :host => 'example.com',
121
- :subprotocol => 'sample',
122
- :resource_name => '/demo'
123
- )
124
- assert_equal req.to_s, "GET /demo HTTP/1.1\x0d\x0a" +
125
- "Upgrade: WebSocket\x0d\x0a" +
126
- "Connection: Upgrade\x0d\x0a" +
127
- "Host: example.com\x0d\x0a" +
128
- "Origin: http://example.com\x0d\x0a" +
129
- "WebSocket-Protocol: sample\x0d\x0a" +
130
- "\x0d\x0a"
131
-
132
- req = LibWebSocket::Request.new(
133
- :version => 75,
134
- :host => 'example.com',
135
- :resource_name => '/demo'
136
- );
137
- assert_equal req.to_s, "GET /demo HTTP/1.1\x0d\x0a" +
138
- "Upgrade: WebSocket\x0d\x0a" +
139
- "Connection: Upgrade\x0d\x0a" +
140
- "Host: example.com\x0d\x0a" +
141
- "Origin: http://example.com\x0d\x0a" +
142
- "\x0d\x0a"
143
- end
144
-
145
- end