em-midori 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|