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 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: