Class: RTunnel::Server

Inherits:
Object
  • Object
show all
Includes:
RTunnel, CommandProcessor, ConnectionId, Logging
Defined in:
lib/rtunnel/server.rb

Overview

The RTunnel server class, managing control and connection servers.

Defined Under Namespace

Classes: ControlConnection, TunnelConnection

Constant Summary

Constants included from RTunnel

DEFAULT_CONTROL_PORT, KEEP_ALIVE_INTERVAL, TUNNEL_TIMEOUT

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ConnectionId

new_cipher, #new_connection_id, new_counter

Methods included from Logging

#D, #E, #F, #I, #W, #init_log

Methods included from CommandProcessor

#process_close_connection, #process_create_connection, #process_generate_session_key, #process_keep_alive, #process_remote_listen, #process_send_data, #process_set_session_key, #receive_command, #unexpected_command

Methods included from RTunnel

resolve_address, run_client, run_server

Constructor Details

#initialize(options = {}) ⇒ Server

Returns a new instance of Server.



19
20
21
22
23
24
# File 'lib/rtunnel/server.rb', line 19

def initialize(options = {})
  process_options options
  @tunnel_controls = {}
  @tunnel_connections = {}
  @tunnel_connections_by_control = {}
end

Instance Attribute Details

#authorized_keysObject (readonly)

Returns the value of attribute authorized_keys.



15
16
17
# File 'lib/rtunnel/server.rb', line 15

def authorized_keys
  @authorized_keys
end

#control_addressObject (readonly)

Returns the value of attribute control_address.



14
15
16
# File 'lib/rtunnel/server.rb', line 14

def control_address
  @control_address
end

#control_hostObject (readonly)

Returns the value of attribute control_host.



14
15
16
# File 'lib/rtunnel/server.rb', line 14

def control_host
  @control_host
end

#control_portObject (readonly)

Returns the value of attribute control_port.



14
15
16
# File 'lib/rtunnel/server.rb', line 14

def control_port
  @control_port
end

#highest_listen_portObject (readonly)

Returns the value of attribute highest_listen_port.



16
17
18
# File 'lib/rtunnel/server.rb', line 16

def highest_listen_port
  @highest_listen_port
end

#keep_alive_intervalObject (readonly)

Returns the value of attribute keep_alive_interval.



15
16
17
# File 'lib/rtunnel/server.rb', line 15

def keep_alive_interval
  @keep_alive_interval
end

#lowest_listen_portObject (readonly)

Returns the value of attribute lowest_listen_port.



16
17
18
# File 'lib/rtunnel/server.rb', line 16

def lowest_listen_port
  @lowest_listen_port
end

#tunnel_connectionsObject (readonly)

Returns the value of attribute tunnel_connections.



17
18
19
# File 'lib/rtunnel/server.rb', line 17

def tunnel_connections
  @tunnel_connections
end

Class Method Details

.extract_authorized_keys(keys_file) ⇒ Object



127
128
129
# File 'lib/rtunnel/server.rb', line 127

def self.extract_authorized_keys(keys_file)
  keys_file and Crypto.load_public_keys keys_file
end

.extract_control_address(address) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/rtunnel/server.rb', line 109

def self.extract_control_address(address)
  return "0.0.0.0:#{RTunnel::DEFAULT_CONTROL_PORT}" unless address
  if address =~ /^\d+$/
    host = nil
    port = address.to_i
  else
    host = SocketFactory.host_from_address address
    port = SocketFactory.port_from_address address
  end
  host = RTunnel.resolve_address(host || "0.0.0.0")
  port ||= RTunnel::DEFAULT_CONTROL_PORT.to_s
  "#{host}:#{port}"
end

.extract_highest_listen_port(port) ⇒ Object



135
136
137
# File 'lib/rtunnel/server.rb', line 135

def self.extract_highest_listen_port(port)
  port || 65535
end

.extract_keep_alive_interval(interval) ⇒ Object



123
124
125
# File 'lib/rtunnel/server.rb', line 123

def self.extract_keep_alive_interval(interval)
  interval || RTunnel::KEEP_ALIVE_INTERVAL
end

.extract_lowest_listen_port(port) ⇒ Object



131
132
133
# File 'lib/rtunnel/server.rb', line 131

def self.extract_lowest_listen_port(port)
  port || 0
end

Instance Method Details

#create_tunnel_listener(listen_port, control_connection, &creation_block) ⇒ Object

Creates a listener on a certain port. The given block should create and return the listener. If a listener is already active on the given port, the current listener is closed, and the new listener is created after the old listener is closed.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rtunnel/server.rb', line 50

def create_tunnel_listener(listen_port, control_connection, &creation_block)
  if old_control = @tunnel_controls[listen_port]
    D "Closing old listener on port #{listen_port}"
    EventMachine.stop_server old_control.listener
  end
  
  EventMachine.next_tick do
    next unless yield
    
    @tunnel_controls[listen_port] = control_connection
    redirect_tunnel_connections old_control, control_connection if old_control
    on_remote_listen
  end
end

#deregister_tunnel_connection(connection) ⇒ Object

De-registers a tunnel connection.



74
75
76
77
78
# File 'lib/rtunnel/server.rb', line 74

def deregister_tunnel_connection(connection)
  @tunnel_connections.delete connection.connection_id
  control_connection = connection.control_connection
  @tunnel_connections_by_control[control_connection].delete connection
end

#on_remote_listen(&block) ⇒ Object



89
90
91
92
93
94
95
# File 'lib/rtunnel/server.rb', line 89

def on_remote_listen(&block)
  if block
    @on_remote_listen = block
  elsif @on_remote_listen
    @on_remote_listen.call
  end 
end

#process_options(options) ⇒ Object

option processing



99
100
101
102
103
104
105
106
107
# File 'lib/rtunnel/server.rb', line 99

def process_options(options)
  [:control_address, :keep_alive_interval, :authorized_keys,
   :lowest_listen_port, :highest_listen_port].each do |opt|
    instance_variable_set "@#{opt}".to_sym,
        RTunnel::Server.send("extract_#{opt}".to_sym, options[opt])
  end
  
  init_log :level => options[:log_level]    
end

#redirect_tunnel_connections(old_control, new_control) ⇒ Object



80
81
82
83
84
85
86
87
# File 'lib/rtunnel/server.rb', line 80

def redirect_tunnel_connections(old_control, new_control)
  return unless old_connections = @tunnel_connections_by_control[old_control]
  old_connections.each do |tunnel_connection|
    tunnel_connection.control_connection = new_control
  end
  @tunnel_connections_by_control[new_control] ||= Set.new
  @tunnel_connections_by_control[new_control] += old_connections
end

#register_tunnel_connection(connection) ⇒ Object

Registers a tunnel connection, so it can receive data.



66
67
68
69
70
71
# File 'lib/rtunnel/server.rb', line 66

def register_tunnel_connection(connection)
  @tunnel_connections[connection.connection_id] = connection
  control_connection = connection.control_connection
  @tunnel_connections_by_control[control_connection] ||= Set.new
  @tunnel_connections_by_control[control_connection] << connection
end

#startObject



26
27
28
29
30
31
# File 'lib/rtunnel/server.rb', line 26

def start
  return if @control_listener
  @control_host = SocketFactory.host_from_address @control_address
  @control_port = SocketFactory.port_from_address @control_address
  start_server
end

#start_serverObject



39
40
41
42
43
44
# File 'lib/rtunnel/server.rb', line 39

def start_server
  D "Control server on #{@control_host} port #{@control_port}"
  @control_listener = EventMachine.start_server @control_host, @control_port,
                                                Server::ControlConnection,
                                                self
end

#stopObject



33
34
35
36
37
# File 'lib/rtunnel/server.rb', line 33

def stop
  return unless @control_listener
  EventMachine.stop_server @control_listener
  @control_listener = nil
end