This commit is contained in:
Jesse Sanford 2017-04-23 13:57:56 +00:00 committed by GitHub
commit 9d92c13634
2 changed files with 186 additions and 24 deletions

View File

@ -49,6 +49,10 @@ Sec-WebSocket-Accept: %s\r
def initialize(opts)
@verbose = opts['verbose']
@opts = opts
@@client_id = 0 # Track client number total on class
vmsg "in WebSocketServer.initialize"
port = opts['listen_port']
host = opts['listen_host'] || GServer::DEFAULT_HOST
@ -64,11 +68,6 @@ Sec-WebSocket-Accept: %s\r
@sslContext.verify_mode = OpenSSL::SSL::VERIFY_NONE
@sslContext.verify_depth = 0
end
@@client_id = 0 # Track client number total on class
@verbose = opts['verbose']
@opts = opts
end
def serve(io)
@ -117,7 +116,7 @@ Sec-WebSocket-Accept: %s\r
end
def msg(m)
printf("% 3d: %s\n", Thread.current[:my_client_id] || 0, m)
log sprintf("% 3d: %s\n", Thread.current[:my_client_id] || 0, m)
end
def vmsg(m)

View File

@ -9,12 +9,15 @@ $: << "other"
$: << "../other"
require 'websocket'
require 'optparse'
require 'fileutils'
# Proxy traffic to and from a WebSockets client to a normal TCP
# socket server target. All traffic to/from the client is base64
# encoded/decoded to allow binary data to be sent/received to/from
# the target.
class WebSocketProxy < WebSocketServer
attr_accessor 'target_host', 'target_port'
attr_reader :opts, :quit
@@Traffic_legend = "
Traffic Legend:
@ -31,20 +34,150 @@ Traffic Legend:
def initialize(opts)
vmsg "in WebSocketProxy.initialize"
super(opts)
@opts = opts
@target_host = opts["target_host"]
@target_port = opts["target_port"]
super(opts)
@target_host = opts['target_host']
@target_port = opts['target_port']
#replace the logfile option with the expanded path
opts[:logfile] = File.expand_path(logfile) if logfile?
opts[:pidfile] = File.expand_path(pidfile) if pidfile?
end
def daemonize?
opts[:daemonize]
end
# Echo back whatever is received
def logfile
opts[:logfile]
end
def pidfile
opts[:pidfile]
end
def logfile?
!logfile.nil?
end
def pidfile?
!pidfile.nil?
end
def write_pid
if pidfile?
begin
File.open(pidfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY){|f| f.write("#{Process.pid}") }
at_exit { File.delete(pidfile) if File.exists?(pidfile) }
rescue Errno::EEXIST
check_pid
retry
end
end
end
def check_pid
if pidfile?
case pid_status(pidfile)
when :running, :not_owned
log "A server is already running. Check #{pidfile}"
exit(1)
when :dead
File.delete(pidfile)
end
end
end
def pid_status(pidfile)
return :exited unless File.exists?(pidfile)
pid = ::File.read(pidfile).to_i
return :dead if pid == 0
Process.kill(0, pid) # check process status
:running
rescue Errno::ESRCH
:dead
rescue Errno::EPERM
:not_owned
end
def redirect_output
FileUtils.mkdir_p(File.dirname(logfile), :mode => 0755)
FileUtils.touch logfile
File.chmod(0644, logfile)
$stderr.reopen(logfile, 'a')
$stdout.reopen($stderr)
$stdout.sync = $stderr.sync = true
end
def suppress_output
$stderr.reopen('/dev/null', 'a')
$stdout.reopen($stderr)
end
def trap_signals
trap(:QUIT) do # kill -9
log "Hard killing websockify server..."
stop
log "Bye!"
end
trap(:TERM) do # kill -15
log "Gracefully shutting down websockify server..."
Thread.new { shutdown; exit }
log "Bye!"
end
end
def daemonize
exit if fork
Process.setsid
exit if fork
Dir.chdir "/"
end
def run!(max_connections)
check_pid
daemonize if daemonize?
write_pid
trap_signals
if logfile?
redirect_output
elsif daemonize?
suppress_output
end
log "Starting Websockify server on #{opts['listen_host']}:#{opts['listen_port']} and proxying to #{target_host}:#{target_port}"
#tell gserver to start
start(max_connections)
#join the gserver thread to this one
join
end
# Echo back whatever is received
def new_websocket_client(client)
path = Thread.current[:path]
msg "path = #{path}"
if path =~ /:/
msg "path has a ip and port"
possible_target_host = path[/(\d+\.\d+\.\d+\.\d+):(\d+)/,1]
possible_target_port = path[/(\d+\.\d+\.\d+\.\d+):(\d+)/,2].to_i
end
Thread.current[:path] = "/"
if possible_target_host and possible_target_port
@target_host = possible_target_host
@target_port = possible_target_port
end
msg "connecting to: %s:%s" % [@target_host, @target_port]
tsock = TCPSocket.open(@target_host, @target_port)
if @verbose then puts @@Traffic_legend end
if @verbose then log @@Traffic_legend end
begin
do_proxy(client, tsock)
@ -122,14 +255,48 @@ Traffic Legend:
end
# Parse parameters
opts = {}
parser = OptionParser.new do |o|
o.on('--verbose', '-v') { |b| opts['verbose'] = b }
o.parse!
end
opts = {}
version = "1.0.0"
maxcon_help = "maximum number of connections allowed"
daemonize_help = "run daemonized in the background (default: false)"
pidfile_help = "the pid filename"
logfile_help = "the log filename"
include_help = "an additional $LOAD_PATH"
debug_help = "set $DEBUG to true"
warn_help = "enable warnings"
usage = "Usage: server list_port target_host'target_port' [options]"
op = OptionParser.new
op.banner = "Websockify Server #{version}"
op.separator ""
op.separator "#{usage}"
op.separator ""
op.separator "Process options:"
op.on("-m", "--maxcon NUMBER", maxcon_help) { |value| opts[:maxcon] = value || 100 }
op.on("-d", "--daemonize", daemonize_help) { opts[:daemonize] = true }
op.on("-p", "--pid PIDFILE", pidfile_help) { |value| opts[:pidfile] = value }
op.on("-l", "--log LOGFILE", logfile_help) { |value| opts[:logfile] = value }
op.separator ""
op.separator "Ruby options:"
op.on("-I", "--include PATH", include_help) { |value| $LOAD_PATH.unshift(*value.split(":").map{|v| File.expand_path(v)}) }
op.on( "--debug", debug_help) { $DEBUG = true }
op.on( "--warn", warn_help) { $-w = true }
op.separator ""
op.separator "Common options:"
op.on("-h", "--help") { puts op.to_s; exit }
op.on("-V", "--version") { puts version; exit }
op.on("-v", "--verbose") { |value| opts['verbose'] = true }
op.separator ""
op.parse!(ARGV)
if ARGV.length < 2
puts "Too few arguments"
puts "Too few arguments."
puts op.to_s
exit 2
end
@ -137,7 +304,7 @@ end
if ARGV[0].count(":") > 0
opts['listen_host'], _, opts['listen_port'] = ARGV[0].rpartition(':')
else
opts['listen_host'], opts['listen_port'] = nil, ARGV[0]
opts['listen_host'], opts['listen_port'] = '0.0.0.0', ARGV[0]
end
begin
@ -161,11 +328,7 @@ rescue
exit 2
end
puts "Starting server on #{opts['listen_host']}:#{opts['listen_port']}"
server = WebSocketProxy.new(opts)
server.start(100)
server.join
puts "Server has been terminated"
server.run!(opts[:maxcon].to_i)
# vim: sw=2