pry-remote-em 0.7.5 → 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +140 -0
- data/README.md +347 -63
- data/bin/pry-remote-em +40 -21
- data/bin/pry-remote-em-broker +28 -0
- data/lib/pry-remote-em.rb +23 -12
- data/lib/pry-remote-em/broker.rb +85 -63
- data/lib/pry-remote-em/client.rb +75 -130
- data/lib/pry-remote-em/client/broker.rb +6 -3
- data/lib/pry-remote-em/client/generic.rb +7 -6
- data/lib/pry-remote-em/client/interactive_menu.rb +171 -0
- data/lib/pry-remote-em/client/keyboard.rb +11 -15
- data/lib/pry-remote-em/client/proxy.rb +3 -2
- data/lib/pry-remote-em/proto.rb +58 -77
- data/lib/pry-remote-em/sandbox.rb +47 -0
- data/lib/pry-remote-em/server.rb +156 -75
- data/lib/pry-remote-em/server/shell_cmd.rb +1 -1
- data/lib/pry-remote-em/version.rb +1 -1
- metadata +52 -42
data/bin/pry-remote-em
CHANGED
@@ -1,34 +1,38 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'uri'
|
4
|
+
require 'readline'
|
4
5
|
require 'highline'
|
5
6
|
require 'pry-remote-em/client'
|
6
7
|
require 'optparse'
|
7
8
|
|
8
9
|
options = {}
|
9
10
|
OptionParser.new do |opts|
|
10
|
-
opts.on(
|
11
|
+
opts.on('-c', '--connect NAME', 'connect to the first pry remote em server matching NAME') do |name|
|
11
12
|
options[:connect] = name
|
12
|
-
end
|
13
|
-
opts.on(
|
13
|
+
end
|
14
|
+
opts.on('-p', '--proxy NAME', 'proxy through the broker to the first pry remote em server matching NAME') do |name|
|
14
15
|
options[:proxy] = name
|
15
|
-
end
|
16
|
+
end
|
17
|
+
opts.on('-P', '--proxy-by-default', 'show servers table with proxy mode enabled by default (ignored on -c or -p)') do |name|
|
18
|
+
options[:proxy_by_default] = true
|
19
|
+
end
|
16
20
|
|
17
|
-
opts.on(
|
21
|
+
opts.on('--fh HOST', '--filter-host HOST', 'only show servers listening at the given address (regexp)') do |host|
|
18
22
|
if host =~ /^pryems?:\/\//
|
19
23
|
ARGV.push(host)
|
20
|
-
else
|
24
|
+
else
|
21
25
|
options[:filter_host] = Regexp.new(host)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
opts.on(
|
26
|
+
end
|
27
|
+
end
|
28
|
+
opts.on('--fn NAME', '--filter-name NAME', 'only show servers with a matching name (regexp)') do |name|
|
25
29
|
if name =~ /^pryems?:\/\//
|
26
30
|
ARGV.push(name)
|
27
|
-
else
|
31
|
+
else
|
28
32
|
options[:filter_name] = Regexp.new(name)
|
29
|
-
end
|
33
|
+
end
|
30
34
|
end
|
31
|
-
opts.on(
|
35
|
+
opts.on('--[no-]fs', '--[no-]filter-ssl', 'show only servers that support ssl') do |ssl|
|
32
36
|
options[:filter_ssl] = ssl
|
33
37
|
end
|
34
38
|
|
@@ -37,30 +41,45 @@ OptionParser.new do |opts|
|
|
37
41
|
opts.on('--sp', '--sort-port', 'sort by port') { options[:sort] = :port }
|
38
42
|
opts.on('--ss', '--sort-ssl', 'sort by ssl support') { options[:sort] = :ssl }
|
39
43
|
|
44
|
+
opts.on('-d', '--details KEY', "show value from server's details option by given key instead of url in table, use @ to show all details") do |key|
|
45
|
+
options[:show_details] = key
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on('-i', '--ignore-localhost', 'filter out localhost urls from list') do
|
49
|
+
options[:ignore_localhost] = true
|
50
|
+
end
|
51
|
+
|
40
52
|
opts.parse!(ARGV)
|
41
|
-
end
|
53
|
+
end
|
42
54
|
|
43
|
-
uri = ARGV[0] ||
|
55
|
+
uri = if ARGV[0].nil? || ARGV[0].empty?
|
56
|
+
host = ENV['PRYEMBROKER'].nil? || ENV['PRYEMBROKER'].empty? ? PryRemoteEm::DEFAULT_BROKER_HOST : ENV['PRYEMBROKER']
|
57
|
+
port = ENV['PRYEMBROKERPORT'].nil? || ENV['PRYEMBROKERPORT'].empty? ? PryRemoteEm::DEFAULT_BROKER_PORT : ENV['PRYEMBROKERPORT']
|
58
|
+
"pryem://#{host}:#{port}"
|
59
|
+
else
|
60
|
+
ARGV[0]
|
61
|
+
end
|
44
62
|
uri = URI.parse(uri)
|
45
63
|
unless %w(pryem pryems).include?(uri.scheme)
|
46
|
-
abort "only pryem URIs are currently supported\n usage: pryem[s]
|
64
|
+
abort "only pryem URIs are currently supported\n usage: pryem[s]://#{PryRemoteEm::DEFAULT_BROKER_HOST}:#{PryRemoteEm::DEFAULT_BROKER_PORT}"
|
47
65
|
end
|
48
|
-
uri.port = PryRemoteEm::
|
66
|
+
uri.port = PryRemoteEm::DEFAULT_BROKER_PORT unless uri.port
|
49
67
|
|
50
68
|
tried = 0
|
51
69
|
auth_proc = proc do
|
52
70
|
tried += 1
|
53
|
-
user = uri.user || ($stdin.tty? ? Readline.readline(
|
71
|
+
user = uri.user || ($stdin.tty? ? Readline.readline('user: ') : raise('username is require for authentication'))
|
54
72
|
pass = if !uri.password.nil? && tried <= 1
|
55
73
|
uri.password
|
56
74
|
elsif $stdin.tty?
|
57
|
-
HighLine.new.ask("#{user}'s password: ") { |q| q.echo = '*'}
|
75
|
+
HighLine.new.ask("#{user}'s password: ") { |q| q.echo = '*' }
|
58
76
|
else
|
59
|
-
raise
|
60
|
-
end
|
77
|
+
raise 'password is required to authenticate'
|
78
|
+
end
|
61
79
|
[user, pass]
|
62
80
|
end
|
63
81
|
|
64
82
|
EM.run do
|
65
|
-
|
83
|
+
client_options = options.merge(auth: auth_proc, tls: uri.scheme == 'pryems')
|
84
|
+
PryRemoteEm::Client.start(uri.host, uri.port, client_options) { EM.stop }
|
66
85
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pry-remote-em/broker'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = { tls: false }
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.on('-h', '--host HOST', 'host to bind broker server (same as PRYEMBROKER variable, default: "127.0.0.1")') do |host|
|
9
|
+
options[:host] = host
|
10
|
+
end
|
11
|
+
|
12
|
+
opts.on('-p', '--port PORT', 'port to bind broker server (same as PRYEMBROKERPORT variable, default: 6462)') do |port|
|
13
|
+
options[:port] = port
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on('-s', '--tls', 'use TLS for broker (default: false)') do
|
17
|
+
options[:tls] = true
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.parse!(ARGV)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
EM.run do
|
25
|
+
trap(:INT) { EM.stop }
|
26
|
+
|
27
|
+
PryRemoteEm::Broker.run options[:host], options[:port], tls: options[:tls], raise_if_port_in_use: true
|
28
|
+
end
|
data/lib/pry-remote-em.rb
CHANGED
@@ -1,29 +1,40 @@
|
|
1
1
|
begin
|
2
2
|
require 'openssl'
|
3
3
|
rescue LoadError
|
4
|
-
warn
|
4
|
+
warn 'OpenSSL support is not available'
|
5
5
|
end
|
6
|
-
require 'pry-remote-em/version'
|
7
|
-
require 'pry-remote-em/proto'
|
8
|
-
require 'eventmachine'
|
9
6
|
require 'socket'
|
10
7
|
require 'fiber'
|
11
8
|
require 'uri'
|
9
|
+
require 'eventmachine'
|
10
|
+
require 'pry-remote-em/version'
|
11
|
+
require 'pry-remote-em/proto'
|
12
|
+
require 'pry-remote-em/server'
|
12
13
|
|
13
14
|
module PryRemoteEm
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
DEFAULT_SERVER_HOST = '127.0.0.1'
|
16
|
+
DEFAULT_SERVER_PORT = 6463
|
17
|
+
DEFAULT_BROKER_HOST = '127.0.0.1'
|
18
|
+
DEFAULT_BROKER_PORT = 6462
|
19
|
+
|
20
|
+
NEGOTIATION_TIMEOUT = 15
|
21
|
+
HEARTBEAT_SEND_INTERVAL = 15
|
22
|
+
HEARTBEAT_CHECK_INTERVAL = 20
|
23
|
+
RECONNECT_TO_BROKER_TIMEOUT = 3
|
24
|
+
|
25
|
+
MAXIMUM_ERRORS_IN_SANDBOX = 100
|
19
26
|
end
|
20
27
|
|
21
28
|
|
22
29
|
class Object
|
23
|
-
def remote_pry_em(host =
|
24
|
-
|
25
|
-
|
30
|
+
def remote_pry_em(host = nil, port = nil, options = {}, &block)
|
31
|
+
host, options = nil, host if host.kind_of?(Hash) # Support for options hash as first argument instead of third
|
32
|
+
|
33
|
+
options = { target: self, host: host, port: port }.merge(options)
|
34
|
+
PryRemoteEm::Server.run(options, &block)
|
26
35
|
end
|
36
|
+
|
37
|
+
alias pry_remote_em remote_pry_em # source of common confusing
|
27
38
|
end
|
28
39
|
|
29
40
|
|
data/lib/pry-remote-em/broker.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'logger'
|
1
2
|
require 'socket'
|
2
3
|
require 'pry-remote-em'
|
3
4
|
require 'pry-remote-em/client/broker'
|
@@ -9,29 +10,20 @@ module PryRemoteEm
|
|
9
10
|
attr_reader :listening, :host, :port
|
10
11
|
alias :listening? :listening
|
11
12
|
|
12
|
-
def run(host =
|
13
|
+
def run(host = nil, port = nil, opts = {})
|
14
|
+
host ||= ENV['PRYEMBROKER'].nil? || ENV['PRYEMBROKER'].empty? ? DEFAULT_BROKER_HOST : ENV['PRYEMBROKER']
|
15
|
+
port ||= ENV['PRYEMBROKERPORT'].nil? || ENV['PRYEMBROKERPORT'].empty? ? DEFAULT_BROKER_PORT : ENV['PRYEMBROKERPORT']
|
16
|
+
port = port.to_i if port.kind_of?(String)
|
13
17
|
raise "root permission required for port below 1024 (#{port})" if port < 1024 && Process.euid != 0
|
14
|
-
@host
|
15
|
-
@port
|
18
|
+
@host = host
|
19
|
+
@port = port
|
20
|
+
opts = opts.dup
|
16
21
|
# Brokers cannot use SSL directly. If they do then when a proxy request to an SSL server is received
|
17
22
|
# the client and server will not be able to negotiate a SSL session. The proxied traffic can be SSL
|
18
23
|
# encrypted, but the SSL session will be between the client and the server.
|
19
|
-
opts = opts.dup
|
20
24
|
opts[:tls] = false
|
21
|
-
@opts
|
22
|
-
|
23
|
-
EM.start_server(host, port, PryRemoteEm::Broker, opts) do |broker|
|
24
|
-
end
|
25
|
-
log.info("[pry-remote-em broker] listening on #{opts[:tls] ? 'pryems' : 'pryem'}://#{host}:#{port}")
|
26
|
-
@listening = true
|
27
|
-
rescue => e
|
28
|
-
# EM 1.0.0.beta4's message tells us the port is in use; 0.12.10 just says, 'no acceptor'
|
29
|
-
if (e.message.include?('port is in use') || e.message.include?('no acceptor'))
|
30
|
-
# [pry-remote-em broker] a broker is already listening on #{host}:#{port}
|
31
|
-
else
|
32
|
-
raise e
|
33
|
-
end
|
34
|
-
end
|
25
|
+
@opts = opts
|
26
|
+
start_server(host, port, opts) unless @listening || ENV['PRYEMREMOTEBROKER'] || @opts[:remote_broker]
|
35
27
|
client { |c| yield self } if block_given?
|
36
28
|
end
|
37
29
|
|
@@ -40,9 +32,9 @@ module PryRemoteEm
|
|
40
32
|
@waiting = nil
|
41
33
|
@client = nil
|
42
34
|
run(@host, @port, @opts) do
|
43
|
-
PryRemoteEm.servers.each do |
|
44
|
-
next unless EM.get_sockname(
|
45
|
-
register(
|
35
|
+
PryRemoteEm.servers.each do |id, description|
|
36
|
+
next unless EM.get_sockname(description[:server])
|
37
|
+
register(id: description[:id], urls: description[:urls], name: description[:name], details: description[:details])
|
46
38
|
end
|
47
39
|
end
|
48
40
|
end
|
@@ -60,31 +52,38 @@ module PryRemoteEm
|
|
60
52
|
@servers ||= {}
|
61
53
|
end
|
62
54
|
|
63
|
-
def register(
|
64
|
-
|
65
|
-
client { |c| c.send_register_server(u, name) }
|
66
|
-
end
|
55
|
+
def register(description)
|
56
|
+
client { |c| c.send_register_server(description[:id], description[:urls], description[:name], description[:details]) }
|
67
57
|
end
|
68
58
|
|
69
|
-
def unregister(
|
70
|
-
|
71
|
-
|
72
|
-
|
59
|
+
def unregister(id)
|
60
|
+
client { |c| c.send_unregister_server(id) }
|
61
|
+
end
|
62
|
+
|
63
|
+
def register_server(id, description)
|
64
|
+
servers[id] = description
|
65
|
+
watch_heartbeats(id)
|
66
|
+
log.info("[pry-remote-em broker] registered #{id} #{description.inspect}")
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_server(server, description)
|
70
|
+
server.update(urls: description[:urls], name: description[:name])
|
71
|
+
server[:details].update(description[:details])
|
73
72
|
end
|
74
73
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
def unregister_server(id)
|
75
|
+
server = servers.delete(id) or return
|
76
|
+
log.warn("[pry-remote-em broker] unregister #{id} #{server.inspect}")
|
77
|
+
timer = timers.delete(id)
|
78
|
+
timer.cancel if timer
|
79
|
+
hbeats.delete(id)
|
79
80
|
end
|
80
81
|
|
81
|
-
def watch_heartbeats(
|
82
|
-
|
83
|
-
timers[
|
84
|
-
if !hbeats[
|
85
|
-
|
86
|
-
timers[url].cancel
|
87
|
-
timers.delete(url)
|
82
|
+
def watch_heartbeats(id)
|
83
|
+
interval = ENV['PRYEMHBCHECK'].nil? || ENV['PRYEMHBCHECK'].empty? ? HEARTBEAT_CHECK_INTERVAL : ENV['PRYEMHBCHECK']
|
84
|
+
timers[id] ||= EM::PeriodicTimer.new(interval) do
|
85
|
+
if !hbeats[id] || (Time.new - hbeats[id]) > 20
|
86
|
+
unregister_server(id)
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
@@ -101,10 +100,26 @@ module PryRemoteEm
|
|
101
100
|
@connected
|
102
101
|
end
|
103
102
|
|
104
|
-
|
103
|
+
private
|
104
|
+
|
105
|
+
def start_server(host, port, opts)
|
106
|
+
EM.start_server(host, port, PryRemoteEm::Broker, opts)
|
107
|
+
log.info("[pry-remote-em broker] listening on #{opts[:tls] ? 'pryems' : 'pryem'}://#{host}:#{port}")
|
108
|
+
@listening = true
|
109
|
+
rescue => error
|
110
|
+
if error.message.include?('port is in use')
|
111
|
+
if opts[:raise_if_port_in_use]
|
112
|
+
raise
|
113
|
+
else
|
114
|
+
# A broker is already listening on this port, we can do nothing
|
115
|
+
end
|
116
|
+
else
|
117
|
+
raise
|
118
|
+
end
|
119
|
+
end
|
105
120
|
|
106
121
|
def client(&blk)
|
107
|
-
raise ArgumentError.new(
|
122
|
+
raise ArgumentError.new('A block is required') unless block_given?
|
108
123
|
if @client
|
109
124
|
yield @client
|
110
125
|
return
|
@@ -115,9 +130,9 @@ module PryRemoteEm
|
|
115
130
|
else
|
116
131
|
@waiting = [blk]
|
117
132
|
EM.connect(host, port, Client::Broker, @opts) do |client|
|
118
|
-
client.errback { |e| raise(e ||
|
133
|
+
client.errback { |e| raise(e || 'broker client error') }
|
119
134
|
client.callback do
|
120
|
-
@client
|
135
|
+
@client = client
|
121
136
|
while (w = @waiting.shift)
|
122
137
|
w.call(client)
|
123
138
|
end
|
@@ -129,25 +144,25 @@ module PryRemoteEm
|
|
129
144
|
|
130
145
|
include Proto
|
131
146
|
|
132
|
-
def
|
147
|
+
def receive_server_reload_list
|
133
148
|
send_server_list(Broker.servers)
|
134
149
|
end
|
135
150
|
|
136
|
-
def receive_register_server(
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
Broker.servers[
|
141
|
-
|
142
|
-
|
143
|
-
|
151
|
+
def receive_register_server(id, urls, name, details)
|
152
|
+
@ids.push(id)
|
153
|
+
description = { urls: urls, name: name, details: details }
|
154
|
+
Broker.hbeats[id] = Time.new
|
155
|
+
server = Broker.servers[id]
|
156
|
+
if server
|
157
|
+
Broker.update_server(server, description)
|
158
|
+
else
|
159
|
+
Broker.register_server(id, description)
|
160
|
+
end
|
144
161
|
end
|
145
162
|
|
146
|
-
def receive_unregister_server(
|
147
|
-
|
148
|
-
|
149
|
-
log.warn("[pry-remote-em broker] unregister #{url}")
|
150
|
-
Broker.servers.delete(url)
|
163
|
+
def receive_unregister_server(id)
|
164
|
+
server = Broker.servers[id]
|
165
|
+
Broker.unregister_server(id) if server
|
151
166
|
end
|
152
167
|
|
153
168
|
def receive_proxy_connection(url)
|
@@ -156,8 +171,9 @@ module PryRemoteEm
|
|
156
171
|
EM.connect(url.host, url.port, Client::Proxy, self)
|
157
172
|
end
|
158
173
|
|
159
|
-
def initialize(opts = {
|
160
|
-
@opts
|
174
|
+
def initialize(opts = {}, &blk)
|
175
|
+
@opts = opts
|
176
|
+
@ids = []
|
161
177
|
end
|
162
178
|
|
163
179
|
def log
|
@@ -179,15 +195,16 @@ module PryRemoteEm
|
|
179
195
|
|
180
196
|
def peer_ip
|
181
197
|
return @peer_ip if @peer_ip
|
182
|
-
return
|
198
|
+
return '' if get_peername.nil?
|
183
199
|
@peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
|
200
|
+
@peer_ip = '127.0.0.1' if @peer_ip == '::1' # Little hack to avoid segmentation fault in EventMachine 1.2.0.1 while connecting to PryRemoteEm Server from localhost with IPv6 address
|
184
201
|
@peer_ip
|
185
202
|
end
|
186
203
|
|
187
204
|
def peer_port
|
188
205
|
return @peer_port if @peer_port
|
189
|
-
return
|
190
|
-
|
206
|
+
return '' if get_peername.nil?
|
207
|
+
peer_ip # Fills peer_port too
|
191
208
|
@peer_port
|
192
209
|
end
|
193
210
|
|
@@ -196,5 +213,10 @@ module PryRemoteEm
|
|
196
213
|
send_server_list(Broker.servers)
|
197
214
|
end
|
198
215
|
|
216
|
+
def unbind
|
217
|
+
@ids.each do |id|
|
218
|
+
Broker.unregister_server(id)
|
219
|
+
end
|
220
|
+
end
|
199
221
|
end # module::Broker
|
200
222
|
end # module::PryRemoteEm
|
data/lib/pry-remote-em/client.rb
CHANGED
@@ -1,24 +1,21 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'pry-remote-em'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
warn "[pry-remote-em] unable to load keyboard depenencies (termios); interactive shell commands disabled"
|
7
|
-
end
|
8
|
-
require "pry-remote-em/client/generic"
|
3
|
+
require 'pry-remote-em/client/keyboard'
|
4
|
+
require 'pry-remote-em/client/generic'
|
5
|
+
require 'pry-remote-em/client/interactive_menu'
|
9
6
|
require 'pry'
|
10
|
-
require
|
11
|
-
require 'highline'
|
7
|
+
#require 'pry-coolline' rescue require 'readline'
|
12
8
|
|
13
9
|
module PryRemoteEm
|
14
10
|
module Client
|
15
11
|
include EM::Deferrable
|
16
|
-
include
|
12
|
+
include Generic
|
13
|
+
include InteractiveMenu
|
17
14
|
include Pry::Helpers::BaseHelpers
|
18
15
|
|
19
16
|
class << self
|
20
|
-
def start(host =
|
21
|
-
EM.connect(host || PryRemoteEm::
|
17
|
+
def start(host = nil, port = nil, opts = {})
|
18
|
+
EM.connect(host || PryRemoteEm::DEFAULT_SERVER_HOST, port || PryRemoteEm::DEFAULT_SERVER_PORT, PryRemoteEm::Client, opts) do |c|
|
22
19
|
c.callback { yield if block_given? }
|
23
20
|
c.errback do |e|
|
24
21
|
Kernel.puts "[pry-remote-em] connection failed\n#{e}"
|
@@ -42,11 +39,17 @@ module PryRemoteEm
|
|
42
39
|
end
|
43
40
|
|
44
41
|
def post_init
|
45
|
-
|
42
|
+
@input = if defined?(PryCoolline)
|
43
|
+
PryCoolline.make_coolline
|
44
|
+
else
|
45
|
+
Pry.history.load if Pry.config.history.should_load
|
46
|
+
Readline
|
47
|
+
end
|
48
|
+
@input.completion_proc = method(:auto_complete)
|
46
49
|
end
|
47
50
|
|
48
51
|
def ssl_handshake_completed
|
49
|
-
log.info(
|
52
|
+
log.info('[pry-remote-em] TLS connection established')
|
50
53
|
@opts[:tls] = true
|
51
54
|
end
|
52
55
|
|
@@ -60,9 +63,7 @@ module PryRemoteEm
|
|
60
63
|
reconnect(uri.host, uri.port)
|
61
64
|
else
|
62
65
|
@unbound = true
|
63
|
-
log.info(
|
64
|
-
# prior to 1.0.0.b4 error? returns true here even when it's not
|
65
|
-
return succeed if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
|
66
|
+
log.info('[pry-remote-em] session terminated')
|
66
67
|
error? ? fail : succeed
|
67
68
|
end
|
68
69
|
end
|
@@ -79,108 +80,19 @@ module PryRemoteEm
|
|
79
80
|
log.info("\033[33m[pry-remote-em] no servers are registered with the broker\033[0m")
|
80
81
|
Process.exit
|
81
82
|
end
|
82
|
-
|
83
|
-
return unless
|
84
|
-
uri
|
83
|
+
url, proxy = choose_server(list)
|
84
|
+
return unless url
|
85
|
+
uri = URI.parse(url)
|
85
86
|
if proxy
|
86
87
|
@opts[:tls] = uri.scheme == 'pryems'
|
87
88
|
@negotiated = false
|
88
89
|
@tls_started = false
|
89
|
-
return send_proxy_connection(
|
90
|
+
return send_proxy_connection(url)
|
90
91
|
end
|
91
92
|
@reconnect_to = uri
|
92
93
|
close_connection
|
93
94
|
end
|
94
95
|
|
95
|
-
def choose_server(list)
|
96
|
-
highline = HighLine.new
|
97
|
-
proxy = false
|
98
|
-
choice = nil
|
99
|
-
nm_col_len = list.values.map(&:length).sort[-1] + 5
|
100
|
-
ur_col_len = list.keys.map(&:length).sort[-1] + 5
|
101
|
-
header = sprintf("| %-3s | %-#{nm_col_len}s | %-#{ur_col_len}s |", "", "name", "url")
|
102
|
-
border = ("-" * header.length)
|
103
|
-
table = [border, header, border]
|
104
|
-
list = list.to_a.map{|url, name| [URI.parse(url), name]}
|
105
|
-
list = filter_server_list(list)
|
106
|
-
list = sort_server_list(list)
|
107
|
-
list.each_with_index do |(url, name), idx|
|
108
|
-
table << sprintf("| %-2d | %-#{nm_col_len}s | %-#{ur_col_len}s |", idx + 1, name, url)
|
109
|
-
end
|
110
|
-
table << border
|
111
|
-
table = table.join("\n")
|
112
|
-
Kernel.puts table
|
113
|
-
while choice.nil?
|
114
|
-
if proxy
|
115
|
-
question = "(q) to quit; (r) to refresh (c) to connect\nproxy to: "
|
116
|
-
else
|
117
|
-
question = "(q) to quit; (r) to refresh (p) to proxy\nconnect to: "
|
118
|
-
end
|
119
|
-
if (choice = opts.delete(:proxy))
|
120
|
-
proxy = true
|
121
|
-
else
|
122
|
-
choice = opts.delete(:connect) || highline.ask(question)
|
123
|
-
proxy = false
|
124
|
-
end
|
125
|
-
|
126
|
-
return close_connection if ['q', 'quit', 'exit'].include?(choice.downcase)
|
127
|
-
if ['r', 'reload', 'refresh'].include?(choice.downcase)
|
128
|
-
send_server_list
|
129
|
-
return nil
|
130
|
-
end
|
131
|
-
if ['c', 'connect'].include?(choice.downcase)
|
132
|
-
proxy = false
|
133
|
-
choice = nil
|
134
|
-
next
|
135
|
-
end
|
136
|
-
if ['p', 'proxy'].include?(choice.downcase)
|
137
|
-
proxy = true
|
138
|
-
choice = nil
|
139
|
-
next
|
140
|
-
end
|
141
|
-
choice = choice.to_i > 0 ?
|
142
|
-
list[choice.to_i - 1] :
|
143
|
-
list.find{|(url, name)| url.to_s == choice || name == choice }
|
144
|
-
log.error("\033[31mserver not found\033[0m") unless choice
|
145
|
-
end
|
146
|
-
[choice, proxy]
|
147
|
-
end
|
148
|
-
|
149
|
-
def sort_server_list(list)
|
150
|
-
type = opts[:sort] || :host
|
151
|
-
case type
|
152
|
-
when :name
|
153
|
-
list.sort { |a,b| a[1] <=> b[1] }
|
154
|
-
when :host
|
155
|
-
list.sort { |a,b| a[0].host <=> b[0].host }
|
156
|
-
when :ssl
|
157
|
-
list.sort { |a,b| b[0].scheme <=> a[0].scheme }
|
158
|
-
when :port
|
159
|
-
list.sort { |a,b| a[0].port <=> b[0].port }
|
160
|
-
else
|
161
|
-
list.sort { |a,b| a[0].host <=> b[0].host }
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def filter_server_list(list)
|
166
|
-
if opts[:filter_host]
|
167
|
-
list = list.select { |url, name| url.host =~ opts[:filter_host] }
|
168
|
-
end
|
169
|
-
if opts[:filter_name]
|
170
|
-
list = list.select { |url, name| name =~ opts[:filter_name] }
|
171
|
-
end
|
172
|
-
if opts.include?(:filter_ssl)
|
173
|
-
list = opts[:filter_ssl] ?
|
174
|
-
list.select{|url, name| url.scheme == 'pryems' } :
|
175
|
-
list.select{|url, name| url.scheme == 'pryem' }
|
176
|
-
end
|
177
|
-
if list.empty?
|
178
|
-
log.info("\033[33m[pry-remote-em] no registered servers match the given filter\033[0m")
|
179
|
-
Process.exit
|
180
|
-
end
|
181
|
-
list
|
182
|
-
end
|
183
|
-
|
184
96
|
def receive_auth(a)
|
185
97
|
return fail a if a.is_a?(String)
|
186
98
|
return authenticate if a == false
|
@@ -204,11 +116,22 @@ module PryRemoteEm
|
|
204
116
|
@keyboard.bufferio(true)
|
205
117
|
@keyboard.close_connection
|
206
118
|
end
|
119
|
+
if c == 255 || c == 127
|
120
|
+
Kernel.puts 'command not found'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# TODO detect if the old pager behavior of Pry is supported and use it
|
125
|
+
# through Pry.pager. If it's not then use the SimplePager.
|
126
|
+
def pager
|
127
|
+
pager_class = ENV['PRYEMNOPAGER'] ? Pry::Pager::NullPager : @opts[:pager] || Pry::Pager::SimplePager
|
128
|
+
@pager ||= pager_class.new(Pry::Output.new(Pry))
|
207
129
|
end
|
208
130
|
|
209
131
|
def receive_raw(r)
|
210
|
-
|
211
|
-
|
132
|
+
pager.write(r)
|
133
|
+
rescue Pry::Pager::StopPaging
|
134
|
+
warn '[pry-remote-em] stop paging is not implemented, use PRYEMNOPAGER environment variable to avoid paging at all'
|
212
135
|
end
|
213
136
|
|
214
137
|
def receive_unknown(j)
|
@@ -216,7 +139,7 @@ module PryRemoteEm
|
|
216
139
|
end
|
217
140
|
|
218
141
|
def authenticate
|
219
|
-
return fail(
|
142
|
+
return fail('[pry-remote-em] authentication required') unless @auth
|
220
143
|
return fail("[pry-remote-em] can't authenticate before negotiation complete") unless @negotiated
|
221
144
|
user, pass = @auth.call
|
222
145
|
return fail("[pry-remote-em] expected #{@auth} to return a user and password") unless user && pass
|
@@ -224,6 +147,8 @@ module PryRemoteEm
|
|
224
147
|
end # authenticate
|
225
148
|
|
226
149
|
def auto_complete(word)
|
150
|
+
word = word.completed_word if defined?(Coolline) && word.kind_of?(Coolline)
|
151
|
+
|
227
152
|
@waiting = Thread.current
|
228
153
|
EM.next_tick { send_completion(word) }
|
229
154
|
sleep
|
@@ -243,26 +168,37 @@ module PryRemoteEm
|
|
243
168
|
readline(p)
|
244
169
|
end
|
245
170
|
|
246
|
-
def readline(prompt)
|
171
|
+
def readline(prompt = @last_prompt)
|
172
|
+
@last_prompt = prompt
|
247
173
|
if @negotiated && !@unbound
|
248
|
-
|
249
|
-
|
250
|
-
|
174
|
+
operation = proc do
|
175
|
+
thread = Thread.current
|
176
|
+
old_trap = Signal.trap(:INT) { thread.raise Interrupt }
|
177
|
+
begin
|
178
|
+
@input.readline(prompt)
|
179
|
+
rescue Interrupt
|
180
|
+
send_clear_buffer
|
181
|
+
puts
|
182
|
+
:ignore_me
|
183
|
+
ensure
|
184
|
+
Signal.trap(:INT, old_trap)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
callback = proc do |l|
|
189
|
+
next if l == :ignore_me
|
190
|
+
|
191
|
+
add_to_history(l) unless l.nil? || l.empty?
|
192
|
+
|
193
|
+
if l.nil?
|
194
|
+
readline
|
195
|
+
elsif '^^' == l[0..1]
|
251
196
|
send_msg_bcast(l[2..-1])
|
252
|
-
elsif '
|
197
|
+
elsif '^' == l[0]
|
253
198
|
send_msg(l[1..-1])
|
254
199
|
elsif '.' == l[0]
|
255
|
-
|
256
|
-
|
257
|
-
readline(prompt)
|
258
|
-
else
|
259
|
-
send_shell_cmd(l[1..-1])
|
260
|
-
if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
|
261
|
-
Kernel.puts "\033[1minteractive shell commands are not well supported when running on EventMachine prior to 1.0.0.beta4\033[0m"
|
262
|
-
else
|
263
|
-
@keyboard = EM.open_keyboard(Keyboard, self)
|
264
|
-
end
|
265
|
-
end
|
200
|
+
send_shell_cmd(l[1..-1])
|
201
|
+
@keyboard = EM.open_keyboard(Keyboard, self)
|
266
202
|
elsif 'reset' == l.strip
|
267
203
|
# TODO work with 'bundle exec pry-remote-em ...'
|
268
204
|
# TODO work with 'ruby -I lib bin/pry-remote-em ...'
|
@@ -270,15 +206,24 @@ module PryRemoteEm
|
|
270
206
|
exec("#{$0} #{ARGV.join(' ')}")
|
271
207
|
else
|
272
208
|
send_raw(l)
|
273
|
-
end
|
209
|
+
end
|
274
210
|
end
|
275
|
-
|
211
|
+
|
212
|
+
EM.defer(operation, callback)
|
276
213
|
end
|
277
214
|
end # readline(prompt = @last_prompt)
|
278
215
|
|
216
|
+
def add_to_history(line)
|
217
|
+
if defined?(Readline) && @input == Readline
|
218
|
+
Readline::HISTORY.push(line)
|
219
|
+
end
|
220
|
+
# Nothing to do with Coolline, it just works
|
221
|
+
end
|
279
222
|
end # module::Client
|
280
223
|
end # module::PryRemoteEm
|
281
224
|
|
225
|
+
# TODO detect if the old pager behavior of Pry is supported and use it. If it's not
|
226
|
+
# then don't bother adding a pager accessor
|
282
227
|
# Pry::Helpers::BaseHelpers#stagger_output expects Pry.pager to be defined
|
283
228
|
class Pry
|
284
229
|
class << self
|