Class: HrrRbSsh::Connection::Channel

Inherits:
Object
  • Object
show all
Defined in:
lib/hrr_rb_ssh/connection/channel.rb,
lib/hrr_rb_ssh/connection/channel/channel_type.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/direct_tcpip.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/forwarded_tcpip.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain/chain_context.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env/context.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec/context.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell/context.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req/context.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem/context.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change/context.rb

Defined Under Namespace

Classes: ChannelType

Constant Summary collapse

INITIAL_WINDOW_SIZE =
100000
MAXIMUM_PACKET_SIZE =
100000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection, message, socket = nil) ⇒ Channel

Returns a new instance of Channel.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 27

def initialize connection, message, socket=nil
  @logger = Logger.new self.class.name

  @connection = connection

  @channel_type = message[:'channel type']
  @local_channel  = connection.assign_channel
  @remote_channel = message[:'sender channel']
  @local_window_size          = INITIAL_WINDOW_SIZE
  @local_maximum_packet_size  = MAXIMUM_PACKET_SIZE
  @remote_window_size         = message[:'initial window size']
  @remote_maximum_packet_size = message[:'maximum packet size']

  @channel_type_instance = ChannelType[@channel_type].new connection, self, message, socket

  @receive_message_queue = Queue.new
  @receive_data_queue = Queue.new
  @receive_extended_data_queue = Queue.new

  @r_io_in,  @w_io_in  = IO.pipe
  @r_io_out, @w_io_out = IO.pipe
  @r_io_err, @w_io_err = IO.pipe

  @channel_closing_monitor = Monitor.new

  @closed = nil
  @exit_status = nil
end

Instance Attribute Details

#channel_typeObject (readonly)

Returns the value of attribute channel_type.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def channel_type
  @channel_type
end

#exit_statusObject (readonly)

Returns the value of attribute exit_status.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def exit_status
  @exit_status
end

#local_channelObject (readonly)

Returns the value of attribute local_channel.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def local_channel
  @local_channel
end

#local_maximum_packet_sizeObject (readonly)

Returns the value of attribute local_maximum_packet_size.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def local_maximum_packet_size
  @local_maximum_packet_size
end

#local_window_sizeObject (readonly)

Returns the value of attribute local_window_size.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def local_window_size
  @local_window_size
end

#receive_message_queueObject (readonly)

Returns the value of attribute receive_message_queue.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def receive_message_queue
  @receive_message_queue
end

#remote_channelObject (readonly)

Returns the value of attribute remote_channel.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def remote_channel
  @remote_channel
end

#remote_maximum_packet_sizeObject (readonly)

Returns the value of attribute remote_maximum_packet_size.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def remote_maximum_packet_size
  @remote_maximum_packet_size
end

#remote_window_sizeObject (readonly)

Returns the value of attribute remote_window_size.



16
17
18
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 16

def remote_window_size
  @remote_window_size
end

Instance Method Details

#channel_loop_threadObject



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 162

def channel_loop_thread
  Thread.start do
    @logger.info { "start channel loop thread" }
    begin
      loop do
        begin
          message = @receive_message_queue.deq
          if message.nil? && @receive_message_queue.closed?
            break
          end
          case message[:'message number']
          when Message::SSH_MSG_CHANNEL_EOF::VALUE
            @receive_data_queue.close
            @receive_extended_data_queue.close
          when Message::SSH_MSG_CHANNEL_REQUEST::VALUE
            @logger.info { "received channel request: #{message[:'request type']}" }
            case @connection.mode
            when Mode::SERVER
              begin
                @channel_type_instance.request message
              rescue => e
                @logger.warn { "request failed: #{e.message}" }
                send_channel_failure if message[:'want reply']
              else
                send_channel_success if message[:'want reply']
              end
            when Mode::CLIENT
              case message[:'request type']
              when "exit-status"
                @logger.info { "exit status: #{message[:'exit status']}" }
                @exit_status = message[:'exit status'].to_i
              end
            end
          when Message::SSH_MSG_CHANNEL_DATA::VALUE
            @logger.info { "received channel data" }
            local_channel = message[:'recipient channel']
            @receive_data_queue.enq message[:'data']
          when Message::SSH_MSG_CHANNEL_EXTENDED_DATA::VALUE
            @logger.info { "received channel extended data" }
            local_channel = message[:'recipient channel']
            @receive_extended_data_queue.enq message[:'data']
          when Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE
            @logger.debug { "received channel window adjust" }
            @remote_window_size = [@remote_window_size + message[:'bytes to add'], 0xffff_ffff].min
          else
            @logger.warn { "received unsupported message: #{message.inspect}" }
          end
        rescue => e
          @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
          close from=:channel_loop_thread
          break
        end
      end
    ensure
      @logger.info { "closing channel loop thread" }
      @receive_data_queue.close
      @receive_extended_data_queue.close
    end
    @logger.info { "channel loop thread closed" }
  end
end

#close(from = :outside, exitstatus = 0) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 109

def close from=:outside, exitstatus=0
  @channel_closing_monitor.synchronize {
    return if @closed
    @logger.info { "close channel" }
    @closed = true
  }
  unless from == :channel_type_instance
    @channel_type_instance.close
  end
  @receive_message_queue.close
  begin
    if from == :channel_type_instance
      send_channel_eof
      case exitstatus
      when Integer
        send_channel_request_exit_status exitstatus
      else
        @logger.warn { "skip sending exit-status because exitstatus is not an instance of Integer" }
      end
    elsif from == :sender_thread
      send_channel_eof
    end
    send_channel_close
  rescue Error::ClosedConnection => e
    Thread.pass
  rescue => e
    @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
  end
  @logger.info { "channel closed" }
end

#closed?Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 158

def closed?
  @closed
end

#err_receiver_threadObject



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 342

def err_receiver_thread
  Thread.start {
    @logger.info { "start err receiver thread" }
    loop do
      begin
        data = @receive_extended_data_queue.deq
        if data.nil? && @receive_extended_data_queue.closed?
          @logger.info { "closing err receiver thread" }
          @logger.info { "closing w_io_err" }
          @w_io_err.close
          @logger.info { "w_io_err closed" }
          break
        end
        @w_io_err.write data
        @local_window_size -= data.size
        if @local_window_size < INITIAL_WINDOW_SIZE/2
          @logger.info { "send channel window adjust" }
          send_channel_window_adjust
          @local_window_size += INITIAL_WINDOW_SIZE
        end
      rescue Error::EPIPE, IOError => e
        close
        break
      rescue => e
        @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
        close
        break
      end
    end
    @logger.info { "err receiver thread closed" }
  }
end

#err_sender_threadObject



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 250

def err_sender_thread
  Thread.start {
    @logger.info { "start err sender thread" }
    loop do
      if @r_io_err.closed?
        @logger.info { "closing err sender thread" }
        break
      end
      begin
        data = @r_io_err.readpartial(10240)
        sendable_size = [data.size, @remote_window_size].min
        sending_data = data[0, sendable_size]
        send_channel_extended_data sending_data if sendable_size > 0
        @remote_window_size -= sendable_size
      rescue EOFError, IOError => e
        @r_io_err.close rescue nil
      rescue => e
        @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
        @r_io_err.close rescue nil
        close
      end
    end
    @logger.info { "err sender thread closed" }
  }
end

#ioObject



62
63
64
65
66
67
68
69
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 62

def io
  case @connection.mode
  when Mode::SERVER
    [@r_io_in, @w_io_out, @w_io_err]
  when Mode::CLIENT
    [@w_io_in, @r_io_out, @r_io_err]
  end
end

#out_receiver_threadObject



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 309

def out_receiver_thread
  Thread.start {
    @logger.info { "start out receiver thread" }
    loop do
      begin
        data = @receive_data_queue.deq
        if data.nil? && @receive_data_queue.closed?
          @logger.info { "closing out receiver thread" }
          @logger.info { "closing w_io_out" }
          @w_io_out.close
          @logger.info { "w_io_out closed" }
          break
        end
        @w_io_out.write data
        @local_window_size -= data.size
        if @local_window_size < INITIAL_WINDOW_SIZE/2
          @logger.info { "send channel window adjust" }
          send_channel_window_adjust
          @local_window_size += INITIAL_WINDOW_SIZE
        end
      rescue Errno::EPIPE, IOError => e
        close
        break
      rescue => e
        @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
        close
        break
      end
    end
    @logger.info { "out receiver thread closed" }
  }
end

#out_sender_threadObject



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 224

def out_sender_thread
  Thread.start {
    @logger.info { "start out sender thread" }
    loop do
      if @r_io_out.closed?
        @logger.info { "closing out sender thread" }
        break
      end
      begin
        data = @r_io_out.readpartial(10240)
        sendable_size = [data.size, @remote_window_size].min
        sending_data = data[0, sendable_size]
        send_channel_data sending_data if sendable_size > 0
        @remote_window_size -= sendable_size
      rescue EOFError, IOError => e
        @r_io_out.close rescue nil
      rescue => e
        @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
        @r_io_out.close rescue nil
        close
      end
    end
    @logger.info { "out sender thread closed" }
  }
end

#receiver_threadObject



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 276

def receiver_thread
  Thread.start {
    @logger.info { "start receiver thread" }
    loop do
      begin
        data = @receive_data_queue.deq
        if data.nil? && @receive_data_queue.closed?
          @logger.info { "closing receiver thread" }
          @logger.info { "closing w_io_in" }
          @w_io_in.close
          @logger.info { "w_io_in closed" }
          break
        end
        @w_io_in.write data
        @local_window_size -= data.size
        if @local_window_size < INITIAL_WINDOW_SIZE/2
          @logger.info { "send channel window adjust" }
          send_channel_window_adjust
          @local_window_size += INITIAL_WINDOW_SIZE
        end
      rescue Errno::EPIPE, IOError => e
        close
        break
      rescue => e
        @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
        close
        break
      end
    end
    @logger.info { "receiver thread closed" }
  }
end

#send_channel_closeObject



563
564
565
566
567
568
569
570
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 563

def send_channel_close
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_CLOSE::VALUE,
    :'recipient channel' => @remote_channel,
  }
  payload = Message::SSH_MSG_CHANNEL_CLOSE.encode message
  @connection.send payload
end

#send_channel_data(data) ⇒ Object



429
430
431
432
433
434
435
436
437
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 429

def send_channel_data data
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_DATA::VALUE,
    :'recipient channel' => @remote_channel,
    :'data'              => data,
  }
  payload = Message::SSH_MSG_CHANNEL_DATA.encode message
  @connection.send payload
end

#send_channel_eofObject



554
555
556
557
558
559
560
561
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 554

def send_channel_eof
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_EOF::VALUE,
    :'recipient channel' => @remote_channel,
  }
  payload = Message::SSH_MSG_CHANNEL_EOF.encode message
  @connection.send payload
end

#send_channel_extended_data(data, code = Message::SSH_MSG_CHANNEL_EXTENDED_DATA::DataTypeCode::SSH_EXTENDED_DATA_STDERR) ⇒ Object



439
440
441
442
443
444
445
446
447
448
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 439

def send_channel_extended_data data, code=Message::SSH_MSG_CHANNEL_EXTENDED_DATA::DataTypeCode::SSH_EXTENDED_DATA_STDERR
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_EXTENDED_DATA::VALUE,
    :'recipient channel' => @remote_channel,
    :'data type code'    => code,
    :'data'              => data,
  }
  payload = Message::SSH_MSG_CHANNEL_EXTENDED_DATA.encode message
  @connection.send payload
end

#send_channel_failureObject



410
411
412
413
414
415
416
417
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 410

def send_channel_failure
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_FAILURE::VALUE,
    :'recipient channel' => @remote_channel,
  }
  payload = Message::SSH_MSG_CHANNEL_FAILURE.encode message
  @connection.send payload
end

#send_channel_request_env(variable_name, variable_value) ⇒ Object



467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 467

def send_channel_request_env variable_name, variable_value
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel' => @remote_channel,
    :'request type'      => "env",
    :'want reply'        => false,
    :'variable name'     => variable_name,
    :'variable value'    => variable_value,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_request_exec(command) ⇒ Object



491
492
493
494
495
496
497
498
499
500
501
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 491

def send_channel_request_exec command
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel' => @remote_channel,
    :'request type'      => "exec",
    :'want reply'        => false,
    :'command'           => command,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_request_exit_status(exitstatus) ⇒ Object



542
543
544
545
546
547
548
549
550
551
552
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 542

def send_channel_request_exit_status exitstatus
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel' => @remote_channel,
    :'request type'      => "exit-status",
    :'want reply'        => false,
    :'exit status'       => exitstatus,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_request_pty_req(term_env_var_val, term_width_chars, term_height_rows, term_width_pixel, term_height_pixel, encoded_term_modes) ⇒ Object



450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 450

def send_channel_request_pty_req term_env_var_val, term_width_chars, term_height_rows, term_width_pixel, term_height_pixel, encoded_term_modes
  message = {
    :'message number'                  => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel'               => @remote_channel,
    :'request type'                    => "pty-req",
    :'want reply'                      => false,
    :'TERM environment variable value' => term_env_var_val,
    :'terminal width, characters'      => term_width_chars,
    :'terminal height, rows'           => term_height_rows,
    :'terminal width, pixels'          => term_width_pixel,
    :'terminal height, pixels'         => term_height_pixel,
    :'encoded terminal modes'          => encoded_term_modes,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_request_shellObject



480
481
482
483
484
485
486
487
488
489
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 480

def send_channel_request_shell
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel' => @remote_channel,
    :'request type'      => "shell",
    :'want reply'        => false,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_request_signal(signal_name) ⇒ Object



530
531
532
533
534
535
536
537
538
539
540
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 530

def send_channel_request_signal signal_name
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel' => @remote_channel,
    :'request type'      => "signal",
    :'want reply'        => false,
    :'signal name'       => signal_name,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_request_subsystem(subsystem_name) ⇒ Object



503
504
505
506
507
508
509
510
511
512
513
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 503

def send_channel_request_subsystem subsystem_name
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel' => @remote_channel,
    :'request type'      => "subsystem",
    :'want reply'        => false,
    :'subsystem name'    => subsystem_name,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_request_window_change(term_width_cols, term_height_rows, term_width_pixel, term_height_pixel) ⇒ Object



515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 515

def send_channel_request_window_change term_width_cols, term_height_rows, term_width_pixel, term_height_pixel
  message = {
    :'message number'          => Message::SSH_MSG_CHANNEL_REQUEST::VALUE,
    :'recipient channel'       => @remote_channel,
    :'request type'            => "window-change",
    :'want reply'              => false,
    :'terminal width, columns' => term_width_cols,
    :'terminal height, rows'   => term_height_rows,
    :'terminal width, pixels'  => term_width_pixel,
    :'terminal height, pixels' => term_height_pixel,
  }
  payload = Message::SSH_MSG_CHANNEL_REQUEST.encode message
  @connection.send payload
end

#send_channel_successObject



401
402
403
404
405
406
407
408
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 401

def send_channel_success
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_SUCCESS::VALUE,
    :'recipient channel' => @remote_channel,
  }
  payload = Message::SSH_MSG_CHANNEL_SUCCESS.encode message
  @connection.send payload
end

#send_channel_window_adjustObject



419
420
421
422
423
424
425
426
427
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 419

def send_channel_window_adjust
  message = {
    :'message number'    => Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE,
    :'recipient channel' => @remote_channel,
    :'bytes to add'      => INITIAL_WINDOW_SIZE,
  }
  payload = Message::SSH_MSG_CHANNEL_WINDOW_ADJUST.encode message
  @connection.send payload
end

#sender_threadObject



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 375

def sender_thread
  Thread.start {
    @logger.info { "start sender thread" }
    loop do
      if @r_io_in.closed?
        @logger.info { "closing sender thread" }
        break
      end
      begin
        data = @r_io_in.readpartial(10240)
        sendable_size = [data.size, @remote_window_size].min
        sending_data = data[0, sendable_size]
        send_channel_data sending_data if sendable_size > 0
        @remote_window_size -= sendable_size
      rescue EOFError, IOError => e
        @r_io_in.close rescue nil
      rescue => e
        @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
        @r_io_in.close rescue nil
      end
    end
    close from=:sender_thread
    @logger.info { "sender thread closed" }
  }
end

#set_remote_parameters(message) ⇒ Object



56
57
58
59
60
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 56

def set_remote_parameters message
  @remote_channel = message[:'sender channel']
  @remote_window_size = message[:'initial window size']
  @remote_maximum_packet_size = message[:'maximum packet size']
end

#startObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 71

def start
  @channel_loop_thread = channel_loop_thread
  case @connection.mode
  when Mode::SERVER
    @out_sender_thread   = out_sender_thread
    @err_sender_thread   = err_sender_thread
    @receiver_thread     = receiver_thread
    @channel_type_instance.start
  when Mode::CLIENT
    @out_receiver_thread = out_receiver_thread
    @err_receiver_thread = err_receiver_thread
    @sender_thread       = sender_thread
    @channel_type_instance.start
  end
  @closed = false
  @logger.debug { "in start: #{@waiting_thread}" }
  @waiting_thread.wakeup if @waiting_thread
end

#wait_until_closedObject



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 140

def wait_until_closed
  [
    @out_sender_thread,
    @err_sender_thread,
    @receiver_thread,
    @out_receiver_thread,
    @err_receiver_thread,
    @sender_thread,
    @channel_loop_thread
  ].each{ |t|
    begin
      t.join if t.instance_of? Thread
    rescue => e
      @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
    end
  }
end

#wait_until_senders_closedObject



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 96

def wait_until_senders_closed
  [
    @out_sender_thread,
    @err_sender_thread,
  ].each{ |t|
    begin
      t.join if t.instance_of? Thread
    rescue => e
      @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
    end
  }
end

#wait_until_startedObject



90
91
92
93
94
# File 'lib/hrr_rb_ssh/connection/channel.rb', line 90

def wait_until_started
  @waiting_thread = Thread.current
  @logger.debug { "in wait_until_started: #{@waiting_thread}" }
  Thread.stop
end