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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49747119b2524c9b0f81ca22a1c9f27010b880de
4
- data.tar.gz: d32a3a67fd807cdeb7c49d5b7a90aacd24f24f43
3
+ metadata.gz: 2125fd6cda987cb74946857e89100347e12fa381
4
+ data.tar.gz: 767c573b0d050352009ee0167a812b31c476d557
5
5
  SHA512:
6
- metadata.gz: 51732ede10120a05f89e960826aadffb5342efec233eaaff238a9b82c887c905e09cae0357b8c6802f05db0f77e011c709cd0fa2b3bcce366e8aee92297a524e
7
- data.tar.gz: c7e2497cdeed26883d3a5dff6d1195a77c27926ad46e01fd3a0bb556abcdd8bb0f5fd14a7191cbb7c7f881450c23894ff7f5e389db6551a7751fecbfc0976ce3
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.20
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
20
+ - rvm: rbx-3.59
21
21
  jdk: openjdk7
22
22
  allow_failures:
23
23
  - rvm: jruby-head
24
- - rvm: rbx-3.20
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/debug'
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 = Array.new if @route.nil?
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
- @route.each do |route|
182
- matched = match(route.method, route.path, request.method, request.path)
183
- if matched
184
- clean_room = 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 = lambda {clean_room.instance_exec(connection.websocket, *matched, &route.function)}.call
193
- return Midori::Response.new
194
- else
195
- result = lambda {clean_room.instance_exec(*matched, &route.function)}.call
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
- raise Midori::Error::NotFound
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
- .gsub(/\/(:[_a-z][_a-z0-9]+?)\//, '/([^/]+?)/')
235
- .gsub(/\/(:[_a-z][_a-z0-9]+?)$/, '/([^/]+?)$')
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'get post put delete options link unlink websocket eventsource' # :nodoc:
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
@@ -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
@@ -1,48 +1,48 @@
1
1
  module Midori::Const
2
2
  STATUS_CODE = {
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'
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
- "Server" => "Midori/#{Midori::VERSION}"
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
@@ -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
@@ -4,4 +4,5 @@ module Midori::Error
4
4
  class OpCodeError < StandardError; end
5
5
  class NotMasked < StandardError; end
6
6
  class FrameEnd < StandardError; end
7
- end
7
+ class PingPongSizeTooLarge < StandardError; end
8
+ end
@@ -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 = Hash.new
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
@@ -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
@@ -5,4 +5,4 @@ class Midori::Route
5
5
  @path = path
6
6
  @function = function
7
7
  end
8
- end
8
+ end
@@ -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
- $stdout << "#{@request.ip} - - [#{Time.now.inspect}] \"#{@request.method} #{@request.path} #{@request.protocol}\" #{@response.status} #{(Time.now.to_f - start_time.to_f).round(5)}\n".green
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.yellow
33
+ puts e.inspect.red
34
+ puts e.backtrace.join("\n").yellow
35
35
  end
36
- unless (@request.websocket? || @request.eventsource?)
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
- begin
47
- @websocket.decode(data)
48
- case @websocket.opcode
49
- when 0x1, 0x2
50
- call_event(:message, @websocket.msg)
51
- when 0x9
52
- call_event(:ping)
53
- @websocket.pong
54
- when 0xA
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
- lambda {@websocket.instance_exec(*args, &@websocket.events[event])}.call unless @websocket.events[event].nil?
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
@@ -18,12 +18,4 @@ class String
18
18
  def blue
19
19
  colorize(34)
20
20
  end
21
-
22
- def pink
23
- colorize(35)
24
- end
25
-
26
- def light_blue
27
- colorize(36)
28
- end
29
- end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module Midori
2
- VERSION = '0.0.6'.freeze
3
- end
2
+ VERSION = '0.0.7'.freeze
3
+ end
@@ -1,63 +1,75 @@
1
+ ##
2
+ # This class provides methods for WebSocket connection instance.
1
3
  class Midori::WebSocket
2
- attr_accessor :msg, :opcode, :events, :connection
4
+ attr_accessor :msg, :opcode, :events, :connection
3
5
 
4
- def initialize(connection)
5
- @events = Hash.new
6
- @connection = connection
7
- end
6
+ def initialize(connection)
7
+ @events = {}
8
+ @connection = connection
9
+ end
8
10
 
9
- def decode(data)
10
- # Fin and Opcode
11
- byte_tmp = data.getbyte
12
- fin = byte_tmp & 0b10000000
13
- @opcode = byte_tmp & 0b00001111
14
- raise Midori::Error::ContinuousFrame unless fin
15
- raise Midori::Error::OpCodeError unless [0x1, 0x2, 0x8, 0x9, 0xA].include?opcode
16
- raise Midori::Error::FrameEnd if @opcode == 0x8 # Close Frame
17
- return if @opcode == 0x9 || @opcode == 0xA # Ping Pong
18
- decode_mask(data)
19
- end
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
- def decode_mask(data)
22
- # Mask
23
- byte_tmp = data.getbyte
24
- is_masked = byte_tmp & 0b10000000
25
- raise Midori::Error::NotMasked unless is_masked
26
- # Payload
27
- payload = byte_tmp & 0b01111111
28
- mask = 4.times.map {data.getbyte}
29
- # Message
30
- masked_msg = payload.times.map {data.getbyte}
31
- @msg = masked_msg.each_with_index.map {|byte, i| byte ^ mask[i % 4]}
32
- @msg = @msg.pack('C*').force_encoding('utf-8') if @opcode == 0x1
33
- end
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
- def on(event, &block) # open, message, close, ping, pong
36
- @events[event] = block
37
- end
41
+ def on(event, &block) # open, message, close, ping, pong
42
+ @events[event] = block
43
+ end
38
44
 
39
- def send(msg)
40
- output = Array.new
41
- if msg.is_a?String
42
- output << 0b10000001 << msg.size << msg
43
- elsif msg.is_a?Array
44
- output << 0b10000010 << msg.size
45
- output.concat msg
46
- else
47
- raise Midori::Error::OpCodeError
48
- end
49
- @connection.send_data(output.pack("CCA#{msg.size}"))
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
- def ping
53
- @connection.send_data "\t"
54
- end
59
+ def ping(str)
60
+ heartbeat(0b10001001, str)
61
+ end
55
62
 
56
- def pong
57
- @connection.send_data "\n"
58
- end
63
+ def pong(str)
64
+ heartbeat(0b10001010, str)
65
+ end
59
66
 
60
- def close
61
- Midori::Error::FrameEnd
62
- end
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.6
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-06 00:00:00.000000000 Z
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
- - !ruby/object:Gem::Dependency
34
- name: bundler
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: