Class: RTunnel::Client::ServerConnection
- Inherits:
-
EventMachine::Connection
- Object
- EventMachine::Connection
- RTunnel::Client::ServerConnection
- Includes:
- RTunnel, RTunnel::CommandProcessor, RTunnel::CommandProtocol, Logging
- Defined in:
- lib/rtunnel/client.rb
Overview
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
-
#client ⇒ Object
readonly
Returns the value of attribute client.
Instance Method Summary collapse
-
#check_tunnel_timeout ⇒ Object
Closes the connection if no command has been received for some time.
-
#data_connection_closed(connection_id) ⇒ Object
Called when a tunnel connection is closed.
-
#disable_tunnel_timeouts ⇒ Object
Disables timeout checking (so the tunnel will not be torn down if no command is received for some period of time).
-
#enable_tunnel_timeouts ⇒ Object
After this is called, the control connection will be closed if no command is received within a certain amount of time.
-
#initialize(client) ⇒ ServerConnection
constructor
A new instance of ServerConnection.
- #post_init ⇒ Object
-
#process_close_connection(connection_id) ⇒ Object
CloseConnectionCommand handler.
-
#process_create_connection(connection_id) ⇒ Object
CreateConnectionCommand handler.
-
#process_keep_alive ⇒ Object
Keep-alive received from the control connection.
-
#process_send_data(connection_id, data) ⇒ Object
SendData handler.
-
#process_set_session_key(encrypted_keys) ⇒ Object
SetSessionKey handler.
- #receive_bad_frame(frame, exception) ⇒ Object
-
#receive_command(command) ⇒ Object
:nodoc:.
-
#request_listen ⇒ Object
Asks the server to open a listen socket for this client’s tunnel.
-
#request_session_key ⇒ Object
Asks the server to establish a session key with this client.
-
#tunnel_timeout? ⇒ Boolean
If true, a tunnel timeout has occured.
- #unbind ⇒ Object
Methods included from RTunnel::CommandProtocol
#incoming_command_hasher=, #outgoing_command_hasher=, #receive_frame, #send_command
Methods included from FrameProtocol
Methods included from RTunnel::CommandProcessor
#process_generate_session_key, #process_remote_listen, #unexpected_command
Methods included from Logging
Methods included from RTunnel
resolve_address, run_client, run_server
Constructor Details
#initialize(client) ⇒ ServerConnection
Returns a new instance of ServerConnection.
99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rtunnel/client.rb', line 99 def initialize(client) super() @client = client @tunnel_to_address = client.tunnel_to_address @tunnel_to_host = SocketFactory.host_from_address @tunnel_to_address @tunnel_to_port = SocketFactory.port_from_address @tunnel_to_address @timeout_timer = nil @hasher = nil @connections = @client.connections init_log :to => @client end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
97 98 99 |
# File 'lib/rtunnel/client.rb', line 97 def client @client end |
Instance Method Details
#check_tunnel_timeout ⇒ Object
Closes the connection if no command has been received for some time.
244 245 246 247 248 249 250 |
# File 'lib/rtunnel/client.rb', line 244 def check_tunnel_timeout if tunnel_timeout? W 'Tunnel timeout. Disconnecting from server.' disable_tunnel_timeouts close_connection_after_writing end end |
#data_connection_closed(connection_id) ⇒ Object
Called when a tunnel connection is closed.
168 169 170 171 172 |
# File 'lib/rtunnel/client.rb', line 168 def data_connection_closed(connection_id) return unless @connections.delete(connection_id) D "Connection #{connection_id} closed by this end" send_command CloseConnectionCommand.new(connection_id) end |
#disable_tunnel_timeouts ⇒ Object
Disables timeout checking (so the tunnel will not be torn down if no command is received for some period of time).
254 255 256 257 258 |
# File 'lib/rtunnel/client.rb', line 254 def disable_tunnel_timeouts return unless @timeout_timer @timeout_timer.cancel @timeout_timer = nil end |
#enable_tunnel_timeouts ⇒ Object
After this is called, the control connection will be closed if no command is received within a certain amount of time.
236 237 238 239 240 241 |
# File 'lib/rtunnel/client.rb', line 236 def enable_tunnel_timeouts @last_packet_time = Time.now @timeout_timer = EventMachine::PeriodicTimer.new(1.0) do check_tunnel_timeout end end |
#post_init ⇒ Object
112 113 114 115 116 117 118 |
# File 'lib/rtunnel/client.rb', line 112 def post_init if @client.private_key request_session_key else request_listen end end |
#process_close_connection(connection_id) ⇒ Object
CloseConnectionCommand handler
158 159 160 161 162 163 164 165 166 |
# File 'lib/rtunnel/client.rb', line 158 def process_close_connection(connection_id) if connection = @connections[connection_id] I "Closing connection #{connection_id}" connection.close_connection_after_writing @connections.delete connection_id else W "Asked to close inexistent connection #{connection_id}" end end |
#process_create_connection(connection_id) ⇒ Object
CreateConnectionCommand handler
145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/rtunnel/client.rb', line 145 def process_create_connection(connection_id) if @connections[connection_id] E "asked to create already open connection #{connection_id}" return end D "Tunnel #{connection_id} to #{@tunnel_to_host} port #{@tunnel_to_port}" connection = EventMachine.connect(@tunnel_to_host, @tunnel_to_port, Client::TunnelConnection, connection_id, @client) @connections[connection_id] = connection end |
#process_keep_alive ⇒ Object
Keep-alive received from the control connection.
225 226 |
# File 'lib/rtunnel/client.rb', line 225 def process_keep_alive end |
#process_send_data(connection_id, data) ⇒ Object
SendData handler
175 176 177 178 179 180 181 182 |
# File 'lib/rtunnel/client.rb', line 175 def process_send_data(connection_id, data) if connection = @connections[connection_id] D "Data: #{data.length} bytes for #{connection_id}" connection.tunnel_data data else W "Received data for non-existent connection #{connection_id}!" end end |
#process_set_session_key(encrypted_keys) ⇒ Object
SetSessionKey handler
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 |
# File 'lib/rtunnel/client.rb', line 185 def process_set_session_key(encrypted_keys) case encrypted_keys when '' W "Sent key to open tunnel server" request_listen when 'NO' if @client.private_key E "Server refused provided key" else E "Server requires authentication and no private key was provided" end close_connection_after_writing else D "Received server session keys, installing hashers" iokeys = StringIO.new Crypto.decrypt_with_key(client.private_key, encrypted_keys) @out_hasher = Crypto::Hasher.new iokeys.read_varstring @in_hasher = Crypto::Hasher.new iokeys.read_varstring self.outgoing_command_hasher = @out_hasher self.incoming_command_hasher = @in_hasher D "Hashers installed, opening listen socket on server" request_listen end end |
#receive_bad_frame(frame, exception) ⇒ Object
211 212 213 214 215 216 217 218 219 220 |
# File 'lib/rtunnel/client.rb', line 211 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 |
#receive_command(command) ⇒ Object
:nodoc:
229 230 231 232 |
# File 'lib/rtunnel/client.rb', line 229 def receive_command(command) @last_packet_time = Time.now super end |
#request_listen ⇒ Object
Asks the server to open a listen socket for this client’s tunnel.
121 122 123 124 |
# File 'lib/rtunnel/client.rb', line 121 def request_listen send_command RemoteListenCommand.new(@client.remote_listen_address) enable_tunnel_timeouts end |
#request_session_key ⇒ Object
Asks the server to establish a session key with this client.
127 128 129 130 131 |
# File 'lib/rtunnel/client.rb', line 127 def request_session_key D 'Private key provided, asking server for session key' key_fp = Crypto.key_fingerprint @client.private_key send_command GenerateSessionKeyCommand.new(key_fp) end |
#tunnel_timeout? ⇒ Boolean
If true, a tunnel timeout has occured.
261 262 263 |
# File 'lib/rtunnel/client.rb', line 261 def tunnel_timeout? Time.now - @last_packet_time > client.tunnel_timeout end |
#unbind ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/rtunnel/client.rb', line 133 def unbind # wait for a second, then try connecting again W 'Lost server connection, will reconnect in 1s' EventMachine.add_timer(1.0) { client.connect_to_server } @connections.each { |conn_id, conn| conn.close_connection_after_writing } @connections.clear end |