Class: RTunnel::Server::ControlConnection
- Inherits:
-
EventMachine::Connection
- Object
- EventMachine::Connection
- RTunnel::Server::ControlConnection
- Includes:
- RTunnel, CommandProcessor, CommandProtocol, Logging
- Defined in:
- lib/rtunnel/server.rb
Overview
A client connection to the server’s control port.
Constant Summary
Constants included from RTunnel
DEFAULT_CONTROL_PORT, KEEP_ALIVE_INTERVAL, TUNNEL_TIMEOUT
Instance Attribute Summary collapse
-
#listener ⇒ Object
readonly
Returns the value of attribute listener.
-
#server ⇒ Object
readonly
Returns the value of attribute server.
Instance Method Summary collapse
-
#disable_keep_alives ⇒ Object
Disables sending KeepAlives.
-
#enable_keep_alives ⇒ Object
Enables sending KeepAliveCommands every few seconds.
-
#initialize(server) ⇒ ControlConnection
constructor
A new instance of ControlConnection.
-
#keep_alive_if_needed ⇒ Object
Sends a KeepAlive command if no command was sent recently.
- #post_init ⇒ Object
- #process_close_connection(tunnel_connection_id) ⇒ Object
- #process_generate_session_key(public_key_fp) ⇒ Object
-
#process_remote_listen(address) ⇒ Object
Command processing.
- #process_send_data(tunnel_connection_id, data) ⇒ Object
- #receive_bad_frame(frame, exception) ⇒ Object
-
#send_command(command) ⇒ Object
:nodoc:.
- #unbind ⇒ Object
-
#validate_remote_listen(host, port) ⇒ Object
Verifies if a RemoteListenCommand should be honored.
Methods included from Logging
Methods included from CommandProtocol
#incoming_command_hasher=, #outgoing_command_hasher=, #receive_frame
Methods included from FrameProtocol
Methods included from CommandProcessor
#process_create_connection, #process_keep_alive, #process_set_session_key, #receive_command, #unexpected_command
Methods included from RTunnel
resolve_address, run_client, run_server
Constructor Details
#initialize(server) ⇒ ControlConnection
Returns a new instance of ControlConnection.
150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/rtunnel/server.rb', line 150 def initialize(server) super() @server = server @tunnel_connections = server.tunnel_connections @listener = nil @keep_alive_timer = nil @keep_alive_interval = server.keep_alive_interval @in_hasher = @out_hasher = nil init_log :to => @server end |
Instance Attribute Details
#listener ⇒ Object (readonly)
Returns the value of attribute listener.
148 149 150 |
# File 'lib/rtunnel/server.rb', line 148 def listener @listener end |
#server ⇒ Object (readonly)
Returns the value of attribute server.
148 149 150 |
# File 'lib/rtunnel/server.rb', line 148 def server @server end |
Instance Method Details
#disable_keep_alives ⇒ Object
Disables sending KeepAlives.
298 299 300 301 302 |
# File 'lib/rtunnel/server.rb', line 298 def disable_keep_alives return unless @keep_alive_timer @keep_alive_timer.cancel @keep_alive_timer = nil end |
#enable_keep_alives ⇒ Object
Enables sending KeepAliveCommands every few seconds.
282 283 284 285 286 287 288 |
# File 'lib/rtunnel/server.rb', line 282 def enable_keep_alives @last_command_time = Time.now @keep_alive_timer = EventMachine::PeriodicTimer.new(@keep_alive_interval / 2) do keep_alive_if_needed end end |
#keep_alive_if_needed ⇒ Object
Sends a KeepAlive command if no command was sent recently.
291 292 293 294 295 |
# File 'lib/rtunnel/server.rb', line 291 def keep_alive_if_needed if Time.now - @last_command_time >= @keep_alive_interval send_command KeepAliveCommand.new end end |
#post_init ⇒ Object
163 164 165 166 167 |
# File 'lib/rtunnel/server.rb', line 163 def post_init @client_port, @client_host = *Socket.unpack_sockaddr_in(get_peername) D "Established connection with #{@client_host} port #{@client_port}" enable_keep_alives end |
#process_close_connection(tunnel_connection_id) ⇒ Object
227 228 229 230 231 232 233 234 235 |
# File 'lib/rtunnel/server.rb', line 227 def process_close_connection(tunnel_connection_id) tunnel_connection = @tunnel_connections[tunnel_connection_id] if tunnel_connection D "Closed from tunneled end: #{tunnel_connection_id}" tunnel_connection.close_from_tunnel else W "Asked to close unknown connection #{tunnel_connection_id}" end end |
#process_generate_session_key(public_key_fp) ⇒ Object
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/rtunnel/server.rb', line 237 def process_generate_session_key(public_key_fp) if @server. if public_key = @server.[public_key_fp] D "Authorized client key received, generating session key" @out_hasher, @in_hasher = Crypto::Hasher.new, Crypto::Hasher.new iokeys = StringIO.new iokeys.write_varstring @in_hasher.key iokeys.write_varstring @out_hasher.key encrypted_keys = Crypto.encrypt_with_key public_key, iokeys.string else D("Rejecting unauthorized client key (%s authorized keys)" % @server..length) encrypted_keys = 'NO' end else D "Asked to generate session key, but no authorized keys set" encrypted_keys = '' end send_command SetSessionKeyCommand.new(encrypted_keys) self.incoming_command_hasher = @in_hasher if @in_hasher self.outgoing_command_hasher = @out_hasher if @out_hasher end |
#process_remote_listen(address) ⇒ Object
Command processing
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/rtunnel/server.rb', line 177 def process_remote_listen(address) listen_host = SocketFactory.host_from_address address listen_port = SocketFactory.port_from_address address unless validate_remote_listen listen_host, listen_port send_command SetSessionKeyCommand.new('NO') return end @server.create_tunnel_listener listen_port, self do D "Creating listener for #{listen_host} port #{listen_port}" begin @listener = EventMachine.start_server listen_host, listen_port, Server::TunnelConnection, self, listen_host, listen_port rescue RuntimeError => e # EventMachine raises 'no acceptor' if the listen address is invalid E "Invalid listen address #{listen_host}" @listener = nil end end D "Listening on #{listen_host} port #{listen_port}" end |
#process_send_data(tunnel_connection_id, data) ⇒ Object
217 218 219 220 221 222 223 224 225 |
# File 'lib/rtunnel/server.rb', line 217 def process_send_data(tunnel_connection_id, data) tunnel_connection = @tunnel_connections[tunnel_connection_id] if tunnel_connection D "Data: #{data.length} bytes coming from #{tunnel_connection_id}" tunnel_connection.send_data data else W "Asked to send to unknown connection #{tunnel_connection_id}" end end |
#receive_bad_frame(frame, exception) ⇒ Object
261 262 263 264 265 266 267 268 269 270 |
# File 'lib/rtunnel/server.rb', line 261 def receive_bad_frame(frame, exception) case exception when :bad_signature D "Ignoring command with invalid signature" when Exception D "Ignoring malformed command." D "Decoding exception: #{exception.class.name} - #{exception}\n" + "#{exception.backtrace.join("\n")}\n" end end |
#send_command(command) ⇒ Object
:nodoc:
276 277 278 279 |
# File 'lib/rtunnel/server.rb', line 276 def send_command(command) @last_command_time = Time.now super end |
#unbind ⇒ Object
169 170 171 172 |
# File 'lib/rtunnel/server.rb', line 169 def unbind D "Lost connection from #{@client_host} port #{@client_port}" disable_keep_alives end |
#validate_remote_listen(host, port) ⇒ Object
Verifies if a RemoteListenCommand should be honored.
203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/rtunnel/server.rb', line 203 def validate_remote_listen(host, port) if @server. and @out_hasher.nil? D "Asked to open listen socket by unauthorized client" return false end if port < @server.lowest_listen_port or port > @server.highest_listen_port D "Asked to listen to forbidden port" return false end true end |