nobject 1.0.1 → 1.0.2

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
  SHA256:
3
- metadata.gz: 99e7b2b83952e588a823fc66b9f9591d380e6b15ec6befc7a500f9175b708be3
4
- data.tar.gz: 73520de71d444c9ce29d3a713a251c5135575c2d7ebe523d1425dcc5455424be
3
+ metadata.gz: a07616d80ff414ef453ae35d7f8c7ae88b6c62f6683444bb2f2fd629a39b4f0d
4
+ data.tar.gz: 5e9eba6b82be1695ffcf0f26b936c2939c66ea9683e459599b3909ed3e604280
5
5
  SHA512:
6
- metadata.gz: 2cf62524464081dd0e49ff651c1f0ee817ab566c6cbe5666446f793cea4a6f143b7c41bd7e1f6c8030a36c7a646aceb4f8069dc0f30558f42f97b26b78444c21
7
- data.tar.gz: a9e42da33528635173f4af66621b0e5aa81830371a091b1df0072d2f31c42a2dc5fedc346a83c26c62e62205116b67a7398d1d1d0507b167481f74ac358fd2a4
6
+ metadata.gz: 16428d2597623632176561480785fc7b02d7440177f37561ee3030c80db0c0fa5009e0583067fc9e94a106301ffdfb0b0dfb5e67dc83ed438d8281a9879bed24
7
+ data.tar.gz: badd4e8b38c40fe20300b58034e5815ca30a804132257334a86d009e2a25cf4053288cdfe5f1e834b1e5bddbc4050461fcd7bea054f9db37d7212b264e29ee91
@@ -0,0 +1,54 @@
1
+ require 'socket'
2
+
3
+ module Nobject
4
+ # this class is used by the client application, wraps a local object, pushes
5
+ # it to a Nobject::Serve4r, which will then send method calls to a matching
6
+ # Nobject::Remote object
7
+ class Local
8
+ # host: the hostname of the server to push obj to
9
+ # port: the port number of the server to push obj to
10
+ # obj: the obj to store over the network
11
+ #
12
+ # ex:
13
+ # # this will create a new Nobject::Local, then push it to the specified
14
+ # server Nobject::Local.new('localhost', 1234, <object>)
15
+ def initialize(host, port, obj)
16
+ @socket = TCPSocket.new(host, port)
17
+ obj_bytes = Marshal.dump(obj)
18
+
19
+ @socket.send([obj_bytes.length].pack('Q>'), 0)
20
+ @socket.send(obj_bytes, 0)
21
+ end
22
+
23
+ def method_missing(method, *args, **kwargs, &block)
24
+ msg = { method: method, args: args }
25
+ msg_bytes = Marshal.dump(msg)
26
+
27
+ @socket.send([msg_bytes.length].pack('Q>'), 0)
28
+ @socket.send(msg_bytes, 0)
29
+
30
+ return_size = @socket.recv(8).unpack('Q>').first
31
+ return_data = Marshal.load(@socket.recv(return_size))
32
+
33
+ case return_data.first
34
+ when :ok then return_data.last
35
+ when :raise then raise return_data.last
36
+ else
37
+ raise Local::UnknownReturnDataType.new("unknown data type '#{return_data.first}' within Nobject::Local (Nobject::Local::UnknownReturnDataType)")
38
+ end
39
+ end
40
+
41
+ #####################################
42
+ # method overridden from Object class
43
+ #####################################
44
+ def !~(other); method_missing(:is_a?, other); end
45
+ def <=>(other); method_missing(:<=>, other); end
46
+ def ===(other); method_missing(:<=>, other); end
47
+ def is_a?(klass); method_missing(:is_a?, klass); end
48
+ def inspect; method_missing(:inspect); end
49
+ def to_s; method_missing(:to_s); end
50
+ end
51
+
52
+ class Local::UnknownReturnDataType < RuntimeError; end
53
+ class Local::InvalidMethod < RuntimeError; end
54
+ end
@@ -0,0 +1,38 @@
1
+ require 'socket'
2
+
3
+ module Nobject
4
+ # this class is used by the Nobject::Server to receive objects pushed to the
5
+ # Nobject::Server, listens for method invocations over the network, and sends
6
+ # the method invocations onwards to this object
7
+ class Remote
8
+ def initialize(socket)
9
+ @socket = socket
10
+ obj_size = @socket.recv(8).unpack('Q>').first
11
+ @obj = Marshal.load(@socket.recv(obj_size))
12
+ end
13
+
14
+ def serve!
15
+ Thread.new do
16
+ loop do
17
+ msg_size = @socket.recv(8).unpack('Q>').first
18
+ msg = Marshal.load(@socket.recv(msg_size))
19
+
20
+ result = @obj.send(msg[:method], *msg[:args]) #local_method, *msg[:args])
21
+ network_return([
22
+ :ok,
23
+ result
24
+ ])
25
+ end
26
+ end
27
+ end
28
+
29
+ def network_return(data)
30
+ data_bytes = Marshal.dump(data)
31
+
32
+ @socket.send([data_bytes.length].pack('Q>'), 0)
33
+ @socket.send(data_bytes, 0)
34
+ end
35
+ end
36
+
37
+ class Nobject::NoMethodError < NameError; end
38
+ end
@@ -0,0 +1,47 @@
1
+ require 'socket'
2
+ require_relative './remote'
3
+
4
+ module Nobject
5
+ ##
6
+ # this class listens for incoming requests to store an object over the network,
7
+ # accepts connections and then hands those sockets off to server object storage
8
+ # and invocation.
9
+ #
10
+ # ex:
11
+ # Nobject::Server.new(1234).start!
12
+ class Server
13
+ def initialize(port)
14
+ @server = TCPServer.new(port)
15
+ @keep_running = true
16
+ @nobjects = []
17
+ end
18
+
19
+ def alive?
20
+ @keep_running
21
+ end
22
+
23
+ def start!
24
+ loop do
25
+ break unless @keep_running
26
+
27
+ begin
28
+ incoming_socket = @server.accept_nonblock
29
+ Remote.new(incoming_socket).serve!
30
+ rescue IO::EAGAINWaitReadable => e
31
+ # no connection pending
32
+ begin
33
+ IO.select([@server])
34
+ retry
35
+ rescue Interrupt, IRB::Abort
36
+ @keep_running = false
37
+ @server&.close
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def stop!
44
+ @keep_running = false
45
+ end
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nobject
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Lunt
@@ -15,9 +15,9 @@ executables: []
15
15
  extensions: []
16
16
  extra_rdoc_files: []
17
17
  files:
18
- - lib/nobject.rb
19
- - lib/nobject_server.rb
20
- - lib/proxy_nobject.rb
18
+ - lib/nobject/local.rb
19
+ - lib/nobject/remote.rb
20
+ - lib/nobject/server.rb
21
21
  homepage: https://github.com/jefflunt/nobject
22
22
  licenses:
23
23
  - MIT
data/lib/nobject.rb DELETED
@@ -1,35 +0,0 @@
1
- require 'socket'
2
-
3
- # this class wraps a local object, listens for method invocations over the
4
- # network, and sends the method invocations onwards to the local object.
5
- class Nobject
6
- def initialize(socket)
7
- @socket = socket
8
- obj_size = @socket.recv(8).unpack('Q>').first
9
- @obj = Marshal.load(@socket.recv(obj_size))
10
- end
11
-
12
- def serve!
13
- Thread.new do
14
- loop do
15
- msg_size = @socket.recv(8).unpack('Q>').first
16
- msg = Marshal.load(@socket.recv(msg_size))
17
-
18
- result = @obj.send(msg[:method], *msg[:args]) #local_method, *msg[:args])
19
- network_return([
20
- :ok,
21
- result
22
- ])
23
- end
24
- end
25
- end
26
-
27
- def network_return(data)
28
- data_bytes = Marshal.dump(data)
29
-
30
- @socket.send([data_bytes.length].pack('Q>'), 0)
31
- @socket.send(data_bytes, 0)
32
- end
33
- end
34
-
35
- class Nobject::NoMethodError < NameError; end
@@ -1,45 +0,0 @@
1
- require 'socket'
2
- require_relative './nobject'
3
-
4
- ##
5
- # this class listens for incoming requests to store an object over the network,
6
- # accepts connections and then hands those sockets off to server object storage
7
- # and invocation.
8
- #
9
- # ex:
10
- # NobjectServer.new(1234).start!
11
- class NobjectServer
12
- def initialize(port)
13
- @server = TCPServer.new(port)
14
- @keep_running = true
15
- @nobjects = []
16
- end
17
-
18
- def alive?
19
- @keep_running
20
- end
21
-
22
- def start!
23
- loop do
24
- break unless @keep_running
25
-
26
- begin
27
- incoming_socket = @server.accept_nonblock
28
- Nobject.new(incoming_socket).serve!
29
- rescue IO::EAGAINWaitReadable => e
30
- # no connection pending
31
- begin
32
- IO.select([@server])
33
- retry
34
- rescue Interrupt, IRB::Abort
35
- @keep_running = false
36
- @server&.close
37
- end
38
- end
39
- end
40
- end
41
-
42
- def stop!
43
- @keep_running = false
44
- end
45
- end
data/lib/proxy_nobject.rb DELETED
@@ -1,51 +0,0 @@
1
- require 'socket'
2
-
3
- # this is the class that accepts instantiated objects in the main program, and
4
- # then pushes them to a remote server
5
- class ProxyNobject
6
- # host: the hostname of the server to push obj to
7
- # port: the port number of the server to push obj to
8
- # obj: the obj to store over the network
9
- #
10
- # ex:
11
- # # this will create a new ProxyNobject, then put it to the specified server
12
- # ProxyNobject.new('localhost', 1234, <object>)
13
- def initialize(host, port, obj)
14
- @socket = TCPSocket.new(host, port)
15
- obj_bytes = Marshal.dump(obj)
16
-
17
- @socket.send([obj_bytes.length].pack('Q>'), 0)
18
- @socket.send(obj_bytes, 0)
19
- end
20
-
21
- def method_missing(method, *args, **kwargs, &block)
22
- msg = { method: method, args: args }
23
- msg_bytes = Marshal.dump(msg)
24
-
25
- @socket.send([msg_bytes.length].pack('Q>'), 0)
26
- @socket.send(msg_bytes, 0)
27
-
28
- return_size = @socket.recv(8).unpack('Q>').first
29
- return_data = Marshal.load(@socket.recv(return_size))
30
-
31
- case return_data.first
32
- when :ok then return_data.last
33
- when :raise then raise return_data.last
34
- else
35
- raise ProxyNobject::UnknownReturnDataType.new("unknown data type '#{return_data.first}' within ProxyNobject (ProxyNobject::UnknownReturnDataType)")
36
- end
37
- end
38
-
39
- #####################################
40
- # method overridden from Object class
41
- #####################################
42
- def !~(other); method_missing(:is_a?, other); end
43
- def <=>(other); method_missing(:<=>, other); end
44
- def ===(other); method_missing(:<=>, other); end
45
- def is_a?(klass); method_missing(:is_a?, klass); end
46
- def inspect; method_missing(:inspect); end
47
- def object_id; method_missing(:object_id); end
48
- end
49
-
50
- class ProxyNobject::UnknownReturnDataType < RuntimeError; end
51
- class ProxyNobject::InvalidMethod < RuntimeError; end