2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-04-25 12:12:39 -04:00
|
|
|
require 'socket'
|
|
|
|
|
|
|
|
class SocketServer
|
|
|
|
|
|
|
|
def initialize(socket_path)
|
|
|
|
@socket_path = socket_path
|
|
|
|
@server = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def start(&blk)
|
|
|
|
@server = UNIXServer.new(@socket_path)
|
|
|
|
@accept_thread = new_accept_thread
|
|
|
|
if blk
|
|
|
|
@blk = blk
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def stop
|
2018-03-28 04:20:08 -04:00
|
|
|
@server&.close
|
2017-05-15 07:47:40 -04:00
|
|
|
FileUtils.rm_f(@socket_path)
|
2017-04-25 12:12:39 -04:00
|
|
|
@server = nil
|
|
|
|
@blk = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def new_accept_thread
|
|
|
|
server = @server
|
|
|
|
Thread.new do
|
2017-05-15 07:47:40 -04:00
|
|
|
begin
|
|
|
|
done = false
|
|
|
|
while !done
|
|
|
|
done = !accept_connection(server)
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
self.stop
|
|
|
|
Rails.logger.info("Cleaned up socket server at #{@socket_path}")
|
2017-04-25 12:12:39 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def accept_connection(server)
|
|
|
|
socket = nil
|
|
|
|
begin
|
|
|
|
socket = server.accept
|
2017-05-04 15:50:35 -04:00
|
|
|
rescue IOError, Errno::EPIPE
|
2017-04-25 12:12:39 -04:00
|
|
|
# socket was shut down or something catastrophic like that happened
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
start = Time.now
|
2019-05-02 18:17:27 -04:00
|
|
|
line = +""
|
2017-04-25 12:12:39 -04:00
|
|
|
|
|
|
|
while Time.now - start < 10
|
|
|
|
if IO.select([socket], nil, nil, 10)
|
|
|
|
begin
|
|
|
|
line << socket.read_nonblock(1000)
|
|
|
|
rescue IO::WaitReadable
|
|
|
|
sleep 0.001
|
|
|
|
end
|
|
|
|
end
|
|
|
|
break if line.include?("\n")
|
|
|
|
end
|
|
|
|
|
|
|
|
if line.include?("\n")
|
|
|
|
socket.write get_response(line.strip)
|
|
|
|
end
|
|
|
|
|
|
|
|
true
|
2017-05-04 15:50:35 -04:00
|
|
|
rescue IOError, Errno::EPIPE
|
2017-04-25 12:12:39 -04:00
|
|
|
# nothing to do here, case its normal on shutdown
|
|
|
|
rescue => e
|
2018-09-18 21:11:10 -04:00
|
|
|
Rails.logger.warn("Failed to handle connection #{e}:\n#{e.backtrace.join("\n")}")
|
2017-04-25 12:12:39 -04:00
|
|
|
ensure
|
2018-03-28 04:20:08 -04:00
|
|
|
socket&.close
|
2017-04-25 12:12:39 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def get_response(command)
|
|
|
|
if @blk
|
|
|
|
@blk.call(command)
|
|
|
|
else
|
|
|
|
raise "Must be implemented by child"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|