Class: HrrRbSsh::Connection
- Inherits:
-
Object
- Object
- HrrRbSsh::Connection
show all
- Includes:
- Loggable
- Defined in:
- lib/hrr_rb_ssh/connection.rb,
lib/hrr_rb_ssh/connection/channel.rb,
lib/hrr_rb_ssh/connection/request_handler.rb,
lib/hrr_rb_ssh/connection/channel/channel_type.rb,
lib/hrr_rb_ssh/connection/global_request_handler.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/request_handler/reference_env_request_handler.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec.rb,
lib/hrr_rb_ssh/connection/request_handler/reference_exec_request_handler.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell.rb,
lib/hrr_rb_ssh/connection/request_handler/reference_shell_request_handler.rb,
lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req.rb,
lib/hrr_rb_ssh/connection/request_handler/reference_pty_req_request_handler.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/request_handler/reference_window_change_request_handler.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: Channel, GlobalRequestHandler, RequestHandler
Instance Attribute Summary collapse
Attributes included from Loggable
#log_key, #logger
Instance Method Summary
collapse
Methods included from Loggable
#log_debug, #log_error, #log_fatal, #log_info, #log_warn
Constructor Details
#initialize(authentication, mode, options = {}, logger: nil) ⇒ Connection
Returns a new instance of Connection.
19
20
21
22
23
24
25
26
27
28
29
|
# File 'lib/hrr_rb_ssh/connection.rb', line 19
def initialize authentication, mode, options={}, logger: nil
self.logger = logger
@authentication = authentication
@mode = mode
@options = options
@global_request_handler = GlobalRequestHandler.new self, logger: logger
@channels = Hash.new
@username = nil
@variables = nil
@closed = nil
end
|
Instance Attribute Details
#mode ⇒ Object
Returns the value of attribute mode.
13
14
15
|
# File 'lib/hrr_rb_ssh/connection.rb', line 13
def mode
@mode
end
|
#options ⇒ Object
Returns the value of attribute options.
13
14
15
|
# File 'lib/hrr_rb_ssh/connection.rb', line 13
def options
@options
end
|
#username ⇒ Object
Returns the value of attribute username.
13
14
15
|
# File 'lib/hrr_rb_ssh/connection.rb', line 13
def username
@username
end
|
#variables ⇒ Object
Returns the value of attribute variables.
13
14
15
|
# File 'lib/hrr_rb_ssh/connection.rb', line 13
def variables
@variables
end
|
Instance Method Details
#assign_channel ⇒ Object
40
41
42
43
44
45
46
47
48
|
# File 'lib/hrr_rb_ssh/connection.rb', line 40
def assign_channel
i = 0
res = nil
while true
break unless @channels.keys.include?(i)
i += 1
end
i
end
|
#channel_close(payload) ⇒ Object
258
259
260
261
262
263
264
265
266
267
268
269
270
|
# File 'lib/hrr_rb_ssh/connection.rb', line 258
def channel_close payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_CLOSE::ID }
message = Message::SSH_MSG_CHANNEL_CLOSE.new(logger: logger).decode payload
local_channel = message[:'recipient channel']
channel = @channels[local_channel]
channel.close
log_info { "wait until threads closed in channel" }
channel.wait_until_closed
log_info { "channel closed" }
log_info { "deleting channel" }
@channels.delete local_channel
log_info { "channel deleted" }
end
|
#channel_data(payload) ⇒ Object
237
238
239
240
241
242
|
# File 'lib/hrr_rb_ssh/connection.rb', line 237
def channel_data payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_DATA::ID }
message = Message::SSH_MSG_CHANNEL_DATA.new(logger: logger).decode payload
local_channel = message[:'recipient channel']
@channels[local_channel].receive_message_queue.enq message if @channels.has_key? local_channel
end
|
#channel_eof(payload) ⇒ Object
251
252
253
254
255
256
|
# File 'lib/hrr_rb_ssh/connection.rb', line 251
def channel_eof payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_EOF::ID }
message = Message::SSH_MSG_CHANNEL_EOF.new(logger: logger).decode payload
local_channel = message[:'recipient channel']
@channels[local_channel].receive_message_queue.enq message if @channels.has_key? local_channel
end
|
#channel_extended_data(payload) ⇒ Object
244
245
246
247
248
249
|
# File 'lib/hrr_rb_ssh/connection.rb', line 244
def channel_extended_data payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_EXTENDED_DATA::ID }
message = Message::SSH_MSG_CHANNEL_EXTENDED_DATA.new(logger: logger).decode payload
local_channel = message[:'recipient channel']
@channels[local_channel].receive_message_queue.enq message if @channels.has_key? local_channel
end
|
#channel_open(payload) ⇒ Object
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
# File 'lib/hrr_rb_ssh/connection.rb', line 172
def channel_open payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_OPEN::ID }
message = Message::SSH_MSG_CHANNEL_OPEN.new(logger: logger).decode payload
begin
channel = Channel.new self, message, logger: logger
@channels[channel.local_channel] = channel
channel.start
send_channel_open_confirmation channel
rescue => e
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
recipient_channel = message[:'sender channel']
send_channel_open_failure recipient_channel, Message::SSH_MSG_CHANNEL_OPEN_FAILURE::ReasonCode::SSH_OPEN_CONNECT_FAILED, e.message
end
end
|
#channel_open_confirmation(payload) ⇒ Object
215
216
217
218
219
220
221
|
# File 'lib/hrr_rb_ssh/connection.rb', line 215
def channel_open_confirmation payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION::ID }
message = Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION.new(logger: logger).decode payload
channel = @channels[message[:'recipient channel']]
channel.set_remote_parameters message
channel.start
end
|
#channel_open_start(address, port, socket) ⇒ Object
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
# File 'lib/hrr_rb_ssh/connection.rb', line 153
def channel_open_start address, port, socket
log_info { 'channel open start' }
channel = Channel.new self, {:'channel type' => "forwarded-tcpip"}, socket, logger: logger
@channels[channel.local_channel] = channel
log_info { 'channel opened' }
message = {
:'message number' => Message::SSH_MSG_CHANNEL_OPEN::VALUE,
:'channel type' => "forwarded-tcpip",
:'sender channel' => channel.local_channel,
:'initial window size' => channel.local_window_size,
:'maximum packet size' => channel.local_maximum_packet_size,
:'address that was connected' => address,
:'port that was connected' => port,
:'originator IP address' => socket.remote_address.ip_address,
:'originator port' => socket.remote_address.ip_port,
}
send_channel_open message
end
|
#channel_request(payload) ⇒ Object
223
224
225
226
227
228
|
# File 'lib/hrr_rb_ssh/connection.rb', line 223
def channel_request payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_REQUEST::ID }
message = Message::SSH_MSG_CHANNEL_REQUEST.new(logger: logger).decode payload
local_channel = message[:'recipient channel']
@channels[local_channel].receive_message_queue.enq message if @channels.has_key? local_channel
end
|
#channel_window_adjust(payload) ⇒ Object
230
231
232
233
234
235
|
# File 'lib/hrr_rb_ssh/connection.rb', line 230
def channel_window_adjust payload
log_info { 'received ' + Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::ID }
message = Message::SSH_MSG_CHANNEL_WINDOW_ADJUST.new(logger: logger).decode payload
local_channel = message[:'recipient channel']
@channels[local_channel].receive_message_queue.enq message if @channels.has_key? local_channel
end
|
#close ⇒ Object
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/hrr_rb_ssh/connection.rb', line 69
def close
return if @closed
log_info { "close connection" }
@closed = true
@authentication.close
@channels.values.each do |channel|
begin
channel.close
rescue => e
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
end
end
@channels.clear
@global_request_handler.close
@connection_loop_thread.join if @connection_loop_thread && @connection_loop_thread != Thread.current
log_info { "connection closed" }
end
|
#closed? ⇒ Boolean
87
88
89
|
# File 'lib/hrr_rb_ssh/connection.rb', line 87
def closed?
@closed
end
|
#connection_loop_thread ⇒ Object
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
|
# File 'lib/hrr_rb_ssh/connection.rb', line 91
def connection_loop_thread
log_info { "start connection loop" }
Thread.new do
begin
while true
begin
payload = @authentication.receive
rescue Error::ClosedAuthentication => e
log_info { "authentication closed" }
break
end
@username ||= @authentication.username
@variables ||= @authentication.variables
case payload[0,1].unpack("C")[0]
when Message::SSH_MSG_GLOBAL_REQUEST::VALUE
global_request payload
when Message::SSH_MSG_CHANNEL_OPEN::VALUE
channel_open payload
when Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION::VALUE
channel_open_confirmation payload
when Message::SSH_MSG_CHANNEL_REQUEST::VALUE
channel_request payload
when Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE
channel_window_adjust payload
when Message::SSH_MSG_CHANNEL_DATA::VALUE
channel_data payload
when Message::SSH_MSG_CHANNEL_EXTENDED_DATA::VALUE
channel_extended_data payload
when Message::SSH_MSG_CHANNEL_EOF::VALUE
channel_eof payload
when Message::SSH_MSG_CHANNEL_CLOSE::VALUE
channel_close payload
else
log_warn { "received unsupported message: id: #{payload[0,1].unpack("C")[0]}" }
end
end
rescue => e
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
ensure
log_info { "closing connection loop" }
close
log_info { "connection loop closed" }
end
end
end
|
#global_request(payload) ⇒ Object
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/hrr_rb_ssh/connection.rb', line 137
def global_request payload
log_info { 'received ' + Message::SSH_MSG_GLOBAL_REQUEST::ID }
message = Message::SSH_MSG_GLOBAL_REQUEST.new(logger: logger).decode payload
begin
@global_request_handler.request message
rescue
if message[:'want reply']
send_request_failure
end
else
if message[:'want reply']
send_request_success
end
end
end
|
#loop ⇒ Object
65
66
67
|
# File 'lib/hrr_rb_ssh/connection.rb', line 65
def loop
@connection_loop_thread.join
end
|
#request_channel_open(channel_type, channel_specific_message = {}, wait_response = true) ⇒ Object
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
|
# File 'lib/hrr_rb_ssh/connection.rb', line 187
def request_channel_open channel_type, channel_specific_message={}, wait_response=true
log_info { 'request channel open' }
case channel_type
when "session"
channel = Channel.new self, {:'channel type' => channel_type}, logger: logger
@channels[channel.local_channel] = channel
end
message = {
:'message number' => Message::SSH_MSG_CHANNEL_OPEN::VALUE,
:'channel type' => channel_type,
:'sender channel' => channel.local_channel,
:'initial window size' => channel.local_window_size,
:'maximum packet size' => channel.local_maximum_packet_size,
}
send_channel_open message.merge(channel_specific_message)
log_info { 'sent channel open' }
if wait_response
log_info { 'wait response' }
channel.wait_until_started
end
unless channel.closed?
log_info { 'channel opened' }
channel
else
raise "Faild opening channel"
end
end
|
#send(payload) ⇒ Object
31
32
33
34
35
36
37
38
|
# File 'lib/hrr_rb_ssh/connection.rb', line 31
def send payload
raise Error::ClosedConnection if @closed
begin
@authentication.send payload
rescue Error::ClosedAuthentication
raise Error::ClosedConnection
end
end
|
#send_channel_open(message) ⇒ Object
288
289
290
291
|
# File 'lib/hrr_rb_ssh/connection.rb', line 288
def send_channel_open message
payload = Message::SSH_MSG_CHANNEL_OPEN.new(logger: logger).encode message
@authentication.send payload
end
|
#send_channel_open_confirmation(channel) ⇒ Object
293
294
295
296
297
298
299
300
301
302
303
304
|
# File 'lib/hrr_rb_ssh/connection.rb', line 293
def send_channel_open_confirmation channel
message = {
:'message number' => Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION::VALUE,
:'channel type' => channel.channel_type,
:'recipient channel' => channel.remote_channel,
:'sender channel' => channel.local_channel,
:'initial window size' => channel.local_window_size,
:'maximum packet size' => channel.local_maximum_packet_size,
}
payload = Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION.new(logger: logger).encode message
@authentication.send payload
end
|
#send_channel_open_failure(recipient_channel, reason_code, description) ⇒ Object
306
307
308
309
310
311
312
313
314
315
316
|
# File 'lib/hrr_rb_ssh/connection.rb', line 306
def send_channel_open_failure recipient_channel, reason_code, description
message = {
:'message number' => Message::SSH_MSG_CHANNEL_OPEN_FAILURE::VALUE,
:'recipient channel' => recipient_channel,
:'reason code' => reason_code,
:'description' => description,
:'language tag' => "",
}
payload = Message::SSH_MSG_CHANNEL_OPEN_FAILURE.new(logger: logger).encode message
@authentication.send payload
end
|
#send_request_failure ⇒ Object
280
281
282
283
284
285
286
|
# File 'lib/hrr_rb_ssh/connection.rb', line 280
def send_request_failure
message = {
:'message number' => Message::SSH_MSG_REQUEST_FAILURE::VALUE,
}
payload = Message::SSH_MSG_REQUEST_FAILURE.new(logger: logger).encode message
@authentication.send payload
end
|
#send_request_success ⇒ Object
272
273
274
275
276
277
278
|
# File 'lib/hrr_rb_ssh/connection.rb', line 272
def send_request_success
message = {
:'message number' => Message::SSH_MSG_REQUEST_SUCCESS::VALUE,
}
payload = Message::SSH_MSG_REQUEST_SUCCESS.new(logger: logger).encode message
@authentication.send payload
end
|
#start(foreground: true) ⇒ Object
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
# File 'lib/hrr_rb_ssh/connection.rb', line 50
def start foreground: true
log_info { "start connection" }
begin
@authentication.start
rescue Error::ClosedAuthentication
close
raise Error::ClosedConnection
end
@closed = false
@connection_loop_thread = connection_loop_thread
if foreground
@connection_loop_thread.join
end
end
|