81 lines
1.4 KiB
Ruby
81 lines
1.4 KiB
Ruby
|
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
|
||
|
@server.close if @server
|
||
|
@server = nil
|
||
|
@blk = nil
|
||
|
end
|
||
|
|
||
|
protected
|
||
|
|
||
|
def new_accept_thread
|
||
|
server = @server
|
||
|
Thread.new do
|
||
|
done = false
|
||
|
while !done
|
||
|
done = !accept_connection(server)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def accept_connection(server)
|
||
|
socket = nil
|
||
|
begin
|
||
|
socket = server.accept
|
||
|
rescue IOError
|
||
|
# socket was shut down or something catastrophic like that happened
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
start = Time.now
|
||
|
line = ""
|
||
|
|
||
|
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
|
||
|
rescue IOError => e
|
||
|
# nothing to do here, case its normal on shutdown
|
||
|
rescue => e
|
||
|
Rails.logger.warn("Failed to handle connection in stats socket #{e}")
|
||
|
ensure
|
||
|
socket&.close rescue nil
|
||
|
end
|
||
|
|
||
|
def get_response(command)
|
||
|
if @blk
|
||
|
@blk.call(command)
|
||
|
else
|
||
|
raise "Must be implemented by child"
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|