em-midori 0.0.6 → 0.0.7
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CONTRIBUTE_CODE_OF_CONDUCT.md +49 -0
- data/lib/em-midori.rb +5 -2
- data/lib/em-midori/api.rb +25 -26
- data/lib/em-midori/clean_room.rb +3 -3
- data/lib/em-midori/const.rb +41 -41
- data/lib/em-midori/define_class.rb +2 -2
- data/lib/em-midori/em_midori.rb +2 -4
- data/lib/em-midori/error.rb +2 -1
- data/lib/em-midori/request.rb +3 -7
- data/lib/em-midori/response.rb +2 -2
- data/lib/em-midori/route.rb +1 -1
- data/lib/em-midori/server.rb +29 -37
- data/lib/em-midori/{debug.rb → string.rb} +1 -9
- data/lib/em-midori/version.rb +2 -2
- data/lib/em-midori/websocket.rb +65 -53
- metadata +6 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2125fd6cda987cb74946857e89100347e12fa381
|
4
|
+
data.tar.gz: 767c573b0d050352009ee0167a812b31c476d557
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5dd730b49d12ff2b8c5c0a645f37f47d4c75b0dcb63af9f0c76f713735d4bd89ab6b8aa084af0ddb97163be91688bbcd209115a07422669410b4a62c270123cf
|
7
|
+
data.tar.gz: b4f5885dc1047d3b35af853c5ec766728df19c0af55278e80057c4994d68c378826882f7055e775f88cef3aad402638b0dc3008671e904b8a98e07f88c0cec7f
|
data/.travis.yml
CHANGED
@@ -5,7 +5,7 @@ rvm:
|
|
5
5
|
- 2.3.1
|
6
6
|
- jruby-head
|
7
7
|
- jruby-9.0.4.0
|
8
|
-
- rbx-3.
|
8
|
+
- rbx-3.59
|
9
9
|
|
10
10
|
jdk:
|
11
11
|
- openjdk7
|
@@ -17,11 +17,11 @@ matrix:
|
|
17
17
|
jdk: openjdk7
|
18
18
|
- rvm: 2.3.1
|
19
19
|
jdk: openjdk7
|
20
|
-
- rvm: rbx-3.
|
20
|
+
- rvm: rbx-3.59
|
21
21
|
jdk: openjdk7
|
22
22
|
allow_failures:
|
23
23
|
- rvm: jruby-head
|
24
|
-
- rvm: rbx-3.
|
24
|
+
- rvm: rbx-3.59
|
25
25
|
|
26
26
|
os:
|
27
27
|
- linux
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at delton@heckpsi.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/lib/em-midori.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'digest/sha1'
|
2
|
+
require 'stringio'
|
3
|
+
require 'eventmachine'
|
4
|
+
|
2
5
|
require 'em-midori/version'
|
3
|
-
require 'em-midori/
|
6
|
+
require 'em-midori/string'
|
4
7
|
require 'em-midori/const'
|
5
8
|
require 'em-midori/define_class'
|
6
9
|
require 'em-midori/error'
|
@@ -11,4 +14,4 @@ require 'em-midori/response'
|
|
11
14
|
require 'em-midori/api'
|
12
15
|
require 'em-midori/route'
|
13
16
|
require 'em-midori/server'
|
14
|
-
require 'em-midori/websocket'
|
17
|
+
require 'em-midori/websocket'
|
data/lib/em-midori/api.rb
CHANGED
@@ -163,7 +163,7 @@ class Midori::API
|
|
163
163
|
# === Returns
|
164
164
|
# nil
|
165
165
|
def add_route(method, path, block)
|
166
|
-
@route =
|
166
|
+
@route = [] if @route.nil?
|
167
167
|
if path.class == String
|
168
168
|
# Convert String to Regexp to provide performance boost (Precompiled Regexp)
|
169
169
|
path = convert_route path
|
@@ -177,28 +177,27 @@ class Midori::API
|
|
177
177
|
# * +request+ [+StringIO+] - Http Raw Request
|
178
178
|
# === Returns
|
179
179
|
# [+Midori::Response+] - Http response
|
180
|
-
def receive(request, connection=nil)
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
end
|
197
|
-
clean_room.body = result if result.class == String
|
198
|
-
return clean_room.response
|
199
|
-
end
|
180
|
+
def receive(request, connection = nil)
|
181
|
+
@route.each do |route|
|
182
|
+
matched = match(route.method, route.path, request.method, request.path)
|
183
|
+
next unless matched
|
184
|
+
clean_room = Midori::CleanRoom.new(request)
|
185
|
+
if request.websocket?
|
186
|
+
# Send 101 Switching Protocol
|
187
|
+
connection.send_data Midori::Response.new(101, {
|
188
|
+
'Upgrade' => 'websocket',
|
189
|
+
'Connection' => 'Upgrade',
|
190
|
+
'Sec-WebSocket-Accept' => Digest::SHA1.base64digest(request.header['Sec-WebSocket-Key'] + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
|
191
|
+
}, '')
|
192
|
+
result = -> { clean_room.instance_exec(connection.websocket, *matched, &route.function) }.call
|
193
|
+
return Midori::Response.new
|
194
|
+
else
|
195
|
+
result = -> { clean_room.instance_exec(*matched, &route.function) }.call
|
200
196
|
end
|
201
|
-
|
197
|
+
clean_room.body = result if result.class == String
|
198
|
+
return clean_room.response
|
199
|
+
end
|
200
|
+
raise Midori::Error::NotFound
|
202
201
|
end
|
203
202
|
|
204
203
|
# Match route with given definition
|
@@ -231,8 +230,8 @@ class Midori::API
|
|
231
230
|
# convert_route('/user/:id/order/:order_id') # => Regexp
|
232
231
|
def convert_route(path)
|
233
232
|
path = '^' + path
|
234
|
-
|
235
|
-
|
233
|
+
.gsub(/\/(:[_a-z][_a-z0-9]+?)\//, '/([^/]+?)/')
|
234
|
+
.gsub(/\/(:[_a-z][_a-z0-9]+?)$/, '/([^/]+?)$')
|
236
235
|
path += '$' if path[-1] != '$'
|
237
236
|
Regexp.new path
|
238
237
|
end
|
@@ -240,12 +239,12 @@ class Midori::API
|
|
240
239
|
|
241
240
|
private_class_method :add_route
|
242
241
|
|
243
|
-
METHODS = %w
|
242
|
+
METHODS = %w(get post put delete options link unlink websocket eventsource).freeze # :nodoc:
|
244
243
|
|
245
244
|
# Magics to fill DSL methods through dynamically class method definition
|
246
245
|
METHODS.each do |method|
|
247
246
|
define_singleton_method(method) do |*args, &block|
|
248
|
-
add_route(method.upcase, args[0], block) #args[0]: path
|
247
|
+
add_route(method.upcase, args[0], block) # args[0]: path
|
249
248
|
end
|
250
249
|
end
|
251
250
|
end
|
data/lib/em-midori/clean_room.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
class CleanRoom
|
1
|
+
class Midori::CleanRoom
|
2
2
|
attr_accessor :code, :header, :body, :request
|
3
3
|
def initialize(request)
|
4
4
|
@status = 200
|
5
|
-
@header =
|
5
|
+
@header = Midori::Const::DEFAULT_HEADER.clone
|
6
6
|
@body = ''
|
7
7
|
@request = request
|
8
8
|
end
|
@@ -10,4 +10,4 @@ class CleanRoom
|
|
10
10
|
def response
|
11
11
|
Midori::Response.new(@status, @header, @body)
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
data/lib/em-midori/const.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
1
|
module Midori::Const
|
2
2
|
STATUS_CODE = {
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
3
|
+
100 => '100 Continue',
|
4
|
+
101 => '101 Switching Protocols',
|
5
|
+
200 => '200 OK',
|
6
|
+
201 => '201 Created',
|
7
|
+
202 => '202 Accepted',
|
8
|
+
203 => '203 Non-Authoritative Information',
|
9
|
+
204 => '204 No Content',
|
10
|
+
205 => '205 Reset Content',
|
11
|
+
206 => '206 Partial Content',
|
12
|
+
300 => '300 Multiple Choices',
|
13
|
+
301 => '301 Moved Permanently',
|
14
|
+
304 => '304 Not Modified',
|
15
|
+
305 => '305 Use Proxy',
|
16
|
+
307 => '307 Temporary Redirect',
|
17
|
+
400 => '400 Bad Request',
|
18
|
+
401 => '401 Unauthorized',
|
19
|
+
402 => '402 Payment Required',
|
20
|
+
403 => '403 Forbidden',
|
21
|
+
404 => '404 Not Found',
|
22
|
+
405 => '405 Method Not Allowed',
|
23
|
+
406 => '406 Not Acceptable',
|
24
|
+
407 => '407 Proxy Authentication Required',
|
25
|
+
408 => '408 Request Time-out',
|
26
|
+
409 => '409 Conflict',
|
27
|
+
410 => '410 Gone',
|
28
|
+
411 => '411 Length Required',
|
29
|
+
412 => '412 Precondition Failed',
|
30
|
+
413 => '413 Request Entity Too Large',
|
31
|
+
414 => '414 Request-URI Too Large',
|
32
|
+
415 => '415 Unsupported Media Type',
|
33
|
+
416 => '416 Requested range not satisfiable',
|
34
|
+
417 => '417 Expectation Failed',
|
35
|
+
500 => '500 Internal Server Error',
|
36
|
+
501 => '501 Not Implemented',
|
37
|
+
502 => '502 Bad Gateway',
|
38
|
+
503 => '503 Service Unavailable',
|
39
|
+
504 => '504 Gateway Time-out',
|
40
|
+
505 => '505 HTTP Version not supported'
|
41
41
|
}
|
42
|
-
STATUS_CODE.default= '500 Internal Server Error'
|
42
|
+
STATUS_CODE.default = '500 Internal Server Error'
|
43
43
|
STATUS_CODE.freeze
|
44
44
|
|
45
45
|
DEFAULT_HEADER = {
|
46
|
-
|
46
|
+
'Server' => "Midori/#{Midori::VERSION}"
|
47
47
|
}
|
48
|
-
end
|
48
|
+
end
|
@@ -9,8 +9,8 @@ module Kernel #:nodoc:
|
|
9
9
|
|
10
10
|
def define_error(*args)
|
11
11
|
args.each do |arg|
|
12
|
-
class_name = arg.to_s.split('_').map {|word| word[0] = word[0].upcase; word}.join
|
12
|
+
class_name = arg.to_s.split('_').map { |word| word[0] = word[0].upcase; word }.join
|
13
13
|
define_class(class_name, StandardError)
|
14
14
|
end
|
15
15
|
end
|
16
|
-
end
|
16
|
+
end
|
data/lib/em-midori/em_midori.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
|
3
1
|
module Midori
|
4
|
-
def self.run(api=Midori::API, ip=nil, port=nil)
|
2
|
+
def self.run(api = Midori::API, ip = nil, port = nil)
|
5
3
|
ip ||= '127.0.0.1'
|
6
4
|
port ||= 8081
|
7
5
|
EventMachine.run do
|
@@ -21,4 +19,4 @@ module Midori
|
|
21
19
|
return true
|
22
20
|
end
|
23
21
|
end
|
24
|
-
end
|
22
|
+
end
|
data/lib/em-midori/error.rb
CHANGED
data/lib/em-midori/request.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
|
3
1
|
class Midori::Request
|
4
2
|
attr_accessor :ip, :port,
|
5
3
|
:protocol, :method, :path, :query_string,
|
@@ -15,16 +13,14 @@ class Midori::Request
|
|
15
13
|
# === Attributes
|
16
14
|
# * +data+ [+StringIO+] - Request data
|
17
15
|
def parse(data)
|
18
|
-
@header =
|
16
|
+
@header = {}
|
19
17
|
|
20
18
|
# Parse request
|
21
19
|
line = data.gets.split
|
22
20
|
@protocol = line[2]
|
23
21
|
@method = line[0]
|
24
22
|
@query_string = line[1].match(/\?(.*?)$/)
|
25
|
-
unless @query_string.nil?
|
26
|
-
@query_string = @query_string[1]
|
27
|
-
end
|
23
|
+
@query_string = @query_string[1] unless @query_string.nil?
|
28
24
|
@path = line[1].gsub(/\?(.*?)$/, '')
|
29
25
|
|
30
26
|
# Parse header
|
@@ -61,4 +57,4 @@ class Midori::Request
|
|
61
57
|
def eventsource?
|
62
58
|
@is_eventsource
|
63
59
|
end
|
64
|
-
end
|
60
|
+
end
|
data/lib/em-midori/response.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Midori::Response
|
2
2
|
attr_accessor :status, :header, :body
|
3
3
|
|
4
|
-
def initialize(code=200, header= Midori::Const::DEFAULT_HEADER, body='')
|
4
|
+
def initialize(code = 200, header = Midori::Const::DEFAULT_HEADER.clone, body = '')
|
5
5
|
@status = Midori::Const::STATUS_CODE[code]
|
6
6
|
@header = header
|
7
7
|
@body = body
|
@@ -16,4 +16,4 @@ class Midori::Response
|
|
16
16
|
def to_s
|
17
17
|
"HTTP/1.1 #{@status}\r\n#{generate_header}\r\n#{@body}"
|
18
18
|
end
|
19
|
-
end
|
19
|
+
end
|
data/lib/em-midori/route.rb
CHANGED
data/lib/em-midori/server.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
|
3
1
|
module Midori::Server
|
4
2
|
attr_accessor :request, :api, :websocket
|
5
3
|
|
@@ -20,59 +18,53 @@ module Midori::Server
|
|
20
18
|
else
|
21
19
|
receive_new_request(data)
|
22
20
|
end
|
23
|
-
|
21
|
+
puts "#{@request.ip} - - [#{Time.now.inspect}] \"#{@request.method} #{@request.path} #{@request.protocol}\" #{@response.status} #{(Time.now.to_f - start_time.to_f).round(5)}".green
|
24
22
|
end
|
25
23
|
|
26
24
|
def receive_new_request(data)
|
27
25
|
begin
|
28
26
|
@request.parse(data)
|
29
27
|
@response = @api.receive(request, self)
|
28
|
+
call_event(:open) if @request.websocket?
|
30
29
|
rescue Midori::Error::NotFound => _e
|
31
30
|
@response = Midori::Response.new(404, {}, '404 Not Found')
|
32
31
|
rescue => e
|
33
32
|
@response = Midori::Response.new(500, {}, 'Internal Server Error')
|
34
|
-
puts e.inspect.
|
33
|
+
puts e.inspect.red
|
34
|
+
puts e.backtrace.join("\n").yellow
|
35
35
|
end
|
36
|
-
unless
|
36
|
+
unless @request.websocket? || @request.eventsource?
|
37
37
|
send_data @response
|
38
38
|
close_connection_after_writing
|
39
39
|
end
|
40
|
-
if @request.websocket? && !@websocket.events[:open].nil?
|
41
|
-
call_event(:open)
|
42
|
-
end
|
43
40
|
end
|
44
41
|
|
45
42
|
def websocket_request(data)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
call_event(:pong)
|
56
|
-
else
|
57
|
-
# Unknown Control Frame
|
58
|
-
raise Midori::Error::FrameEnd
|
59
|
-
end
|
60
|
-
rescue Midori::Error::FrameEnd => _e
|
61
|
-
unless @websocket.events[:close].nil?
|
62
|
-
call_event(:close)
|
63
|
-
end
|
64
|
-
send_data "\b" # Opcode 0x8
|
65
|
-
close_connection_after_writing
|
66
|
-
rescue => e
|
67
|
-
puts e.inspect.yellow
|
68
|
-
@response = Midori::Response.new(400, {}, 'Bad Request')
|
69
|
-
send_data @response
|
70
|
-
close_connection_after_writing
|
43
|
+
@websocket.decode(data)
|
44
|
+
case @websocket.opcode
|
45
|
+
when 0x1, 0x2
|
46
|
+
call_event(:message, [@websocket.msg])
|
47
|
+
when 0x9
|
48
|
+
@websocket.pong(@websocket.msg)
|
49
|
+
call_event(:ping)
|
50
|
+
when 0xA
|
51
|
+
call_event(:pong)
|
71
52
|
end
|
53
|
+
rescue Midori::Error::FrameEnd => _e
|
54
|
+
call_event(:close)
|
55
|
+
send_data "\b" # Opcode 0x8
|
56
|
+
close_connection_after_writing
|
57
|
+
rescue Midori::Error::PingPongSizeTooLarge => e
|
58
|
+
puts e.inspect.yellow
|
59
|
+
call_event(:error) # Neglect Too large ping request
|
60
|
+
rescue => e
|
61
|
+
call_event(:error)
|
62
|
+
puts e.inspect.red
|
63
|
+
puts e.backtrace.join("\n").yellow
|
64
|
+
close_connection_after_writing
|
72
65
|
end
|
73
66
|
|
74
|
-
def call_event(event, args=[])
|
75
|
-
|
67
|
+
def call_event(event, args = [])
|
68
|
+
(-> { @websocket.instance_exec(*args, &@websocket.events[event]) }.call) unless @websocket.events[event].nil?
|
76
69
|
end
|
77
|
-
|
78
|
-
end
|
70
|
+
end
|
data/lib/em-midori/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Midori
|
2
|
-
VERSION = '0.0.
|
3
|
-
end
|
2
|
+
VERSION = '0.0.7'.freeze
|
3
|
+
end
|
data/lib/em-midori/websocket.rb
CHANGED
@@ -1,63 +1,75 @@
|
|
1
|
+
##
|
2
|
+
# This class provides methods for WebSocket connection instance.
|
1
3
|
class Midori::WebSocket
|
2
|
-
|
4
|
+
attr_accessor :msg, :opcode, :events, :connection
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def initialize(connection)
|
7
|
+
@events = {}
|
8
|
+
@connection = connection
|
9
|
+
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
def decode(data)
|
12
|
+
# Fin and Opcode
|
13
|
+
byte_tmp = data.getbyte
|
14
|
+
fin = byte_tmp & 0b10000000
|
15
|
+
@opcode = byte_tmp & 0b00001111
|
16
|
+
# NOT Support Multiple Fragments
|
17
|
+
raise Midori::Error::ContinuousFrame unless fin
|
18
|
+
raise Midori::Error::OpCodeError unless [0x1, 0x2, 0x8, 0x9, 0xA].include?opcode
|
19
|
+
close if @opcode == 0x8 # Close Frame
|
20
|
+
# return if @opcode == 0x9 || @opcode == 0xA # Ping Pong
|
21
|
+
decode_mask(data)
|
22
|
+
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
def decode_mask(data)
|
25
|
+
# Mask
|
26
|
+
byte_tmp = data.getbyte
|
27
|
+
is_masked = byte_tmp & 0b10000000
|
28
|
+
raise Midori::Error::NotMasked unless is_masked == 128
|
29
|
+
# Payload
|
30
|
+
payload = byte_tmp & 0b01111111
|
31
|
+
mask = Array.new(4) { data.getbyte }
|
32
|
+
# Message
|
33
|
+
masked_msg = Array.new(payload) { data.getbyte }
|
34
|
+
@msg = masked_msg.each_with_index.map { |byte, i| byte ^ mask[i % 4] }
|
35
|
+
@msg = @msg.pack('C*').force_encoding('utf-8') if [0x1, 0x9, 0xA].include?opcode
|
36
|
+
# For debug
|
37
|
+
# data.rewind
|
38
|
+
# data.bytes {|byte| puts byte.to_s(16)}
|
39
|
+
end
|
34
40
|
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
def on(event, &block) # open, message, close, ping, pong
|
42
|
+
@events[event] = block
|
43
|
+
end
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
def send(msg)
|
46
|
+
output = []
|
47
|
+
if msg.is_a?String
|
48
|
+
output << 0b10000001 << msg.size << msg
|
49
|
+
@connection.send_data(output.pack("CCA#{msg.size}"))
|
50
|
+
elsif msg.is_a?Array
|
51
|
+
output << 0b10000010 << msg.size
|
52
|
+
output.concat msg
|
53
|
+
@connection.send_data(output.pack("C*"))
|
54
|
+
else
|
55
|
+
raise Midori::Error::OpCodeError
|
50
56
|
end
|
57
|
+
end
|
51
58
|
|
52
|
-
|
53
|
-
|
54
|
-
|
59
|
+
def ping(str)
|
60
|
+
heartbeat(0b10001001, str)
|
61
|
+
end
|
55
62
|
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
def pong(str)
|
64
|
+
heartbeat(0b10001010, str)
|
65
|
+
end
|
59
66
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
67
|
+
def heartbeat(method, str)
|
68
|
+
raise Midori::Error::PingPongSizeTooLarge if str.size > 125
|
69
|
+
@connection.send_data [method, str.size, str].pack("CCA#{str.size}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def close
|
73
|
+
raise Midori::Error::FrameEnd
|
74
|
+
end
|
75
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-midori
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HeckPsi Lab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -30,63 +30,8 @@ dependencies:
|
|
30
30
|
- - ">"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.2.0.0
|
33
|
-
-
|
34
|
-
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '1.0'
|
40
|
-
type: :development
|
41
|
-
prerelease: false
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - "~>"
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '1.0'
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: rake
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '11.2'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - "~>"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '11.2'
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: rspec
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - "~>"
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '3.0'
|
68
|
-
type: :development
|
69
|
-
prerelease: false
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - "~>"
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '3.0'
|
75
|
-
- !ruby/object:Gem::Dependency
|
76
|
-
name: faye-websocket
|
77
|
-
requirement: !ruby/object:Gem::Requirement
|
78
|
-
requirements:
|
79
|
-
- - "~>"
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
version: '0.10'
|
82
|
-
type: :development
|
83
|
-
prerelease: false
|
84
|
-
version_requirements: !ruby/object:Gem::Requirement
|
85
|
-
requirements:
|
86
|
-
- - "~>"
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
version: '0.10'
|
89
|
-
description: An EventMachine Based Web Framework on Ruby
|
33
|
+
description: EM Midori is an EventMachine-based Web Framework written in pure Ruby,
|
34
|
+
providing high performance and proper abstraction.
|
90
35
|
email: business@heckpsi.com
|
91
36
|
executables: []
|
92
37
|
extensions: []
|
@@ -100,12 +45,12 @@ files:
|
|
100
45
|
- ".rspec"
|
101
46
|
- ".rubocop.yml"
|
102
47
|
- ".travis.yml"
|
48
|
+
- CONTRIBUTE_CODE_OF_CONDUCT.md
|
103
49
|
- LICENSE
|
104
50
|
- lib/em-midori.rb
|
105
51
|
- lib/em-midori/api.rb
|
106
52
|
- lib/em-midori/clean_room.rb
|
107
53
|
- lib/em-midori/const.rb
|
108
|
-
- lib/em-midori/debug.rb
|
109
54
|
- lib/em-midori/define_class.rb
|
110
55
|
- lib/em-midori/em_midori.rb
|
111
56
|
- lib/em-midori/error.rb
|
@@ -113,6 +58,7 @@ files:
|
|
113
58
|
- lib/em-midori/response.rb
|
114
59
|
- lib/em-midori/route.rb
|
115
60
|
- lib/em-midori/server.rb
|
61
|
+
- lib/em-midori/string.rb
|
116
62
|
- lib/em-midori/version.rb
|
117
63
|
- lib/em-midori/websocket.rb
|
118
64
|
homepage: https://github.com/heckpsi-lab/em-midori
|
@@ -140,4 +86,3 @@ signing_key:
|
|
140
86
|
specification_version: 4
|
141
87
|
summary: An EventMachine Based Web Framework on Ruby
|
142
88
|
test_files: []
|
143
|
-
has_rdoc:
|