net-ssh 6.1.0 → 7.3.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.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +94 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +4 -0
  10. data/.rubocop.yml +12 -1
  11. data/.rubocop_todo.yml +475 -376
  12. data/CHANGES.txt +64 -3
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +29 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +2 -0
  17. data/Gemfile.noed25519 +2 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/README.md +38 -22
  20. data/Rakefile +92 -0
  21. data/SECURITY.md +4 -0
  22. data/docker-compose.yml +25 -0
  23. data/lib/net/ssh/authentication/agent.rb +29 -13
  24. data/lib/net/ssh/authentication/certificate.rb +14 -11
  25. data/lib/net/ssh/authentication/constants.rb +0 -1
  26. data/lib/net/ssh/authentication/ed25519.rb +14 -11
  27. data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
  28. data/lib/net/ssh/authentication/key_manager.rb +65 -36
  29. data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
  30. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
  31. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -2
  32. data/lib/net/ssh/authentication/methods/none.rb +6 -9
  33. data/lib/net/ssh/authentication/methods/password.rb +2 -3
  34. data/lib/net/ssh/authentication/methods/publickey.rb +57 -17
  35. data/lib/net/ssh/authentication/pageant.rb +97 -97
  36. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +3 -3
  37. data/lib/net/ssh/authentication/session.rb +25 -17
  38. data/lib/net/ssh/buffer.rb +71 -51
  39. data/lib/net/ssh/buffered_io.rb +25 -26
  40. data/lib/net/ssh/config.rb +33 -20
  41. data/lib/net/ssh/connection/channel.rb +84 -82
  42. data/lib/net/ssh/connection/constants.rb +0 -4
  43. data/lib/net/ssh/connection/event_loop.rb +30 -24
  44. data/lib/net/ssh/connection/keepalive.rb +12 -12
  45. data/lib/net/ssh/connection/session.rb +109 -108
  46. data/lib/net/ssh/connection/term.rb +56 -58
  47. data/lib/net/ssh/errors.rb +12 -12
  48. data/lib/net/ssh/key_factory.rb +7 -8
  49. data/lib/net/ssh/known_hosts.rb +86 -18
  50. data/lib/net/ssh/loggable.rb +8 -9
  51. data/lib/net/ssh/packet.rb +1 -1
  52. data/lib/net/ssh/prompt.rb +9 -11
  53. data/lib/net/ssh/proxy/command.rb +1 -1
  54. data/lib/net/ssh/proxy/errors.rb +2 -4
  55. data/lib/net/ssh/proxy/http.rb +18 -20
  56. data/lib/net/ssh/proxy/https.rb +8 -10
  57. data/lib/net/ssh/proxy/jump.rb +8 -10
  58. data/lib/net/ssh/proxy/socks4.rb +2 -4
  59. data/lib/net/ssh/proxy/socks5.rb +3 -5
  60. data/lib/net/ssh/service/forward.rb +7 -7
  61. data/lib/net/ssh/test/channel.rb +24 -26
  62. data/lib/net/ssh/test/extensions.rb +35 -35
  63. data/lib/net/ssh/test/kex.rb +6 -8
  64. data/lib/net/ssh/test/local_packet.rb +0 -2
  65. data/lib/net/ssh/test/packet.rb +3 -3
  66. data/lib/net/ssh/test/remote_packet.rb +6 -8
  67. data/lib/net/ssh/test/script.rb +25 -27
  68. data/lib/net/ssh/test/socket.rb +12 -15
  69. data/lib/net/ssh/test.rb +4 -5
  70. data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  71. data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  72. data/lib/net/ssh/transport/algorithms.rb +51 -19
  73. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  74. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  75. data/lib/net/ssh/transport/cipher_factory.rb +56 -29
  76. data/lib/net/ssh/transport/constants.rb +3 -3
  77. data/lib/net/ssh/transport/ctr.rb +7 -7
  78. data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
  79. data/lib/net/ssh/transport/hmac/abstract.rb +20 -5
  80. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  81. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  82. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  83. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  84. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac.rb +12 -12
  87. data/lib/net/ssh/transport/identity_cipher.rb +19 -13
  88. data/lib/net/ssh/transport/kex/abstract.rb +12 -5
  89. data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
  90. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +2 -1
  91. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
  92. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  93. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +21 -21
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -2
  95. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
  96. data/lib/net/ssh/transport/kex.rb +8 -6
  97. data/lib/net/ssh/transport/key_expander.rb +7 -8
  98. data/lib/net/ssh/transport/openssl.rb +51 -26
  99. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  100. data/lib/net/ssh/transport/packet_stream.rb +46 -26
  101. data/lib/net/ssh/transport/server_version.rb +17 -16
  102. data/lib/net/ssh/transport/session.rb +9 -7
  103. data/lib/net/ssh/transport/state.rb +44 -44
  104. data/lib/net/ssh/verifiers/accept_new.rb +0 -2
  105. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  106. data/lib/net/ssh/verifiers/always.rb +6 -4
  107. data/lib/net/ssh/verifiers/never.rb +0 -2
  108. data/lib/net/ssh/version.rb +2 -2
  109. data/lib/net/ssh.rb +15 -8
  110. data/net-ssh-public_cert.pem +19 -18
  111. data/net-ssh.gemspec +7 -4
  112. data/support/ssh_tunnel_bug.rb +3 -3
  113. data.tar.gz.sig +0 -0
  114. metadata +76 -29
  115. metadata.gz.sig +0 -0
  116. data/.travis.yml +0 -52
@@ -5,7 +5,6 @@ require 'net/ssh/connection/term'
5
5
  module Net
6
6
  module SSH
7
7
  module Connection
8
-
9
8
  # The channel abstraction. Multiple "channels" can be multiplexed onto a
10
9
  # single SSH channel, each operating independently and seemingly in parallel.
11
10
  # This class represents a single such channel. Most operations performed
@@ -55,55 +54,55 @@ module Net
55
54
  class Channel
56
55
  include Loggable
57
56
  include Constants
58
-
57
+
59
58
  # The local id for this channel, assigned by the Net::SSH::Connection::Session instance.
60
59
  attr_reader :local_id
61
-
60
+
62
61
  # The remote id for this channel, assigned by the remote host.
63
62
  attr_reader :remote_id
64
-
63
+
65
64
  # The type of this channel, usually "session".
66
65
  attr_reader :type
67
-
66
+
68
67
  # The underlying Net::SSH::Connection::Session instance that supports this channel.
69
68
  attr_reader :connection
70
-
69
+
71
70
  # The maximum packet size that the local host can receive.
72
71
  attr_reader :local_maximum_packet_size
73
-
72
+
74
73
  # The maximum amount of data that the local end of this channel can
75
74
  # receive. This is a total, not per-packet.
76
75
  attr_reader :local_maximum_window_size
77
-
76
+
78
77
  # The maximum packet size that the remote host can receive.
79
78
  attr_reader :remote_maximum_packet_size
80
-
79
+
81
80
  # The maximum amount of data that the remote end of this channel can
82
81
  # receive. This is a total, not per-packet.
83
82
  attr_reader :remote_maximum_window_size
84
-
83
+
85
84
  # This is the remaining window size on the local end of this channel. When
86
85
  # this reaches zero, no more data can be received.
87
86
  attr_reader :local_window_size
88
-
87
+
89
88
  # This is the remaining window size on the remote end of this channel. When
90
89
  # this reaches zero, no more data can be sent.
91
90
  attr_reader :remote_window_size
92
-
91
+
93
92
  # A hash of properties for this channel. These can be used to store state
94
93
  # information about this channel. See also #[] and #[]=.
95
94
  attr_reader :properties
96
-
95
+
97
96
  # The output buffer for this channel. Data written to the channel is
98
97
  # enqueued here, to be written as CHANNEL_DATA packets during each pass of
99
98
  # the event loop. See Connection::Session#process and #enqueue_pending_output.
100
- attr_reader :output #:nodoc:
101
-
99
+ attr_reader :output # :nodoc:
100
+
102
101
  # The list of pending requests. Each time a request is sent which requires
103
102
  # a reply, the corresponding callback is pushed onto this queue. As responses
104
103
  # arrive, they are shifted off the front and handled.
105
- attr_reader :pending_requests #:nodoc:
106
-
104
+ attr_reader :pending_requests # :nodoc:
105
+
107
106
  # Instantiates a new channel on the given connection, of the given type,
108
107
  # and with the given id. If a block is given, it will be remembered until
109
108
  # the channel is confirmed open by the server, and will be invoked at
@@ -112,36 +111,36 @@ module Net
112
111
  # This also sets the default maximum packet size and maximum window size.
113
112
  def initialize(connection, type, local_id, max_pkt_size = 0x8000, max_win_size = 0x20000, &on_confirm_open)
114
113
  self.logger = connection.logger
115
-
114
+
116
115
  @connection = connection
117
116
  @type = type
118
117
  @local_id = local_id
119
-
118
+
120
119
  @local_maximum_packet_size = max_pkt_size
121
120
  @local_window_size = @local_maximum_window_size = max_win_size
122
-
121
+
123
122
  @on_confirm_open = on_confirm_open
124
-
123
+
125
124
  @output = Buffer.new
126
-
125
+
127
126
  @properties = {}
128
-
127
+
129
128
  @pending_requests = []
130
129
  @on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil
131
130
  @on_request = {}
132
131
  @closing = @eof = @sent_eof = @local_closed = @remote_closed = false
133
132
  end
134
-
133
+
135
134
  # A shortcut for accessing properties of the channel (see #properties).
136
135
  def [](name)
137
136
  @properties[name]
138
137
  end
139
-
138
+
140
139
  # A shortcut for setting properties of the channel (see #properties).
141
140
  def []=(name, value)
142
141
  @properties[name] = value
143
142
  end
144
-
143
+
145
144
  # Syntactic sugar for executing a command. Sends a channel request asking
146
145
  # that the given command be invoked. If the block is given, it will be
147
146
  # called when the server responds. The first parameter will be the
@@ -161,7 +160,7 @@ module Net
161
160
  def exec(command, &block)
162
161
  send_channel_request("exec", :string, command, &block)
163
162
  end
164
-
163
+
165
164
  # Syntactic sugar for requesting that a subsystem be started. Subsystems
166
165
  # are a way for other protocols (like SFTP) to be run, using SSH as
167
166
  # the transport. Generally, you'll never need to call this directly unless
@@ -178,7 +177,7 @@ module Net
178
177
  def subsystem(subsystem, &block)
179
178
  send_channel_request("subsystem", :string, subsystem, &block)
180
179
  end
181
-
180
+
182
181
  # Syntactic sugar for setting an environment variable in the remote
183
182
  # process' environment. Note that for security reasons, the server may
184
183
  # refuse to set certain environment variables, or all, at the server's
@@ -190,7 +189,7 @@ module Net
190
189
  def env(variable_name, variable_value, &block)
191
190
  send_channel_request("env", :string, variable_name, :string, variable_value, &block)
192
191
  end
193
-
192
+
194
193
  # A hash of the valid PTY options (see #request_pty).
195
194
  VALID_PTY_OPTIONS = { term: "xterm",
196
195
  chars_wide: 80,
@@ -198,7 +197,7 @@ module Net
198
197
  pixels_wide: 640,
199
198
  pixels_high: 480,
200
199
  modes: {} }
201
-
200
+
202
201
  # Requests that a pseudo-tty (or "pty") be made available for this channel.
203
202
  # This is useful when you want to invoke and interact with some kind of
204
203
  # screen-based program (e.g., vim, or some menuing system).
@@ -218,24 +217,24 @@ module Net
218
217
  # puts "could not obtain pty"
219
218
  # end
220
219
  # end
221
- def request_pty(opts={}, &block)
220
+ def request_pty(opts = {}, &block)
222
221
  extra = opts.keys - VALID_PTY_OPTIONS.keys
223
222
  raise ArgumentError, "invalid option(s) to request_pty: #{extra.inspect}" if extra.any?
224
-
223
+
225
224
  opts = VALID_PTY_OPTIONS.merge(opts)
226
-
225
+
227
226
  modes = opts[:modes].inject(Buffer.new) do |memo, (mode, data)|
228
227
  memo.write_byte(mode).write_long(data)
229
228
  end
230
229
  # mark the end of the mode opcode list with a 0 byte
231
230
  modes.write_byte(0)
232
-
231
+
233
232
  send_channel_request("pty-req", :string, opts[:term],
234
- :long, opts[:chars_wide], :long, opts[:chars_high],
235
- :long, opts[:pixels_wide], :long, opts[:pixels_high],
236
- :string, modes.to_s, &block)
233
+ :long, opts[:chars_wide], :long, opts[:chars_high],
234
+ :long, opts[:pixels_wide], :long, opts[:pixels_high],
235
+ :string, modes.to_s, &block)
237
236
  end
238
-
237
+
239
238
  # Sends data to the channel's remote endpoint. This usually has the
240
239
  # effect of sending the given string to the remote process' stdin stream.
241
240
  # Note that it does not immediately send the data across the channel,
@@ -251,9 +250,10 @@ module Net
251
250
  # channel.send_data("the password\n")
252
251
  def send_data(data)
253
252
  raise EOFError, "cannot send data if channel has declared eof" if eof?
253
+
254
254
  output.append(data.to_s)
255
255
  end
256
-
256
+
257
257
  # Returns true if the channel exists in the channel list of the session,
258
258
  # and false otherwise. This can be used to determine whether a channel has
259
259
  # been closed or not.
@@ -262,7 +262,7 @@ module Net
262
262
  def active?
263
263
  connection.channels.key?(local_id)
264
264
  end
265
-
265
+
266
266
  # Runs the SSH event loop until the channel is no longer active. This is
267
267
  # handy for blocking while you wait for some channel to finish.
268
268
  #
@@ -271,7 +271,7 @@ module Net
271
271
  def wait
272
272
  connection.loop { active? }
273
273
  end
274
-
274
+
275
275
  # True if close() has been called; NOTE: if the channel has data waiting to
276
276
  # be sent then the channel will close after all the data is sent. See
277
277
  # closed?() to determine if we have actually sent CHANNEL_CLOSE to server.
@@ -280,61 +280,63 @@ module Net
280
280
  def closing?
281
281
  @closing
282
282
  end
283
-
283
+
284
284
  # True if we have sent CHANNEL_CLOSE to the remote server.
285
285
  def local_closed?
286
286
  @local_closed
287
287
  end
288
-
288
+
289
289
  def remote_closed?
290
290
  @remote_closed
291
291
  end
292
-
292
+
293
293
  def remote_closed!
294
294
  @remote_closed = true
295
295
  end
296
-
296
+
297
297
  # Requests that the channel be closed. It only marks the channel to be closed
298
298
  # the CHANNEL_CLOSE message will be sent from event loop
299
299
  def close
300
300
  return if @closing
301
+
301
302
  @closing = true
302
303
  end
303
-
304
+
304
305
  # Returns true if the local end of the channel has declared that no more
305
306
  # data is forthcoming (see #eof!). Trying to send data via #send_data when
306
307
  # this is true will result in an exception being raised.
307
308
  def eof?
308
309
  @eof
309
310
  end
310
-
311
+
311
312
  # Tells the remote end of the channel that no more data is forthcoming
312
313
  # from this end of the channel. The remote end may still send data.
313
314
  # The CHANNEL_EOF packet will be sent once the output buffer is empty.
314
315
  def eof!
315
316
  return if eof?
317
+
316
318
  @eof = true
317
319
  end
318
-
320
+
319
321
  # If an #on_process handler has been set up, this will cause it to be
320
322
  # invoked (passing the channel itself as an argument). It also causes all
321
323
  # pending output to be enqueued as CHANNEL_DATA packets (see #enqueue_pending_output).
322
324
  def process
323
325
  @on_process.call(self) if @on_process
324
326
  enqueue_pending_output
325
-
327
+
326
328
  if @eof and not @sent_eof and output.empty? and remote_id and not @local_closed
327
329
  connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id))
328
330
  @sent_eof = true
329
331
  end
330
-
332
+
331
333
  if @closing and not @local_closed and output.empty? and remote_id
332
334
  connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
333
335
  @local_closed = true
334
336
  connection.cleanup_channel(self)
335
337
  end
336
338
  end
337
-
339
+
338
340
  # Registers a callback to be invoked when data packets are received by the
339
341
  # channel. The callback is called with the channel as the first argument,
340
342
  # and the data as the second.
@@ -349,7 +351,7 @@ module Net
349
351
  old, @on_data = @on_data, block
350
352
  old
351
353
  end
352
-
354
+
353
355
  # Registers a callback to be invoked when extended data packets are received
354
356
  # by the channel. The callback is called with the channel as the first
355
357
  # argument, the data type (as an integer) as the second, and the data as
@@ -364,7 +366,7 @@ module Net
364
366
  old, @on_extended_data = @on_extended_data, block
365
367
  old
366
368
  end
367
-
369
+
368
370
  # Registers a callback to be invoked for each pass of the event loop for
369
371
  # this channel. There are no guarantees on timeliness in the event loop,
370
372
  # but it will be called roughly once for each packet received by the
@@ -391,7 +393,7 @@ module Net
391
393
  old, @on_process = @on_process, block
392
394
  old
393
395
  end
394
-
396
+
395
397
  # Registers a callback to be invoked when the server acknowledges that a
396
398
  # channel is closed. This is invoked with the channel as the sole argument.
397
399
  #
@@ -402,7 +404,7 @@ module Net
402
404
  old, @on_close = @on_close, block
403
405
  old
404
406
  end
405
-
407
+
406
408
  # Registers a callback to be invoked when the server indicates that no more
407
409
  # data will be sent to the channel (although the channel can still send
408
410
  # data to the server). The channel is the sole argument to the callback.
@@ -414,7 +416,7 @@ module Net
414
416
  old, @on_eof = @on_eof, block
415
417
  old
416
418
  end
417
-
419
+
418
420
  # Registers a callback to be invoked when the server was unable to open
419
421
  # the requested channel. The channel itself will be passed to the block,
420
422
  # along with the integer "reason code" for the failure, and a textual
@@ -429,7 +431,7 @@ module Net
429
431
  old, @on_open_failed = @on_open_failed, block
430
432
  old
431
433
  end
432
-
434
+
433
435
  # Registers a callback to be invoked when a channel request of the given
434
436
  # type is received. The callback will receive the channel as the first
435
437
  # argument, and the associated (unparsed) data as the second. The data
@@ -460,7 +462,7 @@ module Net
460
462
  old, @on_request[type] = @on_request[type], block
461
463
  old
462
464
  end
463
-
465
+
464
466
  # Sends a new channel request with the given name. The extra +data+
465
467
  # parameter must either be empty, or consist of an even number of
466
468
  # arguments. See Net::SSH::Buffer.from for a description of their format.
@@ -486,28 +488,29 @@ module Net
486
488
  def send_channel_request(request_name, *data, &callback)
487
489
  info { "sending channel request #{request_name.inspect}" }
488
490
  fail "Channel open not yet confirmed, please call send_channel_request(or exec) from block of open_channel" unless remote_id
491
+
489
492
  msg = Buffer.from(:byte, CHANNEL_REQUEST,
490
- :long, remote_id, :string, request_name,
491
- :bool, !callback.nil?, *data)
493
+ :long, remote_id, :string, request_name,
494
+ :bool, !callback.nil?, *data)
492
495
  connection.send_message(msg)
493
496
  pending_requests << callback if callback
494
497
  end
495
-
498
+
496
499
  public # these methods are public, but for Net::SSH internal use only
497
-
500
+
498
501
  # Enqueues pending output at the connection as CHANNEL_DATA packets. This
499
502
  # does nothing if the channel has not yet been confirmed open (see
500
503
  # #do_open_confirmation). This is called automatically by #process, which
501
504
  # is called from the event loop (Connection::Session#process). You will
502
505
  # generally not need to invoke it directly.
503
- def enqueue_pending_output #:nodoc:
506
+ def enqueue_pending_output # :nodoc:
504
507
  return unless remote_id
505
-
508
+
506
509
  while output.length > 0
507
510
  length = output.length
508
511
  length = remote_window_size if length > remote_window_size
509
512
  length = remote_maximum_packet_size if length > remote_maximum_packet_size
510
-
513
+
511
514
  if length > 0
512
515
  connection.send_message(Buffer.from(:byte, CHANNEL_DATA, :long, remote_id, :string, output.read(length)))
513
516
  output.consume!
@@ -517,14 +520,14 @@ module Net
517
520
  end
518
521
  end
519
522
  end
520
-
523
+
521
524
  # Invoked when the server confirms that a channel has been opened.
522
525
  # The remote_id is the id of the channel as assigned by the remote host,
523
526
  # and max_window and max_packet are the maximum window and maximum
524
527
  # packet sizes, respectively. If an open-confirmation callback was
525
528
  # given when the channel was created, it is invoked at this time with
526
529
  # the channel itself as the sole argument.
527
- def do_open_confirmation(remote_id, max_window, max_packet) #:nodoc:
530
+ def do_open_confirmation(remote_id, max_window, max_packet) # :nodoc:
528
531
  @remote_id = remote_id
529
532
  @remote_window_size = @remote_maximum_window_size = max_window
530
533
  @remote_maximum_packet_size = max_packet
@@ -533,7 +536,7 @@ module Net
533
536
  set_remote_env(connection.options[:set_env]) if connection.options[:set_env]
534
537
  @on_confirm_open.call(self) if @on_confirm_open
535
538
  end
536
-
539
+
537
540
  # Invoked when the server failed to open the channel. If an #on_open_failed
538
541
  # callback was specified, it will be invoked with the channel, reason code,
539
542
  # and description as arguments. Otherwise, a ChannelOpenFailed exception
@@ -545,16 +548,16 @@ module Net
545
548
  raise ChannelOpenFailed.new(reason_code, description)
546
549
  end
547
550
  end
548
-
551
+
549
552
  # Invoked when the server sends a CHANNEL_WINDOW_ADJUST packet, and
550
553
  # causes the remote window size to be adjusted upwards by the given
551
554
  # number of bytes. This has the effect of allowing more data to be sent
552
555
  # from the local end to the remote end of the channel.
553
- def do_window_adjust(bytes) #:nodoc:
556
+ def do_window_adjust(bytes) # :nodoc:
554
557
  @remote_maximum_window_size += bytes
555
558
  @remote_window_size += bytes
556
559
  end
557
-
560
+
558
561
  # Invoked when the server sends a channel request. If any #on_request
559
562
  # callback has been registered for the specific type of this request,
560
563
  # it is invoked. If +want_reply+ is true, a packet will be sent of
@@ -563,32 +566,32 @@ module Net
563
566
  # CHANNEL_SUCCESS, unless the callback raised ChannelRequestFailed. The
564
567
  # callback should accept the channel as the first argument, and the
565
568
  # request-specific data as the second.
566
- def do_request(request, want_reply, data) #:nodoc:
569
+ def do_request(request, want_reply, data) # :nodoc:
567
570
  result = true
568
-
571
+
569
572
  begin
570
573
  callback = @on_request[request] or raise ChannelRequestFailed
571
574
  callback.call(self, data)
572
575
  rescue ChannelRequestFailed
573
576
  result = false
574
577
  end
575
-
578
+
576
579
  if want_reply
577
580
  msg = Buffer.from(:byte, result ? CHANNEL_SUCCESS : CHANNEL_FAILURE, :long, remote_id)
578
581
  connection.send_message(msg)
579
582
  end
580
583
  end
581
-
584
+
582
585
  # Invokes the #on_data callback when the server sends data to the
583
586
  # channel. This will reduce the available window size on the local end,
584
587
  # but does not actually throttle requests that come in illegally when
585
588
  # the window size is too small. The callback is invoked with the channel
586
589
  # as the first argument, and the data as the second.
587
- def do_data(data) #:nodoc:
590
+ def do_data(data) # :nodoc:
588
591
  update_local_window_size(data.length)
589
592
  @on_data.call(self, data) if @on_data
590
593
  end
591
-
594
+
592
595
  # Invokes the #on_extended_data callback when the server sends
593
596
  # extended data to the channel. This will reduce the available window
594
597
  # size on the local end. The callback is invoked with the channel,
@@ -597,20 +600,20 @@ module Net
597
600
  update_local_window_size(data.length)
598
601
  @on_extended_data.call(self, type, data) if @on_extended_data
599
602
  end
600
-
603
+
601
604
  # Invokes the #on_eof callback when the server indicates that no
602
605
  # further data is forthcoming. The callback is invoked with the channel
603
606
  # as the argument.
604
607
  def do_eof
605
608
  @on_eof.call(self) if @on_eof
606
609
  end
607
-
610
+
608
611
  # Invokes the #on_close callback when the server closes a channel.
609
612
  # The channel is the only argument.
610
613
  def do_close
611
614
  @on_close.call(self) if @on_close
612
615
  end
613
-
616
+
614
617
  # Invokes the next pending request callback with +false+ as the second
615
618
  # argument.
616
619
  def do_failure
@@ -620,7 +623,7 @@ module Net
620
623
  error { "channel failure received with no pending request to handle it (bug?)" }
621
624
  end
622
625
  end
623
-
626
+
624
627
  # Invokes the next pending request callback with +true+ as the second
625
628
  # argument.
626
629
  def do_success
@@ -686,7 +689,6 @@ module Net
686
689
  env.each { |key, value| self.env(key, value) }
687
690
  end
688
691
  end
689
-
690
692
  end
691
693
  end
692
694
  end
@@ -1,11 +1,9 @@
1
1
  module Net
2
2
  module SSH
3
3
  module Connection
4
-
5
4
  # Definitions of constants that are specific to the connection layer of the
6
5
  # SSH protocol.
7
6
  module Constants
8
-
9
7
  #--
10
8
  # Connection protocol generic messages
11
9
  #++
@@ -29,9 +27,7 @@ module Net
29
27
  CHANNEL_REQUEST = 98
30
28
  CHANNEL_SUCCESS = 99
31
29
  CHANNEL_FAILURE = 100
32
-
33
30
  end
34
-
35
31
  end
36
32
  end
37
33
  end
@@ -1,7 +1,7 @@
1
1
  require 'net/ssh/loggable'
2
2
 
3
- module Net
4
- module SSH
3
+ module Net
4
+ module SSH
5
5
  module Connection
6
6
  # EventLoop can be shared across multiple sessions
7
7
  #
@@ -11,81 +11,84 @@ module Net
11
11
  # and we don't pass session.
12
12
  class EventLoop
13
13
  include Loggable
14
-
15
- def initialize(logger=nil)
14
+
15
+ def initialize(logger = nil)
16
16
  self.logger = logger
17
17
  @sessions = []
18
18
  end
19
-
19
+
20
20
  def register(session)
21
21
  @sessions << session
22
22
  end
23
-
23
+
24
24
  # process until timeout
25
25
  # if a block is given a session will be removed from loop
26
26
  # if block returns false for that session
27
27
  def process(wait = nil, &block)
28
28
  return false unless ev_preprocess(&block)
29
-
29
+
30
30
  ev_select_and_postprocess(wait)
31
31
  end
32
-
32
+
33
33
  # process the event loop but only for the sepcified session
34
34
  def process_only(session, wait = nil)
35
35
  orig_sessions = @sessions
36
36
  begin
37
37
  @sessions = [session]
38
38
  return false unless ev_preprocess
39
+
39
40
  ev_select_and_postprocess(wait)
40
41
  ensure
41
42
  @sessions = orig_sessions
42
43
  end
43
44
  end
44
-
45
+
45
46
  # Call preprocess on each session. If block given and that
46
47
  # block retuns false then we exit the processing
47
48
  def ev_preprocess(&block)
48
49
  return false if block_given? && !yield(self)
50
+
49
51
  @sessions.each(&:ev_preprocess)
50
52
  return false if block_given? && !yield(self)
53
+
51
54
  return true
52
55
  end
53
-
56
+
54
57
  def ev_select_and_postprocess(wait)
55
58
  owners = {}
56
59
  r = []
57
60
  w = []
58
61
  minwait = nil
59
62
  @sessions.each do |session|
60
- sr,sw,actwait = session.ev_do_calculate_rw_wait(wait)
63
+ sr, sw, actwait = session.ev_do_calculate_rw_wait(wait)
61
64
  minwait = actwait if actwait && (minwait.nil? || actwait < minwait)
62
65
  r.push(*sr)
63
66
  w.push(*sw)
64
67
  sr.each { |ri| owners[ri] = session }
65
68
  sw.each { |wi| owners[wi] = session }
66
69
  end
67
-
70
+
68
71
  readers, writers, = IO.select(r, w, nil, minwait)
69
-
72
+
70
73
  fired_sessions = {}
71
-
74
+
72
75
  if readers
73
76
  readers.each do |reader|
74
77
  session = owners[reader]
75
- (fired_sessions[session] ||= { r: [],w: [] })[:r] << reader
78
+ (fired_sessions[session] ||= { r: [], w: [] })[:r] << reader
76
79
  end
77
80
  end
78
81
  if writers
79
82
  writers.each do |writer|
80
83
  session = owners[writer]
81
- (fired_sessions[session] ||= { r: [],w: [] })[:w] << writer
84
+ (fired_sessions[session] ||= { r: [], w: [] })[:w] << writer
82
85
  end
83
86
  end
84
-
85
- fired_sessions.each do |s,rw|
86
- s.ev_do_handle_events(rw[:r],rw[:w])
87
+
88
+ fired_sessions.each do |s, rw|
89
+ s.ev_do_handle_events(rw[:r], rw[:w])
87
90
  end
88
-
91
+
89
92
  @sessions.each { |s| s.ev_do_postprocess(fired_sessions.key?(s)) }
90
93
  true
91
94
  end
@@ -97,18 +100,21 @@ module Net
97
100
  # we call block with session as argument
98
101
  def ev_preprocess(&block)
99
102
  return false if block_given? && !yield(@sessions.first)
103
+
100
104
  @sessions.each(&:ev_preprocess)
101
105
  return false if block_given? && !yield(@sessions.first)
106
+
102
107
  return true
103
108
  end
104
-
109
+
105
110
  def ev_select_and_postprocess(wait)
106
111
  raise "Only one session expected" unless @sessions.count == 1
112
+
107
113
  session = @sessions.first
108
- sr,sw,actwait = session.ev_do_calculate_rw_wait(wait)
114
+ sr, sw, actwait = session.ev_do_calculate_rw_wait(wait)
109
115
  readers, writers, = IO.select(sr, sw, nil, actwait)
110
-
111
- session.ev_do_handle_events(readers,writers)
116
+
117
+ session.ev_do_handle_events(readers, writers)
112
118
  session.ev_do_postprocess(!((readers.nil? || readers.empty?) && (writers.nil? || writers.empty?)))
113
119
  end
114
120
  end