pry-remote-em 0.6.3 → 0.7.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.
- 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
|
|