Class: TunnelRb::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/tunnel_rb/server.rb,
lib/tunnel_rb/server/tls.rb,
lib/tunnel_rb/server/client.rb,
lib/tunnel_rb/server/logger.rb,
lib/tunnel_rb/server/thread_pool.rb,
lib/tunnel_rb/server/token_store.rb,
lib/tunnel_rb/server/http_request.rb,
lib/tunnel_rb/server/public_server.rb,
lib/tunnel_rb/server/control_server.rb,
lib/tunnel_rb/server/socket_helpers.rb,
lib/tunnel_rb/server/client_registry.rb,
lib/tunnel_rb/server/pending_connections.rb

Overview

Top-level coordinator. Wires the components together, owns the background threads, and handles graceful shutdown on SIGINT/SIGTERM.

Defined Under Namespace

Modules: HttpRequest, SocketHelpers, TLS Classes: Client, ClientRegistry, ControlServer, Logger, PendingConnections, PublicServer, ThreadPool, TokenStore

Instance Method Summary collapse

Constructor Details

#initialize(control_port:, public_port:, domain:, url_port: nil, tokens_path: TokenStore::DEFAULT_PATH, tls_cert: nil, tls_key: nil, logger: Logger.new) ⇒ Server

Returns a new instance of Server.



15
16
17
18
19
20
21
22
23
24
25
26
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
55
56
# File 'lib/tunnel_rb/server.rb', line 15

def initialize(
  control_port:,
  public_port:,
  domain:,
  url_port: nil,
  tokens_path: TokenStore::DEFAULT_PATH,
  tls_cert: nil,
  tls_key: nil,
  logger: Logger.new
)
  @logger = logger
  @registry = ClientRegistry.new
  @token_store = TokenStore.new(
    path: tokens_path,
    active_subdomains: -> { @registry.active_subdomains },
    logger: @logger
  )
  @pending_connections = PendingConnections.new

  tls_context = TLS.server_context(cert_path: tls_cert, key_path: tls_key)

  @control = ControlServer.new(
    port: control_port,
    domain: domain,
    url_port: url_port,
    registry: @registry,
    token_store: @token_store,
    pending_connections: @pending_connections,
    tls_context: tls_context,
    logger: @logger
  )
  @public = PublicServer.new(
    port: public_port,
    registry: @registry,
    pending_connections: @pending_connections,
    logger: @logger
  )

  @stop_flag = false
  @threads = []
  @stop_mutex = Mutex.new
end

Instance Method Details

#start(install_signals: true) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/tunnel_rb/server.rb', line 58

def start(install_signals: true)
  @logger.info "🚀 Starting tunnel server..."
  @logger.info(@control.tls? ? "🔒 Control plane TLS: enabled" : "🔓 Control plane TLS: disabled")
  install_signal_handlers if install_signals

  @threads << Thread.new { @control.start }
  @threads << Thread.new { @public.start }
  @threads << Thread.new { @control.read_loop }
  @threads << Thread.new { @control.ping_loop }
  @threads << Thread.new {
    @token_store.cleanup_loop(stop_flag: -> { @stop_flag })
  }

  @threads.each(&:join)
end

#stopObject



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/tunnel_rb/server.rb', line 74

def stop
  @stop_mutex.synchronize do
    return if @stop_flag

    @stop_flag = true
  end

  @logger.info "👋 Shutting down..."
  @control.stop
  @public.stop
  @token_store.persist_now
  @threads.each { |t| t.join(2) }
end