Project

General

Profile

Download (2.36 KB) Statistics
| Branch: | Tag: | Revision:
197e2dce Ohad Levy
require 'open3'
cdd8424f Lukas Zapletal
require 'socket'
require 'timeout'
197e2dce Ohad Levy
class PortInUse < StandardError; end

8ffd9aee Ohad Levy
class WsProxy
attr_accessor :host, :host_port, :password, :timeout, :idle_timeout, :ssl_target
197e2dce Ohad Levy
attr_reader :proxy_port

# Allowed ports to communicate with our web sockets proxy
PORTS = 5910..5930

def initialize(attributes)
# setup all attributes.
defaults.merge(attributes).each do |k, v|
c86ed9c6 Michael Moll
send("#{k}=", v) if respond_to?("#{k}=")
197e2dce Ohad Levy
end
end

5f029ed6 Daniel Lobato
def self.start(attributes)
8ffd9aee Ohad Levy
proxy = WsProxy.new(attributes)
197e2dce Ohad Levy
proxy.start_proxy
end

f35f4a5f Michael Moll
def free_port?(port)
cdd8424f Lukas Zapletal
socket = Socket.new :INET, :STREAM
socket.bind(Socket.pack_sockaddr_in(port, '127.0.0.1'))
5f5b13a9 Michael Moll
true
cdd8424f Lukas Zapletal
rescue Errno::EADDRINUSE
5f5b13a9 Michael Moll
false
cdd8424f Lukas Zapletal
ensure
b03dcd1b Michael Moll
socket&.close
cdd8424f Lukas Zapletal
end

197e2dce Ohad Levy
def start_proxy
cdd8424f Lukas Zapletal
# randomly preselect free tcp port from the range
port = 0
8bbfa2c3 David Davis
Timeout.timeout(5) do
cdd8424f Lukas Zapletal
until free_port?(port = rand(PORTS)); end
end
# execute websockify proxy
197e2dce Ohad Levy
begin
20f48047 Ewoud Kohl van Wijngaarden
cmd = "websockify --daemon --idle-timeout=#{idle_timeout} --timeout=#{timeout} #{port} #{host}:#{host_port}"
8ffd9aee Ohad Levy
cmd += " --ssl-target" if ssl_target
97c34475 Lukas Zapletal
if Setting[:websockets_encrypt]
cmd += " --cert #{Setting[:websockets_ssl_cert]}" if Setting[:websockets_ssl_cert]
cmd += " --key #{Setting[:websockets_ssl_key]}" if Setting[:websockets_ssl_key]
end
197e2dce Ohad Levy
execute(cmd)
20f48047 Ewoud Kohl van Wijngaarden
rescue Errno::ENOENT
raise ::Foreman::Exception.new(N_('Websockify was not found'))
197e2dce Ohad Levy
rescue PortInUse
cdd8424f Lukas Zapletal
# fallback just in case of race condition
197e2dce Ohad Levy
port += 1
cdd8424f Lukas Zapletal
if port >= PORTS.last
75618724 Dominic Cleal
raise ::Foreman::Exception.new(N_('No free ports available for websockify, try again later'))
cdd8424f Lukas Zapletal
else
retry
end
197e2dce Ohad Levy
end
@proxy_port = port
c11b7561 Shira Maximov
{ :port => proxy_port, :password => password, :encrypt => Setting[:websockets_encrypt] }
197e2dce Ohad Levy
end

private

def defaults
{
8ffd9aee Ohad Levy
:timeout => 120,
:idle_timeout => 120,
:host_port => 5900,
f2ee562e Marek Hulan
:host => "0.0.0.0",
197e2dce Ohad Levy
}
end

def logger
Rails.logger
end

5f029ed6 Daniel Lobato
def execute(cmd)
197e2dce Ohad Levy
logger.debug "Starting VNC Proxy: #{cmd}"
8bbfa2c3 David Davis
Open3.popen3(cmd) do |stdin, stdout, stderr|
197e2dce Ohad Levy
stdout.each do |line|
logger.debug "[#{line}"
end
stderr.each do |line|
logger.debug "VNCProxy Error: #{line}"
raise PortInUse if line["socket.error: [Errno 98] Address already in use"]
end
end
end
end