pry-remote-em 0.6.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -38,7 +38,7 @@ program to connect itself to it:
38
38
 
39
39
  You can then connect to the pry session using ``pry-remote-em``:
40
40
 
41
- $ pry-remote-em
41
+ $ pry-remote-em pryem://127.0.0.1:6462/
42
42
  [pry-remote-em] client connected to pryem://127.0.0.1:6462/
43
43
  [pry-remote-em] remote is PryRemoteEm 0.1.0
44
44
  [1] pry(#<Foo>)> stat
@@ -69,7 +69,7 @@ You can then connect to the pry session using ``pry-remote-em``:
69
69
  [7] pry(#<Foo>)> exit
70
70
  [pry-remote-em] session terminated
71
71
 
72
- $ pry-remote-em
72
+ $ pry-remote-em pryem://127.0.0.1:6462/
73
73
  [pry-remote-em] client connected to pryem://127.0.0.1:6462/
74
74
  [pry-remote-em] remote is PryRemoteEm 0.1.0
75
75
  [1] pry(#<Foo>)> x
@@ -110,7 +110,8 @@ EM.run {
110
110
  [pry-remote-em] listening for connections on pryem://localhost:6466/
111
111
 
112
112
  ```shell
113
- $ pry-remote-em
113
+
114
+ $ pry-remote-em pryem://127.0.0.1:6462/
114
115
  [pry-remote-em] client connected to pryem://127.0.0.1:6462/
115
116
  [pry-remote-em] remote is PryRemoteEm 0.4.0 pryem
116
117
  [1] pry("pretty_print")>
@@ -136,6 +137,88 @@ $ pry-remote-em pryem://127.0.0.1:6466/
136
137
  [1] pry(#<RubyVM::InstructionSequence>)>
137
138
  ```
138
139
 
140
+ ## Server Broker
141
+
142
+ When more than one server is running on a given host and each server is
143
+ started with :auto it can be time consuming to manually figure out which
144
+ port each server is running on. The Broker which listens on port 6461
145
+ keeps track of which server is running on which port.
146
+
147
+ By default the pry-remote-em cli utility will connect to the broker and
148
+ retrieve a list of known servers. You can then select one to connect to
149
+ by its id, name or url. You can also choose to proxy your connection
150
+ through the broker to the selected server.
151
+
152
+ ```shell
153
+
154
+ $ bin/pry-remote-em
155
+ [pry-remote-em] client connected to pryem://127.0.0.1:6461/
156
+ [pry-remote-em] remote is PryRemoteEm 0.7.0 pryem
157
+ -----------------------------------------------------------------------------
158
+ | id | name | url |
159
+ -----------------------------------------------------------------------------
160
+ | 1 | #<#<Class:0x007f924b9bbee8>> | pryem://127.0.0.1:6462/ |
161
+ | 2 | #<Foo> | pryem://127.0.0.1:1337/ |
162
+ | 3 | #<#<Class:0x007f924b9bbee8>> | pryems://127.0.0.1:6463/ |
163
+ | 4 | #<#<Class:0x007f924b9bbee8>> | pryems://127.0.0.1:6464/ |
164
+ | 5 | #<#<Class:0x007f924b9bbee8>> | pryems://127.0.0.1:6465/ |
165
+ | 6 | #<#<Class:0x007f924b9bbee8>> | pryems://127.0.0.1:6466/ |
166
+ | 7 | #<#<Class:0x007f924b9bbee8>> | pryems://127.0.0.1:6467/ |
167
+ | 8 | #<#<Class:0x007f924b9bbee8>> | pryem://127.0.0.1:6468/ |
168
+ | 9 | #<#<Class:0x007f924b9bbee8>> | pryem://127.0.0.1:6469/ |
169
+ -----------------------------------------------------------------------------
170
+ (q) to quit; (r) to refresh (p) to proxy
171
+ connect to: 3
172
+ [pry-remote-em] client connected to pryem://127.0.0.1:6463/
173
+ [pry-remote-em] remote is PryRemoteEm 0.7.0 pryems
174
+ [pry-remote-em] negotiating TLS
175
+ [pry-remote-em] TLS connection established
176
+ [1] pry(#<#<Class:0x007f924b9bbee8>>)>
177
+ ```
178
+
179
+ By default the Broker will listen on 127.0.0.1:6461. To change the ip
180
+ address that the Broker binds to specify it in a PRYEMBROKER environment
181
+ variable, or in :broker_host option passed to #remote_pry_em.
182
+
183
+ ```shell
184
+
185
+ $ PRYEMBROKER=0.0.0.0 be ./test/service.rb
186
+ I, [2012-07-13T21:10:00.936993 #88528] INFO -- : [pry-remote-em] listening for connections on pryem://0.0.0.0:6462/
187
+ I, [2012-07-13T21:10:00.937132 #88528] INFO -- : [pry-remote-em broker] listening on pryem://0.0.0.0:6461
188
+ I, [2012-07-13T21:10:00.937264 #88528] INFO -- : [pry-remote-em] listening for connections on pryem://0.0.0.0:1337/
189
+ I, [2012-07-13T21:10:00.937533 #88528] INFO -- : [pry-remote-em] listening for connections on pryems://0.0.0.0:6463/
190
+ I, [2012-07-13T21:10:00.937804 #88528] INFO -- : [pry-remote-em] listening for connections on pryems://0.0.0.0:6464/
191
+ I, [2012-07-13T21:10:00.938126 #88528] INFO -- : [pry-remote-em] listening for connections on pryems://0.0.0.0:6465/
192
+ I, [2012-07-13T21:10:00.938471 #88528] INFO -- : [pry-remote-em] listening for connections on pryems://0.0.0.0:6466/
193
+ I, [2012-07-13T21:10:00.938835 #88528] INFO -- : [pry-remote-em] listening for connections on pryems://0.0.0.0:6467/
194
+ I, [2012-07-13T21:10:00.939230 #88528] INFO -- : [pry-remote-em] listening for connections on pryem://0.0.0.0:6468/
195
+ I, [2012-07-13T21:10:00.939640 #88528] INFO -- : [pry-remote-em] listening for connections on pryem://0.0.0.0:6469/
196
+ I, [2012-07-13T21:10:01.031576 #88528] INFO -- : [pry-remote-em broker] received client connection from 127.0.0.1:62288
197
+ I, [2012-07-13T21:10:01.031931 #88528] INFO -- : [pry-remote-em] client connected to pryem://127.0.0.1:6461/
198
+ I, [2012-07-13T21:10:01.032120 #88528] INFO -- : [pry-remote-em] remote is PryRemoteEm 0.7.0 pryem
199
+ I, [2012-07-13T21:10:01.032890 #88528] INFO -- : [pry-remote-em broker] registered pryem://127.0.0.1:6462/ - "#<#<Class:0x007f924b9bbee8>>"
200
+ I, [2012-07-13T21:10:01.125123 #88528] INFO -- : [pry-remote-em broker] registered pryem://127.0.0.1:6469/ - "#<#<Class:0x007f924b9bbee8>>"
201
+ I, [2012-07-13T21:10:01.125487 #88528] INFO -- : [pry-remote-em broker] registered pryems://127.0.0.1:6467/ - "#<#<Class:0x007f924b9bbee8>>"
202
+ I, [2012-07-13T21:10:01.490729 #88528] INFO -- : [pry-remote-em broker] registered pryems://127.0.0.1:6464/ - "#<#<Class:0x007f924b9bbee8>>"
203
+ I, [2012-07-13T21:10:01.583015 #88528] INFO -- : [pry-remote-em broker] registered pryem://127.0.0.1:1337/ - "#<Foo>"
204
+ I, [2012-07-13T21:10:01.674842 #88528] INFO -- : [pry-remote-em broker] registered pryems://127.0.0.1:6466/ - "#<#<Class:0x007f924b9bbee8>>"
205
+ I, [2012-07-13T21:10:01.766813 #88528] INFO -- : [pry-remote-em broker] registered pryem://127.0.0.1:6468/ - "#<#<Class:0x007f924b9bbee8>>"
206
+ I, [2012-07-13T21:10:01.858423 #88528] INFO -- : [pry-remote-em broker] registered pryems://127.0.0.1:6465/ - "#<#<Class:0x007f924b9bbee8>>"
207
+ ```
208
+
209
+ It is possible to have a pry-remote-em server register with a Broker
210
+ running on a different host. Just specify the Brokers address in the
211
+ PRYEMBROKER environment variable or the :broker_host option passed to #remote_pry_em.
212
+
213
+ To connect to a broker running on a seperate host with the cli client
214
+ just specify it on the command line ``bin/pry-remote-em preym://10.0.0.2:6461/``.
215
+ You can then proxy your client connections to remote servers through
216
+ that Broker.
217
+
218
+ The Broker will not run in TLS mode, but it can proxy connections to a
219
+ TLS enabled server.
220
+
221
+
139
222
  ## TLS Encryption
140
223
 
141
224
  When creating a server pass the :tls => true option to enable TLS.
@@ -369,9 +452,7 @@ E, [2012-02-11T19:23:40.770380 #36471] ERROR -- : refused to execute shell comma
369
452
 
370
453
  # Missing Features
371
454
 
372
- - AutoDiscovery/Broker [ticket](https://github.com/simulacre/pry-remote-em/issues/11)
373
455
  - HTTP Transport [ticket](https://github.com/simulacre/pry-remote-em/issues/12)
374
- - Vi mode editing - RbReadline doesn't support vi edit mode. I'm looking into contributing it. PryRemoteEm uses rb-readline because the STLIB version doesn't play nice with Fibers.
375
456
  - Ssh key based authentication
376
457
 
377
458
 
@@ -4,10 +4,10 @@ require 'uri'
4
4
  require 'highline'
5
5
  require 'pry-remote-em/client'
6
6
 
7
- uri = ARGV[0] || "pryem://localhost:#{PryRemoteEm::DEFPORT}"
7
+ uri = ARGV[0] || "pryem://localhost:#{PryRemoteEm::DEF_BROKERPORT}"
8
8
  uri = URI.parse(uri)
9
9
  unless %w(pryem pryems).include?(uri.scheme)
10
- abort "only pryem URIs are currently supported\n usage: pryem(s)://127.0.0.1:#{PryRemoteEm::DEFPORT}"
10
+ abort "only pryem URIs are currently supported\n usage: pryem(s)://127.0.0.1:#{PryRemoteEm::DEF_BROKERPORT}"
11
11
  end
12
12
 
13
13
  tried = 0
@@ -4,16 +4,18 @@ rescue LoadError
4
4
  warn "OpenSSL support is not available"
5
5
  end
6
6
  require 'pry-remote-em/version'
7
- require 'pry-remote-em/json-proto'
7
+ require 'pry-remote-em/proto'
8
8
  require 'eventmachine'
9
9
  require 'socket'
10
- require 'json'
11
- require "fiber"
10
+ require 'fiber'
11
+ require 'uri'
12
12
 
13
13
  module PryRemoteEm
14
- DEFHOST = 'localhost'
15
- DEFPORT = 6462
16
- NEGOTIMER = 15
14
+ DEFHOST = 'localhost'
15
+ DEFPORT = 6462
16
+ DEF_BROKERPORT = DEFPORT - 1
17
+ DEF_BROKERHOST = 'localhost'
18
+ NEGOTIMER = 15
17
19
  end
18
20
 
19
21
 
@@ -0,0 +1,189 @@
1
+ require 'pry-remote-em'
2
+ require 'pry-remote-em/client/broker'
3
+ require 'pry-remote-em/client/proxy'
4
+
5
+ module PryRemoteEm
6
+ module Broker
7
+ class << self
8
+ attr_reader :listening, :host, :port
9
+ alias :listening? :listening
10
+
11
+ def run(host = ENV['PRYEMBROKER'] || DEF_BROKERHOST, port = ENV['PRYEMBROKERPORT'] || DEF_BROKERPORT, opts = {:tls => false})
12
+ raise "root permission required for port below 1024 (#{port})" if port < 1024 && Process.euid != 0
13
+ @host = host
14
+ @port = port
15
+ # Brokers cannot use SSL directly. If they do then when a proxy request to an SSL server is received
16
+ # the client and server will not be able to negotiate a SSL session. The proxied traffic can be SSL
17
+ # encrypted, but the SSL session will be between the client and the server.
18
+ opts = opts.dup
19
+ opts[:tls] = false
20
+ @opts = opts
21
+ begin
22
+ EM.start_server(host, port, PryRemoteEm::Broker, opts) do |broker|
23
+ end
24
+ log.info("[pry-remote-em broker] listening on #{opts[:tls] ? 'pryems' : 'pryem'}://#{host}:#{port}")
25
+ @listening = true
26
+ rescue => e
27
+ # EM 1.0.0.beta4's message tells us the port is in use; 0.12.10 just says, 'no acceptor'
28
+ if (e.message.include?('port is in use') || e.message.include?('no acceptor'))
29
+ # [pry-remote-em broker] a broker is already listening on #{host}:#{port}
30
+ else
31
+ raise e
32
+ end
33
+ end
34
+ end
35
+
36
+ def restart
37
+ log.info("[pry-remote-em broker] restarting on pryem://#{host}:#{port}")
38
+ run(@host, @port, @opts)
39
+ EM::Timer.new(rand(0.9)) do
40
+ PryRemoteEm.servers.each do |url, (sig, name)|
41
+ next unless EM.get_sockname(sig)
42
+ register(url, name)
43
+ end
44
+ end
45
+ @waiting = nil
46
+ @client = nil
47
+ end
48
+
49
+ def opts
50
+ @opts ||= {}
51
+ end
52
+
53
+ def log
54
+ return opts[:logger] if opts[:logger]
55
+ @log ||= Logger.new(STDERR)
56
+ end
57
+
58
+ def servers
59
+ @servers ||= {}
60
+ end
61
+
62
+ def register(url, name = 'unknown')
63
+ client { |c| c.send_register_server(url, name) }
64
+ end
65
+
66
+ def unregister(server)
67
+ client {|c| c.send_unregister_server(server) }
68
+ end
69
+
70
+ def watch_heartbeats(url)
71
+ return if timers[url]
72
+ timers[url] = EM::PeriodicTimer.new(20) do
73
+ if !hbeats[url] || (Time.new - hbeats[url]) > 20
74
+ servers.delete(url)
75
+ timers[url].cancel
76
+ timers.delete(url)
77
+ end
78
+ end
79
+ end
80
+
81
+ def timers
82
+ @timers ||= {}
83
+ end
84
+
85
+ def hbeats
86
+ @hbeats ||= {}
87
+ end
88
+
89
+ def connected?
90
+ @connected
91
+ end
92
+
93
+ private
94
+
95
+ def client(&blk)
96
+ raise ArgumentError.new("A block is required") unless block_given?
97
+ if @client
98
+ yield @client
99
+ return
100
+ end
101
+
102
+ if @waiting
103
+ @waiting << blk
104
+ else
105
+ @waiting = []
106
+ EM.connect(host, port, Client::Broker, @opts) do |client|
107
+ client.errback { |e| raise(e || "broker client error") }
108
+ client.callback do
109
+ @client = client
110
+ while (w = @waiting.shift)
111
+ w.call(client)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end # class << self
118
+
119
+ include Proto
120
+
121
+ def receive_server_list
122
+ send_server_list(Broker.servers)
123
+ end
124
+
125
+ def receive_register_server(url, name)
126
+ url = URI.parse(url)
127
+ url.host = peer_ip if ['0.0.0.0', 'localhost', '127.0.0.1'].include?(url.host)
128
+ log.info("[pry-remote-em broker] registered #{url} - #{name.inspect}") unless Broker.servers[url] == name
129
+ Broker.servers[url] = name
130
+ Broker.hbeats[url] = Time.new
131
+ Broker.watch_heartbeats(url)
132
+ name
133
+ end
134
+
135
+ def receive_unregister_server(url)
136
+ url = URI.parse(url)
137
+ url.host = peer_ip if ['0.0.0.0', 'localhost', '127.0.0.1'].include?(url.host)
138
+ log.warn("[pry-remote-em broker] unregister #{url}")
139
+ Broker.servers.delete(url)
140
+ end
141
+
142
+ def receive_proxy_connection(url)
143
+ log.info("[pry-remote-em broker] proxying to #{url}")
144
+ url = URI.parse(url)
145
+ EM.connect(url.host, url.port, Client::Proxy, self)
146
+ end
147
+
148
+ def initialize(opts = {:tls => false}, &blk)
149
+ @opts = opts
150
+ end
151
+
152
+ def log
153
+ Broker.log
154
+ end
155
+
156
+ def post_init
157
+ port, ip = Socket.unpack_sockaddr_in(get_peername)
158
+ log.info("[pry-remote-em broker] received client connection from #{ip}:#{port}")
159
+ send_banner("PryRemoteEm #{VERSION} #{@opts[:tls] ? 'pryems' : 'pryem'}")
160
+ @opts[:tls] ? start_tls : send_server_list(Broker.servers)
161
+ end
162
+
163
+ def start_tls
164
+ log.debug("[pry-remote-em broker] starting TLS (#{peer_ip}:#{peer_port})")
165
+ send_start_tls
166
+ super(@opts[:tls].is_a?(Hash) ? @opts[:tls] : {})
167
+ end
168
+
169
+ def peer_ip
170
+ return @peer_ip if @peer_ip
171
+ return "" if get_peername.nil?
172
+ @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
173
+ @peer_ip
174
+ end
175
+
176
+ def peer_port
177
+ return @peer_port if @peer_port
178
+ return "" if get_peername.nil?
179
+ @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
180
+ @peer_port
181
+ end
182
+
183
+ def ssl_handshake_completed
184
+ log.info("[pry-remote-em broker] TLS connection established (#{peer_ip}:#{peer_port})")
185
+ send_server_list(Broker.servers)
186
+ end
187
+
188
+ end # module::Broker
189
+ end # module::PryRemoteEm
@@ -1,17 +1,19 @@
1
1
  require 'uri'
2
2
  require 'pry-remote-em'
3
- require 'pry-remote-em/client/keyboard'
3
+ begin
4
+ require 'pry-remote-em/client/keyboard'
5
+ rescue LoadError => e
6
+ warn "[pry-remote-em] unable to load keyboard depenencies (termios); interactive shell commands disabled"
7
+ end
8
+ require "pry-remote-em/client/generic"
4
9
  require 'pry/helpers/base_helpers'
5
- #require "readline" # doesn't work with Fiber.yield
6
- # - /Users/caleb/src/pry-remote-em/lib/pry-remote-em/client.rb:45:in `yield': fiber called across stack rewinding barrier (FiberError)
7
- require "rb-readline" # doesn't provide vi-mode support :(
8
- # https://github.com/luislavena/rb-readline/issues/21
9
- # https://github.com/simulacre/rb-readline/commit/0376eb4e9526b3dc1a6512716322efcef409628d
10
+ require "readline"
11
+ require 'highline'
10
12
 
11
13
  module PryRemoteEm
12
14
  module Client
13
15
  include EM::Deferrable
14
- include JsonProto
16
+ include Client::Generic
15
17
  include Pry::Helpers::BaseHelpers
16
18
 
17
19
  class << self
@@ -19,7 +21,7 @@ module PryRemoteEm
19
21
  EM.connect(host || PryRemoteEm::DEFHOST, port || PryRemoteEm::DEFPORT, PryRemoteEm::Client, opts) do |c|
20
22
  c.callback { yield if block_given? }
21
23
  c.errback do |e|
22
- puts "[pry-remote-em] connection failed\n#{e}"
24
+ Kernel.puts "[pry-remote-em] connection failed\n#{e}"
23
25
  yield(e) if block_given?
24
26
  end
25
27
  end
@@ -38,117 +40,182 @@ module PryRemoteEm
38
40
  end
39
41
 
40
42
  def post_init
41
- if get_peername
42
- port, ip = Socket.unpack_sockaddr_in(get_peername)
43
- Kernel.puts "[pry-remote-em] client connected to pryem://#{ip}:#{port}/"
44
- else
45
- # TODO use the args used to create this connection
46
- Kernel.puts "[pry-remote-em] client connected"
47
- end
48
- @nego_timer = EM::Timer.new(PryRemoteEm::NEGOTIMER) do
49
- fail("[pry-remote-em] server didn't finish negotiation within #{PryRemoteEm::NEGOTIMER} seconds; terminating")
50
- end
51
43
  Readline.completion_proc = method(:auto_complete)
52
44
  end
53
45
 
54
- def auto_complete(word)
55
- @waiting = Fiber.current
56
- send_data({:c => word})
57
- return Fiber.yield
46
+ def ssl_handshake_completed
47
+ log.info("[pry-remote-em] TLS connection established")
48
+ @opts[:tls] = true
58
49
  end
59
50
 
60
- def receive_json(j)
61
- if j['p'] # prompt
62
- readline(j['p'])
63
-
64
- elsif j['d'] # printable data
65
- stagger_output j['d'], $stdout # Pry::Helpers::BaseHelpers
66
-
67
- elsif j['m']
68
- Kernel.puts "\033[1m! msg: " + j['m'] + "\033[0m"
51
+ def unbind
52
+ if (uri = @reconnect_to)
53
+ @reconnect_to = nil
54
+ tls = uri.scheme == 'pryems'
55
+ log.info("\033[35m[pry-remote-em] connection will not be encrypted\033[0m") if @opts[:tls] && !tls
56
+ @opts[:tls] = tls
57
+ @tls_started = false
58
+ reconnect(uri.host, uri.port)
59
+ else
60
+ @unbound = true
61
+ log.info("[pry-remote-em] session terminated")
62
+ # prior to 1.0.0.b4 error? returns true here even when it's not
63
+ return succeed if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
64
+ error? ? fail : succeed
65
+ end
66
+ end
69
67
 
70
- elsif j['mb']
71
- Kernel.puts "\033[1m!! msg: " + j['mb'] + "\033[0m"
68
+ def receive_banner(name, version, scheme)
69
+ # Client::Generic#receive_banner
70
+ if super(name, version, scheme)
71
+ start_tls if @opts[:tls]
72
+ end
73
+ end
72
74
 
73
- elsif j['s'] # shell command output
74
- Kernel.puts j['s']
75
+ def receive_server_list(list)
76
+ if list.empty?
77
+ log.info("\033[33m[pry-remote-em] no servers are registered with the broker\033[0m")
78
+ Process.exit
79
+ end
80
+ choice, proxy = choose_server(list)
81
+ return unless choice
82
+ uri, name = URI.parse(choice[0]), choice[1]
83
+ if proxy
84
+ @opts[:tls] = uri.scheme == 'pryems'
85
+ @negotiated = false
86
+ @tls_started = false
87
+ return send_proxy_connection(uri)
88
+ end
89
+ @reconnect_to = uri
90
+ close_connection
91
+ end
75
92
 
76
- elsif j.include?('sc') # command completed
77
- if @keyboard
78
- @keyboard.bufferio(true)
79
- @keyboard.close_connection
93
+ def choose_server(list)
94
+ highline = HighLine.new
95
+ proxy = false
96
+ choice = nil
97
+ nm_col_len = list.values.map(&:length).sort[-1] + 5
98
+ ur_col_len = list.keys.map(&:length).sort[-1] + 5
99
+ header = sprintf("| %-3s | %-#{nm_col_len}s | %-#{ur_col_len}s |", "id", "name", "url")
100
+ border = ("-" * header.length)
101
+ table = [border, header, border]
102
+ list = list.to_a
103
+ list.each_with_index do |(url, name), idx|
104
+ table << sprintf("| %-2d | %-#{nm_col_len}s | %-#{ur_col_len}s |", idx + 1, name, url)
105
+ end
106
+ table << border
107
+ table = table.join("\n")
108
+ Kernel.puts table
109
+ while choice.nil?
110
+ if proxy
111
+ question = "(q) to quit; (r) to refresh (c) to connect\nproxy to: "
112
+ else
113
+ question = "(q) to quit; (r) to refresh (p) to proxy\nconnect to: "
80
114
  end
81
-
82
- elsif j['g'] # server banner
83
- Kernel.puts "[pry-remote-em] remote is #{j['g']}"
84
- name, version, scheme = j['g'].split(" ", 3)
85
- # TODO parse version and compare against a Gem style matcher
86
- # https://github.com/simulacre/pry-remote-em/issues/21
87
- return fail("[pry-remote-em] incompatible version #{version}") if version != PryRemoteEm::VERSION
88
- if scheme.nil? || scheme != (reqscheme = @opts[:tls] ? 'pryems' : 'pryem')
89
- if scheme == 'pryems' && defined?(::OpenSSL)
90
- @opts[:tls] = true
91
- else
92
- return fail("[pry-remote-em] server doesn't support required scheme #{reqscheme.dump}")
93
- end # scheme == 'pryems' && defined?(::OpenSSL)
115
+ choice = highline.ask(question)
116
+ return close_connection if ['q', 'quit', 'exit'].include?(choice.downcase)
117
+ if ['r', 'reload', 'refresh'].include?(choice.downcase)
118
+ send_server_list
119
+ return nil
94
120
  end
95
- @nego_timer.cancel
96
- @negotiated = true
97
- start_tls if @opts[:tls]
121
+ if ['c', 'connect'].include?(choice.downcase)
122
+ proxy = false
123
+ choice = nil
124
+ next
125
+ end
126
+ if ['p', 'proxy'].include?(choice.downcase)
127
+ proxy = true
128
+ choice = nil
129
+ next
130
+ end
131
+ choice = choice.to_i.to_s == choice ?
132
+ list[choice.to_i - 1] :
133
+ list.find{|(url, name)| url == choice || name == choice }
134
+ end
135
+ [choice, proxy]
136
+ end
98
137
 
99
- elsif j['c'] # tab completion response
100
- @waiting, f = nil, @waiting
101
- f.resume(j['c']) if f
138
+ def receive_auth(a)
139
+ return fail a if a.is_a?(String)
140
+ return authenticate if a == false
141
+ @authenticated = true if a == true
142
+ end
102
143
 
103
- elsif j.include?('a') # authentication demand
104
- return fail j['a'] if j['a'].is_a?(String)
105
- return authenticate if j['a'] == false
106
- @authenticated = true if j['a'] == true
144
+ def receive_msg(m)
145
+ Kernel.puts "\033[1m! msg: " + m + "\033[0m"
146
+ end
107
147
 
108
- else
109
- warn "[pry-remote-em] received unexpected data: #{j.inspect}"
148
+ def receive_msg_bcast(mb)
149
+ Kernel.puts "\033[1m!! msg: " + mb + "\033[0m"
150
+ end
151
+
152
+ def receive_shell_cmd(c)
153
+ Kernel.puts c
154
+ end
155
+
156
+ def receive_shell_result(c)
157
+ if @keyboard
158
+ @keyboard.bufferio(true)
159
+ @keyboard.close_connection
110
160
  end
111
161
  end
112
162
 
163
+ def receive_raw(r)
164
+ # Pry::Helpers::BaseHelpers
165
+ stagger_output(r, $stdout)
166
+ end
167
+
168
+ def receive_unknown(j)
169
+ warn "[pry-remote-em] received unexpected data: #{j.inspect}"
170
+ end
171
+
113
172
  def authenticate
114
173
  return fail("[pry-remote-em] authentication required") unless @auth
115
174
  return fail("[pry-remote-em] can't authenticate before negotiation complete") unless @negotiated
116
175
  user, pass = @auth.call
117
176
  return fail("[pry-remote-em] expected #{@auth} to return a user and password") unless user && pass
118
- send_data({:a => [user, pass]})
177
+ send_auth([user, pass])
119
178
  end # authenticate
120
179
 
121
- def ssl_handshake_completed
122
- Kernel.puts "[pry-remote-em] TLS connection established"
180
+ def auto_complete(word)
181
+ @waiting = Thread.current
182
+ EM.next_tick { send_completion(word) }
183
+ sleep
184
+ c = Thread.current[:completion]
185
+ Thread.current[:completion] = nil
186
+ c
123
187
  end
124
188
 
125
- def start_tls
126
- Kernel.puts "[pry-remote-em] negotiating TLS"
127
- super(@opts[:tls].is_a?(Hash) ? @opts[:tls] : {})
189
+ def receive_completion(c)
190
+ return unless @waiting
191
+ @waiting[:completion] = c
192
+ @waiting, t = nil, @waiting
193
+ t.run
128
194
  end
129
195
 
130
- def unbind
131
- @unbound = true
132
- Kernel.puts "[pry-remote-em] session terminated"
133
- # prior to 1.0.0.b4 error? returns true here even when it's not
134
- return succeed if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
135
- error? ? fail : succeed
196
+ def receive_prompt(p)
197
+ readline(p)
136
198
  end
137
199
 
138
200
  def readline(prompt)
139
201
  if @negotiated && !@unbound
140
- Fiber.new {
141
- l = Readline.readline(prompt, !prompt.nil?)
202
+ op = proc { Readline.readline(prompt, !prompt.nil?) }
203
+ callback = proc do |l|
142
204
  if '!!' == l[0..1]
143
- send_data({:b => l[2..-1]})
205
+ send_msg_bcast(l[2..-1])
144
206
  elsif '!' == l[0]
145
- send_data({:m => l[1..-1]})
207
+ send_msg(l[1..-1])
146
208
  elsif '.' == l[0]
147
- send_data({:s => l[1..-1]})
148
- if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
149
- Kernel.puts "\033[1minteractive shell commands are not well supported when running on EventMachine prior 1.0.0.beta4\033[0m"
209
+ if !Client.const_defined?(:Keyboard)
210
+ Kernel.puts "\033[31minteractive shell commands are not supported without termios\033[0m"
211
+ readline(prompt)
150
212
  else
151
- @keyboard = EM.open_keyboard(Keyboard, self)
213
+ send_shell_cmd(l[1..-1])
214
+ if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
215
+ Kernel.puts "\033[1minteractive shell commands are not well supported when running on EventMachine prior to 1.0.0.beta4\033[0m"
216
+ else
217
+ @keyboard = EM.open_keyboard(Keyboard, self)
218
+ end
152
219
  end
153
220
  elsif 'reset' == l.strip
154
221
  # TODO work with 'bundle exec pry-remote-em ...'
@@ -156,9 +223,10 @@ module PryRemoteEm
156
223
  Kernel.puts "\033[1m#{$0} #{ARGV.join(' ')}\033[0m"
157
224
  exec("#{$0} #{ARGV.join(' ')}")
158
225
  else
159
- send_data(l)
226
+ send_raw(l)
160
227
  end # "!!" == l[0..1]
161
- }.resume
228
+ end
229
+ EM.defer(op, callback)
162
230
  end
163
231
  end # readline(prompt = @last_prompt)
164
232