opal-drb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +4 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example/Gemfile +11 -0
- data/example/Gemfile.lock +74 -0
- data/example/app/application.rb +14 -0
- data/example/assets/css/application.scss +0 -0
- data/example/bin/console +19 -0
- data/example/config.ru +28 -0
- data/example/server.rb +30 -0
- data/example/views/index.erb +9 -0
- data/lib/opal/drb.rb +15 -0
- data/lib/opal/drb/drb.rb +109 -0
- data/lib/opal/drb/drb_conn.rb +63 -0
- data/lib/opal/drb/drb_message.rb +111 -0
- data/lib/opal/drb/drb_object.rb +103 -0
- data/lib/opal/drb/drb_protocol.rb +43 -0
- data/lib/opal/drb/version.rb +5 -0
- data/lib/opal/drb/websocket.rb +134 -0
- data/opal-drb.gemspec +26 -0
- data/proc.rb +2 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 59cfd003694ff3b5cea5b36890115827c3e5021e
|
4
|
+
data.tar.gz: f1b1ee0b120661e1d119191604d13d6cbc99563e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6d56f0b90def3126209f8d0dbd88bf60d45d0a0ab535787ad26e4b995f9c8ca373ef37261feb6bdb3034837a3a331cbba3d74f044d18aa41956a1c35b6f03d57
|
7
|
+
data.tar.gz: d6a81db3890e07923af570a169103fd82aa83461def8f972af5fcbabe22e95e2b78b3574e3b19278e611038c794d48dc488d3b106d18df672507cb782dd2aab2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "opal/drb"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/example/Gemfile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/opal/opal-sprockets.git
|
3
|
+
revision: a063dffd884b495ed0c54b4c3b0b1cacc4abb322
|
4
|
+
specs:
|
5
|
+
opal-sprockets (0.4.1.0.11.0.rc1.3.1.beta2)
|
6
|
+
opal (~> 0.11.0.rc1)
|
7
|
+
sprockets (~> 3.1)
|
8
|
+
tilt (>= 1.4)
|
9
|
+
|
10
|
+
GIT
|
11
|
+
remote: git://github.com/youchan/opal.git
|
12
|
+
revision: 79998074a820fd1e651bce1e8661245949648285
|
13
|
+
branch: marshal-dump-bignum
|
14
|
+
specs:
|
15
|
+
opal (0.11.0.rc1)
|
16
|
+
ast (>= 2.3.0)
|
17
|
+
hike (~> 1.2)
|
18
|
+
parser (= 2.3.3.1)
|
19
|
+
sourcemap (~> 0.1.0)
|
20
|
+
|
21
|
+
GEM
|
22
|
+
remote: https://rubygems.org/
|
23
|
+
specs:
|
24
|
+
ast (2.3.0)
|
25
|
+
backports (3.8.0)
|
26
|
+
concurrent-ruby (1.0.5)
|
27
|
+
daemons (1.2.4)
|
28
|
+
eventmachine (1.2.3)
|
29
|
+
hike (1.2.3)
|
30
|
+
multi_json (1.12.1)
|
31
|
+
mustermann (1.0.0)
|
32
|
+
parser (2.3.3.1)
|
33
|
+
ast (~> 2.2)
|
34
|
+
rack (2.0.3)
|
35
|
+
rack-protection (2.0.0)
|
36
|
+
rack
|
37
|
+
rake (12.0.0)
|
38
|
+
sass (3.4.24)
|
39
|
+
sinatra (2.0.0)
|
40
|
+
mustermann (~> 1.0)
|
41
|
+
rack (~> 2.0)
|
42
|
+
rack-protection (= 2.0.0)
|
43
|
+
tilt (~> 2.0)
|
44
|
+
sinatra-contrib (2.0.0)
|
45
|
+
backports (>= 2.0)
|
46
|
+
multi_json
|
47
|
+
mustermann (~> 1.0)
|
48
|
+
rack-protection (= 2.0.0)
|
49
|
+
sinatra (= 2.0.0)
|
50
|
+
tilt (>= 1.3, < 3)
|
51
|
+
sourcemap (0.1.1)
|
52
|
+
sprockets (3.7.1)
|
53
|
+
concurrent-ruby (~> 1.0)
|
54
|
+
rack (> 1, < 3)
|
55
|
+
thin (1.7.1)
|
56
|
+
daemons (~> 1.0, >= 1.0.9)
|
57
|
+
eventmachine (~> 1.0, >= 1.0.4)
|
58
|
+
rack (>= 1, < 3)
|
59
|
+
tilt (2.0.7)
|
60
|
+
|
61
|
+
PLATFORMS
|
62
|
+
ruby
|
63
|
+
|
64
|
+
DEPENDENCIES
|
65
|
+
opal!
|
66
|
+
opal-sprockets!
|
67
|
+
rake
|
68
|
+
sass
|
69
|
+
sinatra
|
70
|
+
sinatra-contrib
|
71
|
+
thin
|
72
|
+
|
73
|
+
BUNDLED WITH
|
74
|
+
1.14.6
|
File without changes
|
data/example/bin/console
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
|
5
|
+
require 'menilite'
|
6
|
+
require 'sinatra/activerecord'
|
7
|
+
|
8
|
+
Dir[File.expand_path('../../app/models/', __FILE__) + '/**/*.rb'].each {|file| require(file) }
|
9
|
+
Dir[File.expand_path('../../app/controllers/', __FILE__) + '/**/*.rb'].each {|file| require(file) }
|
10
|
+
|
11
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
12
|
+
# with your gem easier. You can also use a different console, if you like.
|
13
|
+
|
14
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
15
|
+
# require "pry"
|
16
|
+
# Pry.start
|
17
|
+
|
18
|
+
require "irb"
|
19
|
+
IRB.start
|
data/example/config.ru
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.require(:default)
|
3
|
+
|
4
|
+
require_relative 'server'
|
5
|
+
|
6
|
+
app = Rack::Builder.app do
|
7
|
+
server = Server.new(host: 'localhost')
|
8
|
+
|
9
|
+
map '/' do
|
10
|
+
run server
|
11
|
+
end
|
12
|
+
|
13
|
+
map '/assets' do
|
14
|
+
run Server::OPAL.sprockets
|
15
|
+
end
|
16
|
+
|
17
|
+
map '/__OPAL_SOURCE_MAPS__' do
|
18
|
+
run Opal::SourceMapServer.new(Server::OPAL.sprockets, '/__OPAL_SOURCE_MAPS__')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Rack::Server.start({
|
23
|
+
app: app,
|
24
|
+
server: 'thin',
|
25
|
+
Host: '0.0.0.0',
|
26
|
+
Port: 9292,
|
27
|
+
signals: false,
|
28
|
+
})
|
data/example/server.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'opal'
|
3
|
+
|
4
|
+
if development?
|
5
|
+
require 'sinatra/reloader'
|
6
|
+
end
|
7
|
+
|
8
|
+
class Server < Sinatra::Base
|
9
|
+
OPAL = Opal::Server.new do |server|
|
10
|
+
server.append_path 'app'
|
11
|
+
server.append_path 'assets'
|
12
|
+
server.append_path '../lib'
|
13
|
+
Opal.paths.each {|path| server.append_path path }
|
14
|
+
|
15
|
+
server.main = 'application'
|
16
|
+
end
|
17
|
+
|
18
|
+
configure do
|
19
|
+
set opal: OPAL
|
20
|
+
enable :sessions
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/' do
|
24
|
+
erb :index
|
25
|
+
end
|
26
|
+
|
27
|
+
get "/favicon.ico" do
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<html lang="en">
|
2
|
+
<head>
|
3
|
+
<link rel="stylesheet" href="assets/css/application.css" />
|
4
|
+
</head>
|
5
|
+
<body>
|
6
|
+
<content/>
|
7
|
+
<%= ::Opal::Sprockets.javascript_include_tag('application', sprockets: settings.opal.sprockets, prefix: 'assets', debug: true) %>
|
8
|
+
</body>
|
9
|
+
</html>
|
data/lib/opal/drb.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module DRb
|
2
|
+
class DRbError < RuntimeError; end
|
3
|
+
class DRbConnError < DRbError; end
|
4
|
+
class DRbServerNotFound < DRbError; end
|
5
|
+
class DRbBadURI < DRbError; end
|
6
|
+
class DRbBadScheme < DRbError; end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'opal/drb/version'
|
10
|
+
require 'opal/drb/websocket'
|
11
|
+
require 'opal/drb/drb_protocol'
|
12
|
+
require 'opal/drb/drb_conn'
|
13
|
+
require 'opal/drb/drb_object'
|
14
|
+
require 'opal/drb/drb_message'
|
15
|
+
require 'opal/drb/drb'
|
data/lib/opal/drb/drb.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'corelib/marshal'
|
2
|
+
require 'promise'
|
3
|
+
|
4
|
+
module DRb
|
5
|
+
class DRbUnknownError < DRbError
|
6
|
+
def initialize(unknown)
|
7
|
+
@unknown = unknown
|
8
|
+
super(unknown.name)
|
9
|
+
end
|
10
|
+
attr_reader :unknown
|
11
|
+
|
12
|
+
def self._load(s)
|
13
|
+
Marshal::load(s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def _dump(lv)
|
17
|
+
Marshal::dump(@unknown)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class DRbRemoteError < DRbError
|
22
|
+
def initialize(error)
|
23
|
+
@reason = error.class.to_s
|
24
|
+
super("#{error.message} (#{error.class})")
|
25
|
+
set_backtrace(error.backtrace)
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :reason
|
29
|
+
end
|
30
|
+
|
31
|
+
class DRbIdConv
|
32
|
+
def to_obj(ref)
|
33
|
+
ObjectSpace._id2ref(ref)
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_id(obj)
|
37
|
+
obj.nil? ? nil : obj.__id__
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module DRbUndumped
|
42
|
+
def _dump(dummy)
|
43
|
+
raise TypeError, 'can\'t dump'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class DRbUnknown
|
48
|
+
def initialize(err, buf)
|
49
|
+
case err.to_s
|
50
|
+
when /uninitialized constant (\S+)/
|
51
|
+
@name = $1
|
52
|
+
when /undefined class\/module (\S+)/
|
53
|
+
@name = $1
|
54
|
+
else
|
55
|
+
@name = nil
|
56
|
+
end
|
57
|
+
@buf = buf
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :name
|
61
|
+
attr_reader :buf
|
62
|
+
|
63
|
+
def self._load(s)
|
64
|
+
begin
|
65
|
+
Marshal::load(s)
|
66
|
+
rescue NameError, ArgumentError
|
67
|
+
DRbUnknown.new($!, s)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def _dump(lv)
|
72
|
+
@buf
|
73
|
+
end
|
74
|
+
|
75
|
+
def reload
|
76
|
+
self.class._load(@buf)
|
77
|
+
end
|
78
|
+
|
79
|
+
def exception
|
80
|
+
DRbUnknownError.new(self)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class DRbArray
|
85
|
+
def initialize(ary)
|
86
|
+
@ary = ary.collect { |obj|
|
87
|
+
if obj.kind_of? DRbUndumped
|
88
|
+
DRbObject.new(obj)
|
89
|
+
else
|
90
|
+
begin
|
91
|
+
Marshal.dump(obj)
|
92
|
+
obj
|
93
|
+
rescue
|
94
|
+
DRbObject.new(obj)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def self._load(s)
|
101
|
+
Marshal::load(s)
|
102
|
+
end
|
103
|
+
|
104
|
+
def _dump(lv)
|
105
|
+
Marshal.dump(@ary)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module DRb
|
2
|
+
class DRbConn
|
3
|
+
POOL_SIZE = 16
|
4
|
+
@pool = []
|
5
|
+
|
6
|
+
def self.open(remote_uri)
|
7
|
+
begin
|
8
|
+
conn = nil
|
9
|
+
|
10
|
+
@pool = @pool.each_with_object([]) do |c, new_pool|
|
11
|
+
if conn.nil? and c.uri == remote_uri
|
12
|
+
conn = c if c.alive?
|
13
|
+
else
|
14
|
+
new_pool.push c
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
conn = self.new(remote_uri) unless conn
|
19
|
+
succ, result = yield(conn)
|
20
|
+
return succ, result
|
21
|
+
|
22
|
+
ensure
|
23
|
+
if conn
|
24
|
+
if succ
|
25
|
+
@pool.unshift(conn)
|
26
|
+
@pool.pop.close while @pool.size > POOL_SIZE
|
27
|
+
else
|
28
|
+
conn.close
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(remote_uri)
|
35
|
+
@uri = remote_uri
|
36
|
+
@protocol = DRbProtocol.open(remote_uri, DRb::default_config)
|
37
|
+
end
|
38
|
+
attr_reader :uri
|
39
|
+
|
40
|
+
def send_message(ref, msg_id, arg, b, &callback)
|
41
|
+
@protocol.send_request(ref, msg_id, arg, b).then do |stream|
|
42
|
+
yield @protocol.recv_reply stream
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def close
|
47
|
+
@protocol.close
|
48
|
+
@protocol = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def alive?
|
52
|
+
return false unless @protocol
|
53
|
+
@protocol.alive?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.default_config
|
58
|
+
{
|
59
|
+
argc_limit: 256,
|
60
|
+
load_limit: 256 * 102400
|
61
|
+
}
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module DRb
|
2
|
+
class DRbMessage
|
3
|
+
def initialize(config)
|
4
|
+
@load_limit = config[:load_limit]
|
5
|
+
@argc_limit = config[:argc_limit]
|
6
|
+
end
|
7
|
+
|
8
|
+
def dump(obj, error=false)
|
9
|
+
obj = make_proxy(obj, error) if obj.kind_of? DRbUndumped
|
10
|
+
begin
|
11
|
+
str = Marshal::dump(obj)
|
12
|
+
rescue
|
13
|
+
str = Marshal::dump(make_proxy(obj, error))
|
14
|
+
end
|
15
|
+
pack_n(str.size) + str
|
16
|
+
end
|
17
|
+
|
18
|
+
def load(soc)
|
19
|
+
begin
|
20
|
+
sz = soc.read(4)
|
21
|
+
rescue
|
22
|
+
raise(DRbConnError, $!.message, $!.backtrace)
|
23
|
+
end
|
24
|
+
|
25
|
+
raise(DRbConnError, 'connection closed') if sz.nil?
|
26
|
+
raise(DRbConnError, 'premature header') if sz.size < 4
|
27
|
+
|
28
|
+
sz = unpack_n(sz)[0]
|
29
|
+
|
30
|
+
raise(DRbConnError, "too large packet #{sz}") if @load_limit < sz
|
31
|
+
begin
|
32
|
+
str = soc.read(sz)
|
33
|
+
rescue
|
34
|
+
raise(DRbConnError, $!.message, $!.backtrace)
|
35
|
+
end
|
36
|
+
|
37
|
+
raise(DRbConnError, 'connection closed') if str.nil?
|
38
|
+
raise(DRbConnError, 'premature marshal format(can\'t read)') if str.size < sz
|
39
|
+
|
40
|
+
Marshal::load(str)
|
41
|
+
end
|
42
|
+
|
43
|
+
def send_request(stream, ref, msg_id, arg, b)
|
44
|
+
ary = []
|
45
|
+
ary.push(dump(ref.__drbref))
|
46
|
+
ary.push(dump(msg_id))
|
47
|
+
ary.push(dump(arg.length))
|
48
|
+
arg.each do |e|
|
49
|
+
ary.push(dump(e))
|
50
|
+
end
|
51
|
+
ary.push(dump(b))
|
52
|
+
stream.write(ary.join(''))
|
53
|
+
rescue
|
54
|
+
raise(DRbConnError, $!.message, $!.backtrace)
|
55
|
+
end
|
56
|
+
|
57
|
+
def recv_request(stream)
|
58
|
+
ref = load(stream)
|
59
|
+
ro = DRb.to_obj(ref)
|
60
|
+
msg = load(stream)
|
61
|
+
argc = load(stream)
|
62
|
+
raise(DRbConnError, "too many arguments") if @argc_limit < argc
|
63
|
+
argv = Array.new(argc, nil)
|
64
|
+
argc.times do |n|
|
65
|
+
argv[n] = load(stream)
|
66
|
+
end
|
67
|
+
block = load(stream)
|
68
|
+
return ro, msg, argv, block
|
69
|
+
end
|
70
|
+
|
71
|
+
def send_reply(stream, succ, result)
|
72
|
+
stream.write(dump(succ) + dump(result, !succ))
|
73
|
+
rescue
|
74
|
+
raise(DRbConnError, $!.message, $!.backtrace)
|
75
|
+
end
|
76
|
+
|
77
|
+
def recv_reply(stream)
|
78
|
+
succ = load(stream)
|
79
|
+
result = load(stream)
|
80
|
+
[succ, result]
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def make_proxy(obj, error=false)
|
85
|
+
if error
|
86
|
+
DRbRemoteError.new(obj)
|
87
|
+
else
|
88
|
+
DRbObject.new(obj)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def pack_n(n)
|
93
|
+
%x{
|
94
|
+
var s = "";
|
95
|
+
for (var i = 0; i < 4; i++) {
|
96
|
+
var b = n & 255;
|
97
|
+
s = String.fromCharCode(b) + s;
|
98
|
+
n >>= 8
|
99
|
+
}
|
100
|
+
|
101
|
+
return s;
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def unpack_n(s)
|
106
|
+
s.bytes.each_slice(2).map(&:first).each_slice(4).map do |x|
|
107
|
+
x[0] << 24 | x[1] << 16 | x[2] << 8 | x[3]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module DRb
|
2
|
+
class DRbObject
|
3
|
+
def self._load(s)
|
4
|
+
uri, ref = Marshal.load(s)
|
5
|
+
self.new_with(uri, ref)
|
6
|
+
rescue Exception => e
|
7
|
+
`console.log(e)`
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.new_with(uri, ref)
|
11
|
+
it = self.allocate
|
12
|
+
it.instance_variable_set(:@uri, uri)
|
13
|
+
it.instance_variable_set(:@ref, ref)
|
14
|
+
it
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.new_with_uri(uri)
|
18
|
+
self.new(nil, uri)
|
19
|
+
end
|
20
|
+
|
21
|
+
def _dump(lv)
|
22
|
+
Marshal.dump([@uri, @ref])
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(obj, uri=nil)
|
26
|
+
@uri = nil
|
27
|
+
@ref = nil
|
28
|
+
if obj.nil?
|
29
|
+
return if uri.nil?
|
30
|
+
@uri, option = DRbProtocol.uri_option(uri, DRb::default_config)
|
31
|
+
@ref = DRbURIOption.new(option) unless option.nil?
|
32
|
+
else
|
33
|
+
@uri = uri ? uri : nil
|
34
|
+
@ref = obj ? DRb.to_id(obj) : nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def __drburi
|
39
|
+
@uri
|
40
|
+
end
|
41
|
+
|
42
|
+
def __drbref
|
43
|
+
@ref
|
44
|
+
end
|
45
|
+
|
46
|
+
undef :to_s
|
47
|
+
undef :to_a if respond_to?(:to_a)
|
48
|
+
|
49
|
+
def respond_to?(msg_id, priv=false)
|
50
|
+
case msg_id
|
51
|
+
when :_dump
|
52
|
+
true
|
53
|
+
when :marshal_dump
|
54
|
+
false
|
55
|
+
else
|
56
|
+
method_missing(:respond_to?, msg_id, priv)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_missing(msg_id, *a, &b)
|
61
|
+
promise = Promise.new
|
62
|
+
DRbConn.open(@uri) do |conn|
|
63
|
+
conn.send_message(self, msg_id, a, b) do |succ, result|
|
64
|
+
if succ
|
65
|
+
promise.resolve result
|
66
|
+
elsif DRbUnknown === result
|
67
|
+
promise.resolve result
|
68
|
+
else
|
69
|
+
bt = self.class.prepare_backtrace(@uri, result)
|
70
|
+
result.set_backtrace(bt + caller)
|
71
|
+
promise.resolve result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
promise
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.prepare_backtrace(uri, result)
|
79
|
+
prefix = "(#{uri}) "
|
80
|
+
bt = []
|
81
|
+
result.backtrace.each do |x|
|
82
|
+
break if /`__send__'$/ =~ x
|
83
|
+
if /^\(druby:\/\// =~ x
|
84
|
+
bt.push(x)
|
85
|
+
else
|
86
|
+
bt.push(prefix + x)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
bt
|
90
|
+
end
|
91
|
+
|
92
|
+
def pretty_print(q)
|
93
|
+
q.pp_object(self)
|
94
|
+
end
|
95
|
+
|
96
|
+
def pretty_print_cycle(q)
|
97
|
+
q.object_address_group(self) {
|
98
|
+
q.breakable
|
99
|
+
q.text '...'
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module DRb
|
2
|
+
module DRbProtocol
|
3
|
+
@protocol = [DRb::WebSocket] # default
|
4
|
+
end
|
5
|
+
|
6
|
+
module DRbProtocol
|
7
|
+
def add_protocol(prot)
|
8
|
+
@protocol.push(prot)
|
9
|
+
end
|
10
|
+
module_function :add_protocol
|
11
|
+
|
12
|
+
def open(uri, config, first=true)
|
13
|
+
@protocol.each do |prot|
|
14
|
+
begin
|
15
|
+
return prot.open(uri, config)
|
16
|
+
rescue DRbBadScheme
|
17
|
+
rescue DRbConnError
|
18
|
+
raise($!)
|
19
|
+
rescue
|
20
|
+
raise(DRbConnError, "#{uri} - #{$!.inspect}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
raise DRbBadURI, 'can\'t parse uri:' + uri
|
24
|
+
end
|
25
|
+
module_function :open
|
26
|
+
|
27
|
+
def uri_option(uri, config, first=true)
|
28
|
+
@protocol.each do |prot|
|
29
|
+
begin
|
30
|
+
uri, opt = prot.uri_option(uri, config)
|
31
|
+
return uri, opt
|
32
|
+
rescue DRbBadScheme
|
33
|
+
end
|
34
|
+
end
|
35
|
+
if first && (config[:auto_load] != false)
|
36
|
+
auto_load(uri)
|
37
|
+
return uri_option(uri, config, false)
|
38
|
+
end
|
39
|
+
raise DRbBadURI, 'can\'t parse uri:' + uri
|
40
|
+
end
|
41
|
+
module_function :uri_option
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'native'
|
2
|
+
require 'promise'
|
3
|
+
|
4
|
+
class ArrayBuffer
|
5
|
+
include Native
|
6
|
+
|
7
|
+
native_reader :buffer
|
8
|
+
native_reader :length
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
result = ""
|
12
|
+
arr = []
|
13
|
+
%x(
|
14
|
+
for (var i = 0; i < self.native.length; i ++) {
|
15
|
+
arr.push(self.native[i]);
|
16
|
+
result += String.fromCharCode(self.native[i]);
|
17
|
+
}
|
18
|
+
)
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class WebSocket
|
24
|
+
include Native
|
25
|
+
|
26
|
+
def initialize(url)
|
27
|
+
super `new WebSocket(url)`
|
28
|
+
`self.native.binaryType = 'arraybuffer'`
|
29
|
+
end
|
30
|
+
|
31
|
+
def onmessage
|
32
|
+
add_event_listener('message') {|event| yield MessageEvent.new(event) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def onopen
|
36
|
+
add_event_listener('open') {|event| yield MessageEvent.new(event) }
|
37
|
+
end
|
38
|
+
|
39
|
+
alias_native :close
|
40
|
+
alias_native :send
|
41
|
+
alias_native :add_event_listener, :addEventListener
|
42
|
+
|
43
|
+
class MessageEvent
|
44
|
+
include Native
|
45
|
+
|
46
|
+
def data
|
47
|
+
ArrayBuffer.new(`new Uint8Array(self.native.data)`)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module DRb
|
53
|
+
module WebSocket
|
54
|
+
class StrStream
|
55
|
+
def initialize(str='')
|
56
|
+
@buf = str
|
57
|
+
end
|
58
|
+
attr_reader :buf
|
59
|
+
|
60
|
+
def read(n)
|
61
|
+
begin
|
62
|
+
return @buf[0,n]
|
63
|
+
ensure
|
64
|
+
@buf = @buf[n, @buf.size - n]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def write(s)
|
69
|
+
@buf += s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.uri_option(uri, config)
|
74
|
+
return uri, nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.open(uri, config)
|
78
|
+
unless uri =~ /^ws:\/\/(.*?):(\d+)(\?(.*))?$/
|
79
|
+
raise(DRbBadScheme, uri) unless uri =~ /^ws:/
|
80
|
+
raise(DRbBadURI, 'can\'t parse uri:' + uri)
|
81
|
+
end
|
82
|
+
ClientSide.new(uri, config)
|
83
|
+
end
|
84
|
+
|
85
|
+
class ClientSide
|
86
|
+
def initialize(uri, config)
|
87
|
+
@uri = uri
|
88
|
+
@res = nil
|
89
|
+
@config = config
|
90
|
+
@msg = DRbMessage.new(config)
|
91
|
+
@proxy = ENV['HTTP_PROXY']
|
92
|
+
end
|
93
|
+
|
94
|
+
def close
|
95
|
+
end
|
96
|
+
|
97
|
+
def alive?
|
98
|
+
false
|
99
|
+
end
|
100
|
+
|
101
|
+
def send_request(ref, msg_id, *arg, &b)
|
102
|
+
stream = StrStream.new
|
103
|
+
@msg.send_request(stream, ref, msg_id, *arg, &b)
|
104
|
+
post(@uri, stream.buf)
|
105
|
+
end
|
106
|
+
|
107
|
+
def recv_reply(reply_stream)
|
108
|
+
@ws.close
|
109
|
+
@msg.recv_reply(reply_stream)
|
110
|
+
end
|
111
|
+
|
112
|
+
def post(uri, data)
|
113
|
+
promise = Promise.new
|
114
|
+
@ws = ::WebSocket.new(uri)
|
115
|
+
@ws.onmessage do |event|
|
116
|
+
reply_stream = StrStream.new
|
117
|
+
reply_stream.write(event.data.to_s)
|
118
|
+
|
119
|
+
if @config[:load_limit] < reply_stream.buf.size
|
120
|
+
raise TypeError, 'too large packet'
|
121
|
+
end
|
122
|
+
|
123
|
+
promise.resolve reply_stream
|
124
|
+
end
|
125
|
+
|
126
|
+
@ws.onopen do
|
127
|
+
@ws.send(`new Uint8Array(#{data.bytes.each_slice(2).map(&:first)}).buffer`)
|
128
|
+
end
|
129
|
+
promise
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
data/opal-drb.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'opal/drb/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "opal-drb"
|
8
|
+
spec.version = Opal::DRb::VERSION
|
9
|
+
spec.authors = ["youchan"]
|
10
|
+
spec.email = ["youchan01@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A dRuby implementation for Opal}
|
13
|
+
spec.description = %q{A dRuby implementation for Opal which is using WebSocket as Protocol.}
|
14
|
+
spec.homepage = "https://github.com/youchan/opal-drb"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
26
|
+
end
|
data/proc.rb
ADDED
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opal-drb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- youchan
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-07-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.14'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: A dRuby implementation for Opal which is using WebSocket as Protocol.
|
56
|
+
email:
|
57
|
+
- youchan01@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".travis.yml"
|
65
|
+
- Gemfile
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- bin/console
|
69
|
+
- bin/setup
|
70
|
+
- example/Gemfile
|
71
|
+
- example/Gemfile.lock
|
72
|
+
- example/app/application.rb
|
73
|
+
- example/assets/css/application.scss
|
74
|
+
- example/bin/console
|
75
|
+
- example/config.ru
|
76
|
+
- example/server.rb
|
77
|
+
- example/views/index.erb
|
78
|
+
- lib/opal/drb.rb
|
79
|
+
- lib/opal/drb/drb.rb
|
80
|
+
- lib/opal/drb/drb_conn.rb
|
81
|
+
- lib/opal/drb/drb_message.rb
|
82
|
+
- lib/opal/drb/drb_object.rb
|
83
|
+
- lib/opal/drb/drb_protocol.rb
|
84
|
+
- lib/opal/drb/version.rb
|
85
|
+
- lib/opal/drb/websocket.rb
|
86
|
+
- opal-drb.gemspec
|
87
|
+
- proc.rb
|
88
|
+
homepage: https://github.com/youchan/opal-drb
|
89
|
+
licenses: []
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.6.11
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: A dRuby implementation for Opal
|
111
|
+
test_files: []
|