libwebsocket 0.1.5 → 0.1.6

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.
@@ -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