distributor 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,26 +20,29 @@ class Distributor::Client
20
20
  @multiplexer.input io
21
21
  end
22
22
 
23
- @connector.on_close(input) do |io|
24
- @multiplexer.output 0, JSON.dump({ "command" => "close", "ch" => ch })
25
- end
23
+ # @connector.on_close(input) do |io|
24
+ # p [:cl1, input]
25
+ # @multiplexer.output 0, JSON.dump({ "command" => "close", "ch" => ch })
26
+ # end
26
27
 
27
28
  # handle the command channel of the multiplexer
28
29
  @connector.handle(@multiplexer.reader(0)) do |io|
29
- data = JSON.parse(io.readpartial(4096))
30
-
31
- case command = data["command"]
32
- when "close" then
33
- ch = data["ch"]
34
- @on_close[ch].each { |c| c.call(ch) }
35
- when "launch" then
36
- ch = data["ch"]
37
- @multiplexer.reserve ch
38
- @handlers[data["id"]].call(ch)
39
- @handlers.delete(data["id"])
40
- @processes << ch
41
- else
42
- raise "no such command: #{command}"
30
+ append_json(io.readpartial(4096))
31
+
32
+ dequeue_json do |data|
33
+ case command = data["command"]
34
+ when "close" then
35
+ ch = data["ch"]
36
+ @on_close[ch].each { |c| c.call(ch) }
37
+ when "ack" then
38
+ ch = data["ch"]
39
+ @multiplexer.reserve ch
40
+ @handlers[data["id"]].call(ch)
41
+ @handlers.delete(data["id"])
42
+ @processes << ch
43
+ else
44
+ raise "no such command: #{command}"
45
+ end
43
46
  end
44
47
  end
45
48
  end
@@ -49,12 +52,18 @@ class Distributor::Client
49
52
  end
50
53
 
51
54
  def run(command, &handler)
52
- id = "#{Time.now.to_f}-#{rand(10000)}"
55
+ id = generate_id
53
56
  @multiplexer.output 0, JSON.dump({ "id" => id, "command" => "run", "args" => command })
54
57
  @handlers[id] = handler
55
58
  end
56
59
 
57
- def hookup(ch, input, output)
60
+ def tunnel(port, &handler)
61
+ id = generate_id
62
+ @multiplexer.output 0, JSON.dump({ "id" => id, "command" => "tunnel", "port" => port })
63
+ @handlers[id] = handler
64
+ end
65
+
66
+ def hookup(ch, input, output=input)
58
67
  # handle data incoming on the multiplexer
59
68
  @connector.handle(@multiplexer.reader(ch)) do |io|
60
69
  begin
@@ -85,4 +94,22 @@ class Distributor::Client
85
94
  loop { @connector.listen }
86
95
  end
87
96
 
97
+ private
98
+
99
+ def generate_id
100
+ id = "#{Time.now.to_f}-#{rand(10000)}"
101
+ end
102
+
103
+ def append_json(data)
104
+ @json ||= ""
105
+ @json += data
106
+ end
107
+
108
+ def dequeue_json
109
+ while idx = @json.index("}")
110
+ yield JSON.parse(@json[0..idx])
111
+ @json = @json[idx+1..-1]
112
+ end
113
+ end
114
+
88
115
  end
@@ -20,9 +20,15 @@ class Distributor::Connector
20
20
  def listen
21
21
  rs, ws = IO.select(@connections.keys)
22
22
  rs.each do |from|
23
- @on_close.each { |c| c.call } if from.eof?
23
+ @on_close.each { |c| c.call(from) } if from.eof?
24
24
  self.connections[from].call(from)
25
25
  end
26
26
  end
27
27
 
28
+ def close(io)
29
+ @connections.delete(io)
30
+ @on_close[io].each { |c| c.call(io) }
31
+ exit 1
32
+ end
33
+
28
34
  end
@@ -40,7 +40,7 @@ class Distributor::Multiplexer
40
40
  end
41
41
 
42
42
  def close(ch)
43
- writer(ch).close
43
+ output 0, JSON.dump({ "command" => "close", "ch" => ch })
44
44
  rescue IOError
45
45
  end
46
46
 
@@ -2,6 +2,7 @@ require "distributor"
2
2
  require "distributor/connector"
3
3
  require "distributor/multiplexer"
4
4
  require "pty"
5
+ require "socket"
5
6
 
6
7
  class Distributor::Server
7
8
 
@@ -17,18 +18,27 @@ class Distributor::Server
17
18
  @multiplexer.input io
18
19
  end
19
20
 
21
+ @connector.on_close(input) do |ch|
22
+ exit 0
23
+ end
24
+
20
25
  # handle the command channel of the multiplexer
21
26
  @connector.handle(@multiplexer.reader(0)) do |io|
22
- data = JSON.parse(io.readpartial(4096))
23
-
24
- case command = data["command"]
25
- when "close" then
26
- @multiplexer.close data["ch"]
27
- when "run" then
28
- ch = run(data["args"])
29
- @multiplexer.output 0, JSON.dump({ "id" => data["id"], "command" => "launch", "ch" => ch })
30
- else
31
- raise "no such command: #{command}"
27
+ append_json(io.readpartial(4096))
28
+
29
+ dequeue_json do |data|
30
+ case command = data["command"]
31
+ when "tunnel" then
32
+ ch = tunnel(data["port"])
33
+ @multiplexer.output 0, JSON.dump({ "id" => data["id"], "command" => "ack", "ch" => ch })
34
+ when "close" then
35
+ @multiplexer.close data["ch"]
36
+ when "run" then
37
+ ch = run(data["args"])
38
+ @multiplexer.output 0, JSON.dump({ "id" => data["id"], "command" => "ack", "ch" => ch })
39
+ else
40
+ raise "no such command: #{command}"
41
+ end
32
42
  end
33
43
  end
34
44
  end
@@ -43,7 +53,8 @@ class Distributor::Server
43
53
  begin
44
54
  @multiplexer.output(ch, io.readpartial(4096))
45
55
  rescue EOFError
46
- @multiplexer.output 0, JSON.dump({ "command" => "close", "ch" => ch })
56
+ @multiplexer.close(ch)
57
+ @connector.close(io)
47
58
  end
48
59
  end
49
60
 
@@ -56,11 +67,45 @@ class Distributor::Server
56
67
  ch
57
68
  end
58
69
 
59
- def close(ch)
60
- end
70
+ def tunnel(port)
71
+ ch = @multiplexer.reserve
72
+
73
+ tcp = TCPSocket.new("localhost", port)
74
+
75
+ # handle data incoming from process
76
+ @connector.handle(tcp) do |io|
77
+ begin
78
+ @multiplexer.output(ch, io.readpartial(4096))
79
+ rescue EOFError
80
+ @multiplexer.close(ch)
81
+ @connector.close(io)
82
+ end
83
+ end
61
84
 
85
+ # handle data incoming on the multiplexer
86
+ @connector.handle(@multiplexer.reader(ch)) do |input_io|
87
+ data = input_io.readpartial(4096)
88
+ tcp.write data
89
+ end
90
+
91
+ ch
92
+ end
62
93
  def start
63
94
  loop { @connector.listen }
64
95
  end
65
96
 
97
+ private
98
+
99
+ def append_json(data)
100
+ @json ||= ""
101
+ @json += data
102
+ end
103
+
104
+ def dequeue_json
105
+ while idx = @json.index("}")
106
+ yield JSON.parse(@json[0..idx])
107
+ @json = @json[idx+1..-1]
108
+ end
109
+ end
110
+
66
111
  end
@@ -1,5 +1,5 @@
1
1
  module Distributor
2
2
 
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
 
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: distributor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-06-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
16
- requirement: &70336779621500 !ruby/object:Gem::Requirement
16
+ requirement: &70208191262780 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 0.13.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70336779621500
24
+ version_requirements: *70208191262780
25
25
  description: TCP Multiplexer
26
26
  email: ddollar@gmail.com
27
27
  executables: []