em-ssh 0.5.1 → 0.6.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/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