em-ssh 0.4.1 → 0.4.2
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/lib/em-ssh.rb +2 -0
- data/lib/em-ssh/callbacks.rb +1 -0
- data/lib/em-ssh/connection.rb +40 -3
- data/lib/em-ssh/packet-stream.rb +6 -0
- data/lib/em-ssh/session.rb +45 -2
- data/lib/em-ssh/shell.rb +16 -3
- data/lib/em-ssh/version.rb +1 -1
- metadata +2 -2
    
        data/lib/em-ssh.rb
    CHANGED
    
    | @@ -26,6 +26,8 @@ module EventMachine | |
| 26 26 | 
             
                class ConnectionFailed < SshError; end
         | 
| 27 27 | 
             
                class ConnectionTimeout < ConnectionFailed; end
         | 
| 28 28 | 
             
                class ConnectionTerminated < SshError; end
         | 
| 29 | 
            +
                # The server failed to negotiate an ssh protocol version
         | 
| 30 | 
            +
                class NegotiationTimeout < ConnectionFailed; end
         | 
| 29 31 |  | 
| 30 32 |  | 
| 31 33 | 
             
                class << self
         | 
    
        data/lib/em-ssh/callbacks.rb
    CHANGED
    
    | @@ -90,6 +90,7 @@ module EventMachine | |
| 90 90 | 
             
                    def cancel
         | 
| 91 91 | 
             
                      raise "#{@obj} does not have any callbacks for #{@event.inspect}" unless @obj.respond_to?(:callbacks) && @obj.callbacks.respond_to?(:[]) && @obj.callbacks[@event].respond_to?(:delete)
         | 
| 92 92 | 
             
                      @obj.callbacks[@event].delete(self)
         | 
| 93 | 
            +
                      @obj = nil
         | 
| 93 94 | 
             
                      self
         | 
| 94 95 | 
             
                    end # cancel
         | 
| 95 96 | 
             
                  end # class::Callback
         | 
    
        data/lib/em-ssh/connection.rb
    CHANGED
    
    | @@ -100,11 +100,35 @@ module EventMachine | |
| 100 100 | 
             
                    @data         = @socket.input
         | 
| 101 101 | 
             
                  end # post_init
         | 
| 102 102 |  | 
| 103 | 
            -
                  # @return
         | 
| 104 103 | 
             
                  def unbind
         | 
| 105 104 | 
             
                    debug("#{self} is unbound")
         | 
| 106 105 | 
             
                    fire(:closed)
         | 
| 107 106 | 
             
                    @closed = true
         | 
| 107 | 
            +
                    @socket && @socket.close
         | 
| 108 | 
            +
                    @socket = nil
         | 
| 109 | 
            +
                    @data   = nil
         | 
| 110 | 
            +
                    @error_callback = nil
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                    failed_timeout = [@contimeout, @negotimeout, @algotimeout].find { |t| t }
         | 
| 113 | 
            +
                    instance_variables.each do |iv|
         | 
| 114 | 
            +
                      if (t = instance_variable_get(iv)) && (t.is_a?(EM::Timer) || t.is_a?(EM::PeriodicTimer))
         | 
| 115 | 
            +
                        t.cancel
         | 
| 116 | 
            +
                        instance_variable_set(iv, nil)
         | 
| 117 | 
            +
                      end
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                    if @algorithms
         | 
| 121 | 
            +
                      @algorithms.instance_variable_set(:@session, nil)
         | 
| 122 | 
            +
                      @algorithms = nil
         | 
| 123 | 
            +
                    end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                    callbacks.values.flatten.each(&:cancel)
         | 
| 126 | 
            +
                    callbacks.clear
         | 
| 127 | 
            +
                    instance_variables.select{|iv| (t = instance_variable_get(iv)) && t.is_a?(EM::Ssh::Callbacks::Callback) }.each do |iv|
         | 
| 128 | 
            +
                      instance_variable_set(iv, nil)
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    fail(NegotiationTimeout.new(@host)) if failed_timeout
         | 
| 108 132 | 
             
                  end
         | 
| 109 133 |  | 
| 110 134 | 
             
                  def receive_data(data)
         | 
| @@ -116,7 +140,7 @@ module EventMachine | |
| 116 140 | 
             
                  def connection_completed
         | 
| 117 141 | 
             
                    @contimeout.cancel
         | 
| 118 142 | 
             
                    @nocon.cancel
         | 
| 119 | 
            -
                  end | 
| 143 | 
            +
                  end
         | 
| 120 144 |  | 
| 121 145 | 
             
                  def initialize(options = {})
         | 
| 122 146 | 
             
                    debug("#{self.class}.new(#{options})")
         | 
| @@ -129,7 +153,7 @@ module EventMachine | |
| 129 153 |  | 
| 130 154 | 
             
                    begin
         | 
| 131 155 | 
             
                      on(:connected) do |session|
         | 
| 132 | 
            -
                        @connected | 
| 156 | 
            +
                        @connected    = true
         | 
| 133 157 | 
             
                        succeed(session, @host)
         | 
| 134 158 | 
             
                      end
         | 
| 135 159 | 
             
                      on(:error) do |e|
         | 
| @@ -141,11 +165,20 @@ module EventMachine | |
| 141 165 | 
             
                        fail(ConnectionFailed.new(@host))
         | 
| 142 166 | 
             
                        close_connection
         | 
| 143 167 | 
             
                      end
         | 
| 168 | 
            +
             | 
| 144 169 | 
             
                      @contimeout     = EM::Timer.new(@timeout) do
         | 
| 145 170 | 
             
                        fail(ConnectionTimeout.new(@host))
         | 
| 146 171 | 
             
                        close_connection
         | 
| 147 172 | 
             
                      end
         | 
| 148 173 |  | 
| 174 | 
            +
                      @negotimeout = EM::Timer.new(options[:nego_timeout] || @timeout) do
         | 
| 175 | 
            +
                        fail(NegotiationTimeout.new(@host))
         | 
| 176 | 
            +
                      end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                      @algotimeout = EM::Timer.new(options[:nego_timeout] || @timeout) do
         | 
| 179 | 
            +
                        fail(NegotiationTimeout.new(@host))
         | 
| 180 | 
            +
                      end
         | 
| 181 | 
            +
             | 
| 149 182 | 
             
                      @nonego         = on(:closed) do
         | 
| 150 183 | 
             
                        fail(ConnectionTerminated.new(@host))
         | 
| 151 184 | 
             
                        close_connection
         | 
| @@ -160,12 +193,16 @@ module EventMachine | |
| 160 193 | 
             
                      @host_key_verifier = select_host_key_verifier(options[:paranoid])
         | 
| 161 194 | 
             
                      @server_version    = ServerVersion.new(self)
         | 
| 162 195 | 
             
                      on(:version_negotiated) do
         | 
| 196 | 
            +
                        @negotimeout.cancel
         | 
| 197 | 
            +
                        @negotimeout = nil
         | 
| 163 198 | 
             
                        @data.consume!(@server_version.header.length)
         | 
| 164 199 | 
             
                        @algorithms = Net::SSH::Transport::Algorithms.new(self, options)
         | 
| 165 200 |  | 
| 166 201 | 
             
                        register_data_handler
         | 
| 167 202 |  | 
| 168 203 | 
             
                        on_next(:algo_init) do
         | 
| 204 | 
            +
                          @algotimeout.cancel
         | 
| 205 | 
            +
                          @algotimeout = nil
         | 
| 169 206 | 
             
                          auth = AuthenticationSession.new(self, options)
         | 
| 170 207 | 
             
                          user = options.fetch(:user, user)
         | 
| 171 208 | 
             
                          Fiber.new do
         | 
    
        data/lib/em-ssh/packet-stream.rb
    CHANGED
    
    | @@ -34,6 +34,12 @@ module EventMachine | |
| 34 34 | 
             
                    @packet     = nil
         | 
| 35 35 | 
             
                  end # initialize(content="")
         | 
| 36 36 |  | 
| 37 | 
            +
                  def close
         | 
| 38 | 
            +
                    # remove reference to the connection to facilitate Garbage Collection
         | 
| 39 | 
            +
                    return super.tap { @connection = nil } if respond_to?(:super)
         | 
| 40 | 
            +
                    @connection = nil
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 37 43 | 
             
                  # Consumes n bytes from the buffer, where n is the current position
         | 
| 38 44 | 
             
                  # unless otherwise specified. This is useful for removing data from the
         | 
| 39 45 | 
             
                  # buffer that has previously been read, when you are expecting more data
         | 
    
        data/lib/em-ssh/session.rb
    CHANGED
    
    | @@ -3,7 +3,7 @@ module EventMachine | |
| 3 3 | 
             
                class Session < Net::SSH::Connection::Session
         | 
| 4 4 | 
             
                  include Log
         | 
| 5 5 |  | 
| 6 | 
            -
                  def initialize(transport, options | 
| 6 | 
            +
                  def initialize(transport, options={})
         | 
| 7 7 | 
             
                    super(transport, options)
         | 
| 8 8 | 
             
                    register_callbacks
         | 
| 9 9 | 
             
                  end
         | 
| @@ -28,6 +28,32 @@ module EventMachine | |
| 28 28 | 
             
                    transport.send_message(msg)
         | 
| 29 29 | 
             
                  end
         | 
| 30 30 |  | 
| 31 | 
            +
                  # Override Net::SSH::Connection::Session#close to remove dangling references to
         | 
| 32 | 
            +
                  # EM::Ssh::Connections and EM::Ssh::Sessions. Also directly close local channels
         | 
| 33 | 
            +
                  # if the connection is already closed.
         | 
| 34 | 
            +
                  def close
         | 
| 35 | 
            +
                    if @chan_timer
         | 
| 36 | 
            +
                      @chan_timer.cancel
         | 
| 37 | 
            +
                      remove_instance_variable(:@chan_timer)
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    # Net::SSH::Connection::Session#close doesn't check if the transport is
         | 
| 41 | 
            +
                    # closed. If it is then calling Channel#close will will not close the
         | 
| 42 | 
            +
                    # channel localy and the connection will just spin.
         | 
| 43 | 
            +
                    if transport.closed?
         | 
| 44 | 
            +
                      channels.each do |id, c|
         | 
| 45 | 
            +
                        c.instance_variable_set(:@connection, nil)
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                      channels.clear
         | 
| 48 | 
            +
                    else
         | 
| 49 | 
            +
                      channels.each { |id, channel| channel.close }
         | 
| 50 | 
            +
                      loop { channels.any? && !transport.closed?  }
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                    # remove the reference to the connection to facilitate Garbage Collection
         | 
| 53 | 
            +
                    transport, @transport = @transport, nil
         | 
| 54 | 
            +
                    @listeners.clear
         | 
| 55 | 
            +
                    transport.close
         | 
| 56 | 
            +
                  end
         | 
| 31 57 |  | 
| 32 58 | 
             
                private
         | 
| 33 59 |  | 
| @@ -41,12 +67,29 @@ module EventMachine | |
| 41 67 | 
             
                      send(MAP[packet.type], packet)
         | 
| 42 68 | 
             
                    end #  |packet|
         | 
| 43 69 |  | 
| 44 | 
            -
                    chan_timer = EM.add_periodic_timer(0.01) do
         | 
| 70 | 
            +
                    @chan_timer = EM.add_periodic_timer(0.01) do
         | 
| 45 71 | 
             
                      # we need to check the channel for any data to send and tell it to process any input
         | 
| 46 72 | 
             
                      # at some point we should override Channel#enqueue_pending_output, etc.,.
         | 
| 47 73 | 
             
                      channels.each { |id, channel| channel.process unless channel.closing? }
         | 
| 48 74 | 
             
                    end
         | 
| 49 75 | 
             
                  end # register_callbacks
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def channel_close(packet)
         | 
| 78 | 
            +
                    channel = channels[packet[:local_id]]
         | 
| 79 | 
            +
                    super(packet).tap do
         | 
| 80 | 
            +
                      # remove the connection reference to facilitate Garbage Collection
         | 
| 81 | 
            +
                      channel.instance_variable_set(:@connection, nil)
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def channel_open_failure(packet)
         | 
| 86 | 
            +
                    channel = channels[packet[:local_id]]
         | 
| 87 | 
            +
                    super(packet).tap do
         | 
| 88 | 
            +
                      # remove the connection reference to facilitate Garbage Collection
         | 
| 89 | 
            +
                      channel.instance_variable_set(:@connection, nil)
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 50 93 | 
             
                end # class::Session
         | 
| 51 94 | 
             
              end # class::Ssh
         | 
| 52 95 | 
             
            end # module::EventMachine
         | 
    
        data/lib/em-ssh/shell.rb
    CHANGED
    
    | @@ -93,11 +93,23 @@ module EventMachine | |
| 93 93 |  | 
| 94 94 | 
             
                  # Close the connection to the server and all child shells.
         | 
| 95 95 | 
             
                  # Disconnected shells cannot be split.
         | 
| 96 | 
            -
                  def disconnect
         | 
| 96 | 
            +
                  def disconnect(timeout = nil)
         | 
| 97 | 
            +
                    if timeout
         | 
| 98 | 
            +
                      EM::Timer.new(timeout) { disconnect! }
         | 
| 99 | 
            +
                    end
         | 
| 97 100 | 
             
                    close
         | 
| 98 | 
            -
                    session && session.close
         | 
| 101 | 
            +
                    @session && @session.close
         | 
| 102 | 
            +
                    disconnect!
         | 
| 99 103 | 
             
                  end
         | 
| 100 104 |  | 
| 105 | 
            +
                  def disconnect!
         | 
| 106 | 
            +
                    @session = nil
         | 
| 107 | 
            +
                    if @connection
         | 
| 108 | 
            +
                      @connection.close_connection
         | 
| 109 | 
            +
                      @connection = nil
         | 
| 110 | 
            +
                    end
         | 
| 111 | 
            +
                  end # disconnect!
         | 
| 112 | 
            +
             | 
| 101 113 | 
             
                  # @return [Boolean] true if the session is still alive
         | 
| 102 114 | 
             
                  def connected?
         | 
| 103 115 | 
             
                    session && !session.closed?
         | 
| @@ -108,7 +120,7 @@ module EventMachine | |
| 108 120 | 
             
                  # Fires :closed event.
         | 
| 109 121 | 
             
                  # @see Callbacks
         | 
| 110 122 | 
             
                  def close
         | 
| 111 | 
            -
                    shell.close.tap{ debug("closing") } if shell.active?
         | 
| 123 | 
            +
                    shell.close.tap{ debug("closing") } if shell && shell.active?
         | 
| 112 124 | 
             
                    @closed = true
         | 
| 113 125 | 
             
                    children.each { |c| c.close }
         | 
| 114 126 | 
             
                    fire(:closed)
         | 
| @@ -305,6 +317,7 @@ module EventMachine | |
| 305 317 | 
             
                  # @see #send_and_wait
         | 
| 306 318 | 
             
                  # @param [String] d the data to send encoded as a string
         | 
| 307 319 | 
             
                  def send_data(d, send_newline=true)
         | 
| 320 | 
            +
                    return unless shell
         | 
| 308 321 | 
             
                    if send_newline
         | 
| 309 322 | 
             
                      shell.send_data("#{d}#{line_terminator}")
         | 
| 310 323 | 
             
                    else
         | 
    
        data/lib/em-ssh/version.rb
    CHANGED
    
    
    
        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.4. | 
| 4 | 
            +
              version: 0.4.2
         | 
| 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: 2012- | 
| 12 | 
            +
            date: 2012-09-04 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: eventmachine
         |