em-ssh 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ 0.6.0
2
+ - Disconnect error codes are converted to Ruby exceptions and raised
3
+ - ChannelOpen error codes are converted to Ruby exceptions and raised
4
+ - Shell#split will detect ChannelOpen errors and raise an Exception
5
+
1
6
  0.5.1
2
7
  - [#21](https://github.com/simulacre/em-ssh/pull/22) - Fix em-ssh throws exception when no logger is defined [@mandre](https://github.com/mandre)
3
8
  - [#20](https://github.com/simulacre/em-ssh/pull/20) - Fix Interactive timeout wasn't set if parameter not fed [@freakhill](https://github.com/freakhill)
data/bin/em-ssh-shell CHANGED
@@ -62,20 +62,29 @@ EM.run do
62
62
 
63
63
  shell.callback do
64
64
  commands.clone.each do |command|
65
+
65
66
  mys = shell.split
67
+ mys.errback do |err|
68
+ $stderr.puts "subshell error: #{err} (#{err.class})"
69
+ mys.close
70
+ end
71
+
66
72
  mys.on(:closed) do
67
73
  commands.delete(command)
68
74
  EM.stop if commands.empty?
69
75
  end
70
76
 
71
77
  puts("waiting for: #{waitstr.inspect}")
72
- mys.expect(waitstr) do
73
- puts "sending #{command.inspect} and waiting for #{waitstr.inspect}"
74
- mys.expect(waitstr, command) do |result|
75
- puts "#{mys} result: '#{result}'"
76
- mys.close
78
+ mys.callback do
79
+ mys.expect(waitstr) do
80
+ puts "sending #{command.inspect} and waiting for #{waitstr.inspect}"
81
+ mys.expect(waitstr, command) do |result|
82
+ puts "#{mys} result: '#{result}'"
83
+ mys.close
84
+ end
77
85
  end
78
- end
86
+ end
87
+
79
88
  end
80
89
  end
81
90
  end
@@ -129,7 +129,7 @@ module EventMachine
129
129
 
130
130
  timeout_proc = proc do
131
131
  data_callback && data_callback.cancel
132
- f.resume(TimeoutError.new("#{connection.host}: inactivity timeout (#{opts[:timeout]}) while waiting for #{strregex.inspect}; received: #{buffer.inspect}; waited total: #{Time.new - started}"))
132
+ f.resume(TimeoutError.new("#{@host}: inactivity timeout (#{opts[:timeout]}) while waiting for #{strregex.inspect}; received: #{buffer.inspect}; waited total: #{Time.new - started}"))
133
133
  end
134
134
 
135
135
  data_callback = on(:data) do
@@ -128,7 +128,10 @@ module EventMachine
128
128
  instance_variable_set(iv, nil)
129
129
  end
130
130
 
131
- fail(NegotiationTimeout.new(@host)) if failed_timeout
131
+ if failed_timeout
132
+ fail(@disconnect ? EM::Ssh::Disconnect.from_packet(@disconnect) : NegotiationTimeout.new(@host))
133
+
134
+ end
132
135
  end
133
136
 
134
137
  def receive_data(data)
@@ -289,6 +292,7 @@ module EventMachine
289
292
  while (packet = @socket.poll_next_packet)
290
293
  case packet.type
291
294
  when DISCONNECT
295
+ @disconnect = packet
292
296
  close_connection
293
297
  when IGNORE
294
298
  debug("IGNORE packet received: #{packet[:data].inspect}")
data/lib/em-ssh/shell.rb CHANGED
@@ -87,8 +87,12 @@ module EventMachine
87
87
  # TODO make all methods other than #callback and #errback inaccessible until connected? == true
88
88
  yield self if block_given?
89
89
  Fiber.new {
90
- open rescue fail($!)
91
- succeed(self) if connected? && !closed?
90
+ begin
91
+ open
92
+ succeed(self) if connected? && !closed?
93
+ rescue => e
94
+ fail(e)
95
+ end
92
96
  }.resume
93
97
  end
94
98
 
@@ -155,6 +159,7 @@ module EventMachine
155
159
  Fiber.new { yield(self) if block_given? }.resume
156
160
  f.resume(self)
157
161
  end
162
+ @on_open_err = proc { |e| f.resume(e) }
158
163
  open!
159
164
  return Fiber.yield.tap { |r| raise r if r.is_a?(Exception) }
160
165
  end
@@ -166,7 +171,7 @@ module EventMachine
166
171
  @opening = true
167
172
  begin
168
173
  connect
169
- session.open_channel do |channel|
174
+ chan = session.open_channel do |channel|
170
175
  debug "**** channel open: #{channel}"
171
176
  channel.request_pty(options[:pty] || {}) do |pty,suc|
172
177
  debug "***** pty open: #{pty}; suc: #{suc}"
@@ -186,6 +191,9 @@ module EventMachine
186
191
  end # |shell,success|
187
192
  end # |pty,suc|
188
193
  end # |channel|
194
+ chan.on_open_failed do |chan, code, desc|
195
+ @on_open_err && @on_open_err[ChannelOpenFailed.from_code(code, desc)]
196
+ end
189
197
  rescue => e
190
198
  @opening = false
191
199
  raise ConnectionError.new("failed to create shell for #{host}: #{e} (#{e.class})")
@@ -236,7 +244,7 @@ module EventMachine
236
244
  fire(:split, child)
237
245
  if block_given?
238
246
  # requires that the caller be in a Fiber
239
- child.open rescue child.fail($!)
247
+ child.open
240
248
  yield(child).tap { child.close }
241
249
  else
242
250
  child
@@ -1,5 +1,5 @@
1
1
  module EventMachine
2
2
  class Ssh
3
- VERSION='0.5.1'
3
+ VERSION='0.6.0'
4
4
  end # class::Ssh
5
5
  end # module::EventMachine
data/lib/em-ssh.rb CHANGED
@@ -28,6 +28,67 @@ module EventMachine
28
28
  class ConnectionTerminated < SshError; end
29
29
  # The server failed to negotiate an ssh protocol version
30
30
  class NegotiationTimeout < ConnectionFailed; end
31
+ class Disconnect < SshError
32
+ class HostNotAllowedToConnect < Disconnect; end
33
+ class ProtocolError < Disconnect; end
34
+ class KeyExchangeFailed < Disconnect; end
35
+ class Reserved < Disconnect; end
36
+ class MacError < Disconnect; end
37
+ class CompressionError < Disconnect; end
38
+ class ServiceNotAvailable < Disconnect; end
39
+ class ProtocolVersionNotSupported < Disconnect; end
40
+ class HostKeyNotVerifiable < Disconnect; end
41
+ class ConnectionLost < Disconnect; end
42
+ class ByApplication < Disconnect; end
43
+ class TooManyConnections < Disconnect; end
44
+ class AuthCancelledByUser < Disconnect; end
45
+ class NoMoreAuthMethodsAvailable < Disconnect; end
46
+ class IllegalUserName < Disconnect; end
47
+
48
+ CODES = [
49
+ Disconnect,
50
+ HostNotAllowedToConnect,
51
+ ProtocolError,
52
+ KeyExchangeFailed,
53
+ Reserved,
54
+ MacError,
55
+ CompressionError,
56
+ ServiceNotAvailable,
57
+ ProtocolVersionNotSupported,
58
+ HostKeyNotVerifiable,
59
+ ConnectionLost,
60
+ ByApplication,
61
+ TooManyConnections,
62
+ AuthCancelledByUser,
63
+ NoMoreAuthMethodsAvailable,
64
+ IllegalUserName,
65
+ ]
66
+ class << self
67
+ def from_packet(packet)
68
+ (CODES[packet[:reason_code]] || Disconnect).new(packet[:description])
69
+ end
70
+ end
71
+ end # class::Disconnect < SshError
72
+
73
+ class ChannelOpenFailed < Net::SSH::ChannelOpenFailed
74
+ include Error
75
+ class AdministrativelyProhibited < ChannelOpenFailed; end
76
+ class ConnectFailed < ChannelOpenFailed; end
77
+ class UnknownChannelType < ChannelOpenFailed; end
78
+ class ResourceShortage < ChannelOpenFailed; end
79
+ CODES = [
80
+ ChannelOpenFailed,
81
+ AdministrativelyProhibited,
82
+ ConnectFailed,
83
+ UnknownChannelType,
84
+ ResourceShortage
85
+ ]
86
+ class << self
87
+ def from_code(code, desc)
88
+ (CODES[code] || ChannelOpenFailed).new(code, desc)
89
+ end
90
+ end
91
+ end
31
92
 
32
93
 
33
94
  class << self
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-25 00:00:00.000000000 Z
12
+ date: 2013-06-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine