masyo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ /.bundle
2
+ /vendor/bundles/*
3
+ /tmp/*
4
+ /pkg
5
+
6
+ !.gitkeep
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --colour
3
+ --drb
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+
5
+ script:
6
+ - RAILS_ENV=test bundle exec rspec spec
7
+
8
+ notifications:
9
+ email:
10
+ recipients:
11
+ - toqoz403@gmail.com
12
+ on_success: change
13
+ on_failure: always
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rspec'
7
+ end
8
+
9
+ group :development, :test do
10
+ gem 'pry'
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,33 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ masyo (0.0.1)
5
+ slop
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.0.7)
11
+ diff-lcs (1.1.3)
12
+ method_source (0.8)
13
+ pry (0.9.10)
14
+ coderay (~> 1.0.5)
15
+ method_source (~> 0.8)
16
+ slop (~> 3.3.1)
17
+ rspec (2.11.0)
18
+ rspec-core (~> 2.11.0)
19
+ rspec-expectations (~> 2.11.0)
20
+ rspec-mocks (~> 2.11.0)
21
+ rspec-core (2.11.1)
22
+ rspec-expectations (2.11.3)
23
+ diff-lcs (~> 1.1.3)
24
+ rspec-mocks (2.11.2)
25
+ slop (3.3.3)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ masyo!
32
+ pry
33
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Takatoshi Matsumoto <toqoz403@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is furnished
8
+ to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # Masyo(魔性)
2
+
3
+ ## Description
4
+ Casual TCP Proxy
5
+
6
+ ## Usage
7
+
8
+ ```sh
9
+ $ cd /path-to-masyo
10
+ $ bundle install --path=vendor/bundles
11
+ $ bundle exec ruby bin/masyo -listen_port #{LISTEN_PORT} --server_host #{PROXY_TARGET_HOST} --server_port #{PROXY_TARGET_PORT}
12
+ ```
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/bin/masyo ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require "slop"
5
+ argv = ARGV.dup
6
+ slop = Slop.new(:strict => true, :help => true)
7
+ slop.banner "$ bundle exec ruby bin/masyo [options]\n"
8
+ slop.on :b, :buffer_size=, "buffer byte size(default is 0)"
9
+ slop.on :listen_port=, "listen port (default is 2000)"
10
+ slop.on :server_host=, "target server host (default is \"0.0.0.0\")"
11
+ slop.on :server_port=, "target server port (default is 24224)"
12
+
13
+ begin
14
+ slop.parse!(argv)
15
+ rescue => e
16
+ puts e
17
+ exit!
18
+ end
19
+ options = slop.to_hash
20
+ unless options[:help]
21
+ options.delete(:help)
22
+ options[:listen_port] = (options[:listen_port] || 2000).to_i
23
+ options[:server_host] ||= "0.0.0.0"
24
+ options[:server_port] = (options[:server_port] || 24224).to_i
25
+ options[:buffer_size] = (options[:buffer_size] || 0).to_i
26
+
27
+ root = File.expand_path("../..", __FILE__)
28
+ $LOAD_PATH.unshift root
29
+ $LOAD_PATH.unshift File.join(root, 'lib')
30
+
31
+ require "masyo"
32
+ Masyo.run options
33
+ end
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class TCPSocket
4
+ def close_immediately
5
+ setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_LINGER, [1,0].pack('ii'))
6
+ close
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Masyo
4
+ class BufferOverflowException < StandardError; end
5
+
6
+ class Buffer
7
+ attr_accessor :maxlen, :buffer
8
+
9
+ def initialize(maxlen = 0)
10
+ @maxlen = maxlen
11
+ @buffer = ""
12
+ end
13
+
14
+ def take!
15
+ b = buffer
16
+ clear!
17
+ b
18
+ end
19
+
20
+ def push(str)
21
+ if buffer.bytesize + str.bytesize <= maxlen
22
+ self.buffer += str
23
+ else
24
+ raise BufferOverflowException
25
+ end
26
+ end
27
+ alias_method :<<, :push
28
+
29
+ def clear!
30
+ self.buffer = ""
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,50 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'socket'
4
+
5
+ module Masyo
6
+ class Client
7
+ def initialize(host, port, buffer)
8
+ @host = host
9
+ @port = port
10
+ @buffer = buffer
11
+
12
+ if buffer.maxlen > 0
13
+ extend BufferedClient
14
+ else
15
+ extend PlainClient
16
+ end
17
+ end
18
+
19
+ extend ::Forwardable
20
+ def_delegators :Masyo, :logger
21
+ end
22
+
23
+ module PlainClient
24
+ def post(msg)
25
+ ::TCPSocket.open(@host, @port) { |socket|
26
+ socket.write msg
27
+ }
28
+ end
29
+ end
30
+
31
+ module BufferedClient
32
+ def post(msg)
33
+ ::TCPSocket.open(@host, @port) { |socket|
34
+ begin
35
+ buffer << msg
36
+ rescue BufferOverflowException
37
+ # clear buffer
38
+ socket.write buffer.take!
39
+ begin
40
+ buffer << msg
41
+ rescue BufferOverflowException
42
+ # post without using buffer
43
+ #
44
+ socket.write msg
45
+ end
46
+ end
47
+ }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Masyo
4
+ module Event
5
+
6
+ def self.included(base)
7
+ base.event_types.each do |e|
8
+ base.class_eval {
9
+ define_method("on_#{e}") do |&handler|
10
+ events[e] ||= []
11
+ events[e] << handler
12
+ end
13
+ }
14
+ end
15
+ end
16
+
17
+ def events
18
+ @events ||= {}
19
+ end
20
+
21
+ def trigger_event(name, *arg)
22
+ if events[name]
23
+ events[name].each do |f|
24
+ f.call *arg
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,73 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'socket'
4
+ require 'masyo/event'
5
+
6
+ module Masyo
7
+ class Server
8
+ attr_accessor :tcp_server, :socket_to_client
9
+ TO_CLIENT_SOCKET_TIMEOUT = 3
10
+
11
+ class << self
12
+ def event_types
13
+ [ :read, :close ]
14
+ end
15
+
16
+ def open(*args)
17
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 1..2)" if args.size <= 0 || args.size >= 2
18
+
19
+ server = new(args.first)
20
+ return server unless block_given?
21
+ begin
22
+ yield server
23
+ ensure
24
+ # for sending buffer to server before socket close.
25
+ server.trigger_event :close
26
+ server.close unless server.closed?
27
+ end
28
+ end
29
+ end
30
+
31
+ include Event
32
+
33
+ def initialize(port)
34
+ raise ArgumentError, "#{port} is not a Integer" unless port.is_a? Integer
35
+ @tcp_server = ::TCPServer.new(port)
36
+ end
37
+
38
+ def start
39
+ loop {
40
+ Thread.start(tcp_server.accept) do |to_client|
41
+ handle_request to_client
42
+ end
43
+ }
44
+ end
45
+
46
+ def handle_request(to_client)
47
+ begin
48
+ loop {
49
+ begin
50
+ input = to_client.recv_nonblock(2048)
51
+ rescue ::IO::WaitReadable
52
+ if ::IO.select([ to_client ], nil, nil, TO_CLIENT_SOCKET_TIMEOUT)
53
+ retry
54
+ else
55
+ # timeout!
56
+ break
57
+ end
58
+ else
59
+ break if !input || input == "" || input == "quit"
60
+
61
+ trigger_event :read, input
62
+ end
63
+ }
64
+ ensure
65
+ to_client.close_immediately unless to_client.closed?
66
+ end
67
+ end
68
+
69
+ extend ::Forwardable
70
+ def_delegators :tcp_server, :close, :closed?
71
+ def_delegators :Masyo, :logger
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ module Masyo
2
+ VERSION = "0.0.1"
3
+ end
data/lib/masyo.rb ADDED
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'logger'
4
+ require 'forwardable'
5
+
6
+ require 'masyo/version'
7
+ require 'masyo/server'
8
+ require 'masyo/client'
9
+ require 'masyo/buffer'
10
+ require 'extentions/tcp_socket'
11
+
12
+ module Masyo
13
+ extend self
14
+
15
+ def run(opts = {})
16
+ opts = {
17
+ listen_port: 2000,
18
+ server_host: "0.0.0.0",
19
+ server_port: 24224 ,
20
+ buffer_size: 0
21
+ }.merge(opts)
22
+ Thread.abort_on_exception = true
23
+
24
+ buffer = Buffer.new opts[:buffer_size]
25
+ client = Client.new(opts[:server_host], opts[:server_port], buffer)
26
+ Server.open(opts[:listen_port]) do |server|
27
+ logger.info "listen #{opts[:listen_port]} port."
28
+
29
+ server.on_read do |msg|
30
+ client.post msg
31
+ end
32
+
33
+ server.on_close {
34
+ client.post buffer.take!
35
+ }
36
+
37
+ server.start
38
+ end
39
+ end
40
+
41
+ def logger
42
+ @logger ||= Logger.new STDOUT
43
+ end
44
+ end
data/masyo.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/masyo/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Takatoshi Matsumoto"]
6
+ gem.email = ["toqoz403@gmail.com"]
7
+ gem.description = "simple tcp proxy server written in ruby"
8
+ gem.summary = "masyo"
9
+ gem.homepage = "https://github.com/ToQoz/Masyo"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "masyo"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Masyo::VERSION
17
+
18
+ gem.add_dependency "slop"
19
+ end
data/sample.god ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ God.watch do |w|
4
+ root = File.expand_path("../", __FILE__)
5
+
6
+ w.name = "Masyo"
7
+ w.start = "bundle exec ruby #{File.join(root, 'bin', 'masyo')} --listen_port 2001 --server_host 0.0.0.0 --server_port 24224"
8
+ w.interval = 180.second
9
+ w.keepalive
10
+
11
+ w.start_if do |start|
12
+ start.condition(:process_running) do |c|
13
+ c.running = false
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Masyo::Buffer do
6
+ let (:instance) { described_class.new 100 }
7
+
8
+ describe '#initialize' do
9
+ context 'when given a number for args' do
10
+ it 'should set it to maxlen' do
11
+ described_class.new(100).maxlen.should eq(100)
12
+ end
13
+ end
14
+ context 'when given none for args' do
15
+ it 'should set 0 to maxlen' do
16
+ described_class.new.maxlen.should eq(0)
17
+ end
18
+ end
19
+ end
20
+
21
+ describe '#clear!' do
22
+ it 'should clear buffer' do
23
+ instance.buffer = "toqoz.should be_cool."
24
+ instance.clear!
25
+ instance.buffer.should eq("")
26
+
27
+ end
28
+ end
29
+
30
+ describe '#take!' do
31
+ it 'should return buffer and clear buffer' do
32
+ instance.buffer = "toqoz.should be_cool."
33
+ instance.take!.should eq("toqoz.should be_cool.")
34
+ instance.buffer.should eq("")
35
+ end
36
+ end
37
+
38
+ describe '#push' do
39
+ context 'when given string `don\'t` over buffer' do
40
+ it 'should add string as buffer' do
41
+ str = Array.new(100, "a").join("")
42
+ instance.push str
43
+ instance.buffer.should eq(str)
44
+ end
45
+ end
46
+ context 'when given string over buffer' do
47
+ it 'raise error' do
48
+ proc {
49
+ instance.push Array.new(101, "a").join("")
50
+ }.should raise_error(Masyo::BufferOverflowException)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Masyo::Client do
6
+ describe '#initialize' do
7
+ let(:buffered_client) {
8
+ buffer = double(maxlen: 100)
9
+ described_class.new("0.0.0.0", 8080, buffer)
10
+ }
11
+ let(:plain_client) {
12
+ buffer = double(maxlen: 0)
13
+ described_class.new("0.0.0.0", 8080, buffer)
14
+ }
15
+
16
+ context 'when buffer_size > 0' do
17
+ it 'should use BufferedClient#post as #post' do
18
+ buffered_client.method("post").owner.should eq(Masyo::BufferedClient)
19
+ end
20
+ end
21
+
22
+ context 'when buffer_size == 0' do
23
+ it 'should use PlainClient#post as #post' do
24
+ plain_client.method("post").owner.should eq(Masyo::PlainClient)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#post' do
30
+ let (:instance) { described_class.new("0.0.0.0", 8212, double(maxlen: 10)) }
31
+ it 'should call TCPSocket.open' do
32
+ TCPSocket.should_receive(:open).with(kind_of(String), kind_of(Numeric))
33
+ instance.post("dummy message")
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Masyo::Event do
6
+ let(:instance) do
7
+ mod = described_class
8
+ Class.new {
9
+ class << self
10
+ def event_types
11
+ [ :xxx ]
12
+ end
13
+ end
14
+
15
+ include mod
16
+ }.new
17
+ end
18
+
19
+ describe '.included' do
20
+ context 'when included' do
21
+ it 'define methods for event_types(return by base class methods)' do
22
+ instance.respond_to?(:on_xxx).should be_true
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#on_*' do
28
+ describe '#on_xxx' do
29
+ it 'should store given block as event callback' do
30
+ callback = proc {}
31
+ instance.on_xxx(&callback)
32
+ instance.events.should eq({ xxx: [ callback ] })
33
+ end
34
+ end
35
+ context '#on_invalid_event' do
36
+ it 'should `not` store given block as event callback' do
37
+ proc {
38
+ callback = proc {}
39
+ instance.on_invalid_event(&callback)
40
+ }.should raise_error(NoMethodError)
41
+
42
+ instance.events.should eq({})
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '#trigger_event' do
48
+ context 'when given exist event anme' do
49
+ it 'should trigger all event for #{name}(first args)' do
50
+ callback = proc {}
51
+ callback.should_receive(:call)
52
+ instance.on_xxx(&callback)
53
+ instance.trigger_event :xxx
54
+ end
55
+ end
56
+ context 'when given `not` exist event anme' do
57
+ it 'should not trigger all event for #{name}(first args)' do
58
+ callback = proc {}
59
+ callback.should_not_receive(:call)
60
+ instance.on_invalid_event(&callback) rescue
61
+ instance.trigger_event :invalid_event
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,87 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Masyo::Server do
6
+ let (:instance) { described_class.new(8183) }
7
+ let (:logger) { double(info: true, error: true) }
8
+
9
+ after(:each) do
10
+ instance.close
11
+ end
12
+
13
+ describe '.open' do
14
+ context 'when given over 2 args' do
15
+ it 'should recieve ArgumentError' do
16
+ proc { described_class.open(8183, "hoge", "foo") }.should raise_error(ArgumentError)
17
+ end
18
+ end
19
+ context 'when given non-number value as first arg' do
20
+ it 'should recieve ArgumentError' do
21
+ proc { described_class.open("9090") }.should raise_error(ArgumentError)
22
+ end
23
+ end
24
+ end
25
+
26
+ describe '#initialize' do
27
+ it 'store ::TCPServer as instance variable' do
28
+ instance.tcp_server.is_a?(::TCPServer).should be_true
29
+ end
30
+ end
31
+
32
+ describe '#handle_request' do
33
+ let (:socket) { double(close_immediately: nil, closed?: false) }
34
+
35
+ context 'when BasicSocket#recv_nonblock raise IO::WaitReadable' do
36
+ before :each do
37
+ socket.stub(:recv_nonblock).and_raise(StandardError.new.extend(IO::WaitReadable))
38
+ end
39
+
40
+ it 'should call IO.select.' do
41
+ IO.should_receive(:select).
42
+ with([ socket ], nil, nil, described_class::TO_CLIENT_SOCKET_TIMEOUT).
43
+ and_return(false)
44
+ instance.handle_request(socket)
45
+ end
46
+ end
47
+
48
+ context "when BasicSocket#recv_nonblock don't raise IO::WaitReadable" do
49
+ let (:input) { "dummy_input" }
50
+
51
+ before :each do
52
+ socket.stub(:recv_nonblock).and_return(input, "")
53
+ end
54
+
55
+ context 'and when input is not false, nil, "", "quit"' do
56
+ it 'should call trigger_event with :read as first arg, and input as second arg' do
57
+ instance.should_receive(:trigger_event).with(:read, input)
58
+ proc {
59
+ instance.handle_request(socket)
60
+ }.should_not raise_error
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'when raise Exception except IO::WaitReadable' do
66
+ it 'should close socket and not catch Exceptions.' do
67
+ socket.stub(:recv_nonblock).and_raise(StandardError)
68
+ socket.should_receive(:close_immediately)
69
+
70
+ proc {
71
+ instance.handle_request(socket)
72
+ }.should raise_error(StandardError)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ describe ::TCPServer do
79
+ describe '#close_immediately' do
80
+ it 'should receive setsockopt with relavant options and close' do
81
+ socket = described_class.new(8183)
82
+ socket.should_receive(:setsockopt).with(Socket::SOL_SOCKET, Socket::SO_LINGER, [1,0].pack('ii'))
83
+ socket.should_receive(:close)
84
+ socket.close_immediately
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Masyo do
6
+ describe "#run" do
7
+ before :each do
8
+ Masyo::Buffer.stub(:new)
9
+ Masyo::Client.stub(:new)
10
+ Masyo::Server.stub(:open)
11
+ end
12
+
13
+ it "should set Thread.abort_on_exception = true" do
14
+ Thread.should_receive(:abort_on_exception=).with(true)
15
+ described_class.run
16
+ end
17
+
18
+ it "should call Server.open with port" do
19
+ Masyo::Server.should_receive(:open).with(kind_of(Numeric))
20
+ described_class.run
21
+ end
22
+ end
23
+
24
+ describe "#logger" do
25
+ it 'should return Logger instance.' do
26
+ described_class.logger.is_a?(Logger).should be_true
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "masyo"
data/tmp/.gitkeep ADDED
File without changes
File without changes
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: masyo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Takatoshi Matsumoto
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: slop
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: simple tcp proxy server written in ruby
31
+ email:
32
+ - toqoz403@gmail.com
33
+ executables:
34
+ - masyo
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - .gitignore
39
+ - .rspec
40
+ - .travis.yml
41
+ - Gemfile
42
+ - Gemfile.lock
43
+ - LICENSE
44
+ - README.md
45
+ - Rakefile
46
+ - bin/masyo
47
+ - lib/extentions/tcp_socket.rb
48
+ - lib/masyo.rb
49
+ - lib/masyo/buffer.rb
50
+ - lib/masyo/client.rb
51
+ - lib/masyo/event.rb
52
+ - lib/masyo/server.rb
53
+ - lib/masyo/version.rb
54
+ - masyo.gemspec
55
+ - sample.god
56
+ - spec/masyo/buffer_spec.rb
57
+ - spec/masyo/client_spec.rb
58
+ - spec/masyo/event_spec.rb
59
+ - spec/masyo/server_spec.rb
60
+ - spec/masyo_spec.rb
61
+ - spec/spec_helper.rb
62
+ - tmp/.gitkeep
63
+ - vendor/bundles/.gitkeep
64
+ homepage: https://github.com/ToQoz/Masyo
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 1.8.23
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: masyo
88
+ test_files:
89
+ - spec/masyo/buffer_spec.rb
90
+ - spec/masyo/client_spec.rb
91
+ - spec/masyo/event_spec.rb
92
+ - spec/masyo/server_spec.rb
93
+ - spec/masyo_spec.rb
94
+ - spec/spec_helper.rb