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 +86 -5
- data/bin/pry-remote-em +2 -2
- data/lib/pry-remote-em.rb +8 -6
- data/lib/pry-remote-em/broker.rb +189 -0
- data/lib/pry-remote-em/client.rb +154 -86
- data/lib/pry-remote-em/client/broker.rb +36 -0
- data/lib/pry-remote-em/client/generic.rb +73 -0
- data/lib/pry-remote-em/client/proxy.rb +32 -0
- data/lib/pry-remote-em/proto.rb +167 -0
- data/lib/pry-remote-em/server.rb +152 -74
- data/lib/pry-remote-em/server/shell_cmd.rb +2 -2
- data/lib/pry-remote-em/version.rb +1 -1
- metadata +8 -20
- data/lib/pry-remote-em/json-proto.rb +0 -31
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
|
-
|
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
|
|
data/bin/pry-remote-em
CHANGED
@@ -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::
|
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::
|
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
|
data/lib/pry-remote-em.rb
CHANGED
@@ -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/
|
7
|
+
require 'pry-remote-em/proto'
|
8
8
|
require 'eventmachine'
|
9
9
|
require 'socket'
|
10
|
-
require '
|
11
|
-
require
|
10
|
+
require 'fiber'
|
11
|
+
require 'uri'
|
12
12
|
|
13
13
|
module PryRemoteEm
|
14
|
-
DEFHOST
|
15
|
-
DEFPORT
|
16
|
-
|
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
|
data/lib/pry-remote-em/client.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'pry-remote-em'
|
3
|
-
|
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
|
-
|
6
|
-
|
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
|
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
|
55
|
-
|
56
|
-
|
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
|
61
|
-
if
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
71
|
-
|
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
|
-
|
74
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
109
|
-
|
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
|
-
|
177
|
+
send_auth([user, pass])
|
119
178
|
end # authenticate
|
120
179
|
|
121
|
-
def
|
122
|
-
|
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
|
126
|
-
|
127
|
-
|
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
|
131
|
-
|
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
|
-
|
141
|
-
|
202
|
+
op = proc { Readline.readline(prompt, !prompt.nil?) }
|
203
|
+
callback = proc do |l|
|
142
204
|
if '!!' == l[0..1]
|
143
|
-
|
205
|
+
send_msg_bcast(l[2..-1])
|
144
206
|
elsif '!' == l[0]
|
145
|
-
|
207
|
+
send_msg(l[1..-1])
|
146
208
|
elsif '.' == l[0]
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
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
|
-
|
226
|
+
send_raw(l)
|
160
227
|
end # "!!" == l[0..1]
|
161
|
-
|
228
|
+
end
|
229
|
+
EM.defer(op, callback)
|
162
230
|
end
|
163
231
|
end # readline(prompt = @last_prompt)
|
164
232
|
|