dizby 1.3.0

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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +10 -0
  3. data/LICENSE +24 -0
  4. data/dizby.gemspec +27 -0
  5. data/lib/dizby.rb +12 -0
  6. data/lib/dizby/access/control_list.rb +78 -0
  7. data/lib/dizby/access/entry.rb +61 -0
  8. data/lib/dizby/access/insecure.rb +30 -0
  9. data/lib/dizby/access/list.rb +10 -0
  10. data/lib/dizby/converter/simple.rb +12 -0
  11. data/lib/dizby/converter/timed.rb +23 -0
  12. data/lib/dizby/distributed/array.rb +30 -0
  13. data/lib/dizby/distributed/object.rb +44 -0
  14. data/lib/dizby/distributed/proxy.rb +41 -0
  15. data/lib/dizby/distributed/semi_proxy.rb +26 -0
  16. data/lib/dizby/distributed/undumpable.rb +8 -0
  17. data/lib/dizby/distributed/unknown.rb +57 -0
  18. data/lib/dizby/error.rb +29 -0
  19. data/lib/dizby/protocol/basic.rb +31 -0
  20. data/lib/dizby/protocol/manager.rb +62 -0
  21. data/lib/dizby/protocol/refined.rb +23 -0
  22. data/lib/dizby/protocols/dead.rb +24 -0
  23. data/lib/dizby/protocols/secure.rb +87 -0
  24. data/lib/dizby/protocols/tcp.rb +98 -0
  25. data/lib/dizby/protocols/unix.rb +95 -0
  26. data/lib/dizby/server/abstract.rb +42 -0
  27. data/lib/dizby/server/basic.rb +101 -0
  28. data/lib/dizby/server/registration.rb +23 -0
  29. data/lib/dizby/service.rb +64 -0
  30. data/lib/dizby/stream/client.rb +26 -0
  31. data/lib/dizby/stream/connection.rb +63 -0
  32. data/lib/dizby/stream/messenger.rb +28 -0
  33. data/lib/dizby/stream/query_ref.rb +13 -0
  34. data/lib/dizby/stream/readable.rb +65 -0
  35. data/lib/dizby/stream/writable.rb +37 -0
  36. data/lib/dizby/tunnel/abstract.rb +52 -0
  37. data/lib/dizby/tunnel/basic.rb +21 -0
  38. data/lib/dizby/tunnel/basic_spawn.rb +50 -0
  39. data/lib/dizby/tunnel/bidirectional_strategy.rb +29 -0
  40. data/lib/dizby/tunnel/factory.rb +29 -0
  41. data/lib/dizby/tunnel/local_strategy.rb +24 -0
  42. data/lib/dizby/tunnel/spawn_command.rb +49 -0
  43. data/lib/dizby/tunnel/spawned.rb +43 -0
  44. data/lib/dizby/tunnel/tunnelable_local.rb +8 -0
  45. data/lib/dizby/tunnel/tunnelable_remote.rb +21 -0
  46. data/lib/dizby/utility/classic_access.rb +25 -0
  47. data/lib/dizby/utility/configurable.rb +25 -0
  48. data/lib/dizby/utility/delegator.rb +28 -0
  49. data/lib/dizby/utility/io_barrier.rb +18 -0
  50. data/lib/dizby/utility/log.rb +23 -0
  51. data/lib/dizby/utility/monitor.rb +9 -0
  52. data/lib/dizby/utility/polymorphic_delegated.rb +58 -0
  53. data/lib/dizby/utility/self_pipe.rb +12 -0
  54. data/lib/dizby/utility/semi_built.rb +17 -0
  55. data/lib/dizby/utility/string.rb +8 -0
  56. data/lib/dizby/utility/timed_collection.rb +39 -0
  57. data/lib/dizby/utility/timed_state.rb +41 -0
  58. data/lib/dizby/version.rb +4 -0
  59. data/lib/dizby/worker/connection.rb +44 -0
  60. data/lib/dizby/worker/invoke_method.rb +55 -0
  61. data/lib/dizby/worker/server.rb +39 -0
  62. metadata +146 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5942da7c03a278335c9ed7601035bada58a1fe0f
4
+ data.tar.gz: 4edfa688cb39af31316e8b55586274f910f00090
5
+ SHA512:
6
+ metadata.gz: 63553d5c0ea0238b8337cdf87692f9da50792e14dc1df9cc079674275756097b2b3a968031491fae2589b20d5c70b6583a181b40267a3c22201cd17f8a769f3d
7
+ data.tar.gz: 684fbfdc941b8a823c81967fff3a711348edd9fbfbe3d4167e629ec0df07dd0bfc6952231b11fee0191ba70093d2e002b08b239930f63d731b08e4f6ca971792
@@ -0,0 +1,10 @@
1
+ ---
2
+
3
+ Style/Documentation:
4
+ Enabled: false
5
+
6
+ Metrics/MethodLength:
7
+ Max: 12
8
+
9
+ Style/SpecialGlobalVars:
10
+ Enabled: false
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2013-2015, Nathan Currier
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * Neither the name of the <organization> nor the
12
+ names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ require './lib/dizby/version'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = 'dizby'
6
+ spec.version = Dizby::VERSION
7
+ spec.authors = ['Nathan Currier']
8
+ spec.email = ['nathan.currier@gmail.com']
9
+ spec.license = 'BSD-3-Clause'
10
+
11
+ spec.description = 'Distributed Ruby'
12
+ spec.summary = 'Distributed Ruby'
13
+ spec.homepage = 'https://gem.rideliner.net'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.bindir = 'bin'
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '~> 2.0'
22
+
23
+ spec.add_runtime_dependency 'net-ssh', '~> 3.0'
24
+
25
+ spec.add_development_dependency 'rubocop', '~> 0.35'
26
+ spec.add_development_dependency 'reek', '~> 3.7'
27
+ end
@@ -0,0 +1,12 @@
1
+
2
+ require 'dizby/version'
3
+
4
+ require 'dizby/service'
5
+
6
+ require 'dizby/access/control_list'
7
+ require 'dizby/tunnel/spawn_command'
8
+ require 'dizby/converter/timed'
9
+
10
+ require 'dizby/protocols/dead'
11
+ require 'dizby/protocols/tcp'
12
+ require 'dizby/protocols/secure'
@@ -0,0 +1,78 @@
1
+
2
+ require 'dizby/access/entry'
3
+ require 'dizby/access/list'
4
+
5
+ module Dizby
6
+ module Access
7
+ class ControlList
8
+ # :deny_allow
9
+ # if allowed, allow
10
+ # else if denied, deny
11
+ # else, allow
12
+
13
+ # :allow_deny
14
+ # if denied, deny
15
+ # else if allowed, allow
16
+ # else, deny
17
+
18
+ def initialize(order = :deny_allow)
19
+ @order = order
20
+ @deny = List.new
21
+ @allow = List.new
22
+ end
23
+
24
+ def allow_socket?(soc)
25
+ allow_addr?(soc.peeraddr)
26
+ end
27
+
28
+ def allow_addr?(addr)
29
+ case @order
30
+ when :deny_allow
31
+ deny_allow?(addr)
32
+ when :allow_deny
33
+ allow_deny?(addr)
34
+ else
35
+ false
36
+ end
37
+ end
38
+
39
+ def install_list(list)
40
+ Hash[*list].each do |permission, domain|
41
+ domain = Entry.new(domain)
42
+ case permission.downcase
43
+ when 'allow'
44
+ @allow.push(domain)
45
+ when 'deny'
46
+ @deny.push(domain)
47
+ else
48
+ fail ArgumentError, "Invalid ACL entry #{list}"
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def deny_allow?(addr)
56
+ return true if @allow.matches?(addr)
57
+ return false if @deny.matches?(addr)
58
+ true
59
+ end
60
+
61
+ def allow_deny?(addr)
62
+ return false if @deny.matches?(addr)
63
+ return true if @allow.matches?(addr)
64
+ false
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ # !! To allow unless explicitly denied
71
+ # acl = Dizby::Access::ControlList.new(:allow_deny)
72
+ # acl.install_list %w[ allow all ]
73
+ # acl.install_list your_list_of_denies
74
+
75
+ # !! To deny unless explicitly allowed
76
+ # acl = Dizby::Access::ControlList.new(:deny_allow)
77
+ # acl.install_list %w[ deny all ]
78
+ # acl.install_list your_list_of_allows
@@ -0,0 +1,61 @@
1
+
2
+ require 'ipaddr'
3
+
4
+ module Dizby
5
+ module Access
6
+ class Entry
7
+ def initialize(str)
8
+ if str == '*' || str == 'all'
9
+ @access = [:all]
10
+ elsif str.include?('*')
11
+ @access = [:name, pattern(str)]
12
+ else
13
+ begin
14
+ @access = [:ip, IPAddr.new(str)]
15
+ rescue ArgumentError
16
+ @access = [:name, pattern(str)]
17
+ end
18
+ end
19
+ end
20
+
21
+ def matches?(addr)
22
+ (scope, pattern) = @access
23
+
24
+ case scope
25
+ when :all
26
+ true
27
+ when :ip
28
+ matches_ip?(addr, pattern)
29
+ when :name
30
+ matches_name?(addr, pattern)
31
+ else
32
+ false
33
+ end
34
+ end
35
+
36
+ class << self
37
+ private
38
+
39
+ def pattern(str)
40
+ pattern = str.split('.')
41
+ pattern.map! { |segment| (segment == '*') ? '.+' : segment }
42
+ /^#{pattern.join('\\.')}$/
43
+ end
44
+
45
+ def matches_ip?(addr, pattern)
46
+ ipaddr = IPAddr.new(addr[3])
47
+ # map to ipv6 if entry is ipv6 and address is ipv4
48
+ ipaddr = ipaddr.ipv4_mapped if pattern.ipv6? && ipaddr.ipv4?
49
+
50
+ pattern.include?(ipaddr)
51
+ rescue ArgumentError
52
+ false
53
+ end
54
+
55
+ def matches_name?(addr, pattern)
56
+ pattern =~ addr[2]
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,30 @@
1
+
2
+ require 'dizby/utility/string'
3
+
4
+ module Dizby
5
+ INSECURE_METHODS = [:__send__]
6
+
7
+ def self.check_insecure_method(obj, msg_id)
8
+ unless msg_id.is_a?(Symbol)
9
+ fail ArgumentError, "#{Dizby.any_to_s(msg_id)} is not a symbol"
10
+ end
11
+
12
+ if INSECURE_METHODS.include?(msg_id)
13
+ fail SecurityError, "insecure method `#{msg_id}'"
14
+ end
15
+
16
+ check_hidden_method(obj, msg_id)
17
+ end
18
+
19
+ def self.check_hidden_method(obj, msg_id)
20
+ if obj.private_methods.include?(msg_id)
21
+ desc = Dizby.any_to_s(obj)
22
+ fail NoMethodError, "private method `#{msg_id}' called for #{desc}"
23
+ elsif obj.protected_methods.include?(msg_id)
24
+ desc = Dizby.any_to_s(obj)
25
+ fail NoMethodError, "protected method `#{msg_id}' called for #{desc}"
26
+ else
27
+ true
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+
2
+ module Dizby
3
+ module Access
4
+ class List < Array
5
+ def matches?(addr)
6
+ any? { |entry| entry.matches?(addr) }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module Dizby
3
+ class IdConverter
4
+ def self.to_obj(ref)
5
+ ObjectSpace._id2ref(ref)
6
+ end
7
+
8
+ def self.to_id(obj)
9
+ obj.__id__
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require 'dizby/utility/timed_collection'
3
+ require 'dizby/converter/simple'
4
+
5
+ module Dizby
6
+ class TimedIdConverter
7
+ # default timeout: 10 minutes, default step: 30 seconds
8
+ def initialize(timeout = 600_000, step = 30_000)
9
+ @collection = TimedCollection.new(timeout, step)
10
+ end
11
+
12
+ def to_obj(ref)
13
+ @collection.revive(ref)
14
+ IdConverter.to_obj(ref)
15
+ end
16
+
17
+ def to_id(obj)
18
+ key = IdConverter.to_id(obj)
19
+ @collection.add(key)
20
+ key
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+
2
+ require 'dizby/distributed/object'
3
+ require 'dizby/distributed/undumpable'
4
+
5
+ module Dizby
6
+ class DistributedArray
7
+ def initialize(ary, server)
8
+ @ary = ary.map do |obj|
9
+ if obj.is_a? UndumpableObject
10
+ DistributedObject.new(obj, server)
11
+ else
12
+ begin
13
+ Marshal.dump(obj)
14
+ obj
15
+ rescue
16
+ DistributedObject.new(obj, server)
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def self._load(str)
23
+ Marshal.load(str)
24
+ end
25
+
26
+ def _dump(_)
27
+ Marshal.dump(@ary)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,44 @@
1
+
2
+ require 'dizby/distributed/proxy'
3
+ require 'dizby/access/insecure'
4
+
5
+ module Dizby
6
+ class DistributedObject
7
+ def self._load(str)
8
+ SemiObjectProxy.new(*Marshal.load(str))
9
+ end
10
+
11
+ def _dump(_)
12
+ Marshal.dump [@server.uri, @server.to_id(@obj)]
13
+ end
14
+
15
+ def initialize(obj, server)
16
+ @obj = obj
17
+ @server = server
18
+ end
19
+
20
+ undef :to_s
21
+ undef :to_a if respond_to?(:to_a)
22
+
23
+ def respond_to?(msg_id, priv = false)
24
+ responds =
25
+ case msg_id
26
+ when :_dump
27
+ true
28
+ when :marshal_dump
29
+ false
30
+ else
31
+ method_missing(:respond_to?, msg_id, priv)
32
+ end
33
+
34
+ @server.log.debug("respond_to?(#{msg_id}) => #{responds}")
35
+ responds
36
+ end
37
+
38
+ def method_missing(msg_id, *args, &block)
39
+ @server.log.debug("calling: #{msg_id} #{args.join ', '}")
40
+ Dizby.check_insecure_method(@obj, msg_id)
41
+ @obj.__send__(msg_id, *args, &block)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+
2
+ require 'dizby/distributed/unknown'
3
+
4
+ module Dizby
5
+ class ObjectProxy
6
+ def initialize(conn, ref = nil)
7
+ @ref = ref
8
+ @conn = conn
9
+ end
10
+
11
+ def method_missing(msg_id, *args, &block)
12
+ @conn.server.log.debug("calling through proxy: #{msg_id} #{args}")
13
+ @conn.send_request(@ref, msg_id, *args, &block)
14
+ succ, result = @conn.recv_reply
15
+
16
+ if succ
17
+ result
18
+ elsif result.is_a?(UnknownObject)
19
+ fail result
20
+ else
21
+ bt = Dizby.proxy_backtrace(@conn.remote_uri, result)
22
+ result.set_backtrace(bt + caller)
23
+ fail result
24
+ end
25
+ end
26
+
27
+ undef :to_s
28
+ undef :to_a if respond_to?(:to_a)
29
+
30
+ def respond_to?(msg_id, priv = false)
31
+ method_missing(:respond_to?, msg_id, priv)
32
+ end
33
+ end
34
+
35
+ def self.proxy_backtrace(prefix, exception)
36
+ bt = exception.backtrace.reject { |trace| /`__send__'$/ =~ trace }
37
+ bt.map { |trace| %r{\(drb://} =~ trace ? trace : "#{prefix}#{trace}" }
38
+ # TODO: why do we only add the prefix if the trace doesn't start with drb?
39
+ # What about the other schemes?
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+
2
+ require 'dizby/server/registration'
3
+ require 'dizby/distributed/proxy'
4
+
5
+ module Dizby
6
+ class SemiObjectProxy
7
+ def initialize(uri, ref)
8
+ @uri = uri
9
+ @ref = ref
10
+ end
11
+
12
+ def evaluate(server)
13
+ # cut down on network times by using the object if it exists locally
14
+ success, obj = Dizby.get_obj(@uri, @ref)
15
+
16
+ if success
17
+ server.log.debug("found local obj: #{obj.inspect}")
18
+ obj
19
+ else
20
+ server.log.debug("creating proxy to #{@ref} on #{@uri}")
21
+ client, = server.connect_to(@uri) # throw away the ref
22
+ ObjectProxy.new(client, @ref)
23
+ end
24
+ end
25
+ end
26
+ end