ipcd/src/ipcproxy.cr

126 lines
3.3 KiB
Crystal

require "ipc"
require "hexa"
# TODO: Write documentation for `IPCProxy`
module IPCProxy
VERSION = "0.1.0"
@@proxy_name = "proxy"
@@proxied_service = "pong"
def self.start
@@proxied_service = ARGV[0] if ARGV.size >= 1
@@proxy_name = ARGV[1] if ARGV.size >= 2
puts "proxy named #{@@proxy_name} for service #{@@proxied_service}"
puts "removing keepalive messages"
ipc_proxy = IPC.new()
ipc_proxy.service_init @@proxy_name
ipc_proxy.timer 10_000
timer = 0
ipc_proxy.loop do |event|
begin
case event.type
when LibIPC::EventType::Timer
STDOUT.write "Timer #{timer}.\r".to_slice
STDOUT.flush
timer += 1
when LibIPC::EventType::Connection
fd = ipc_proxy.connect @@proxied_service
ipc_proxy.add_switch event.newfd, fd
input = -> fn_input( LibC::Int, LibC::Char*, LibC::UInt64T*)
output = -> fn_output(LibC::Int, LibC::Char*, LibC::UInt64T )
ipc_proxy.switch_callbacks event.newfd, input, output
puts "New connection (#{event.newfd}) now automatically switched to '#{@@proxied_service}' (#{fd})!"
when LibIPC::EventType::Disconnection
puts "Disconnection from #{event.fd}."
when LibIPC::EventType::MessageTx
puts "Message sent to #{event.fd}."
when LibIPC::EventType::MessageRx
puts "Message received from #{event.fd}."
when LibIPC::EventType::SwitchRx
#puts "Switch message received from #{event.fd}."
when LibIPC::EventType::SwitchTx
#puts "Switch message sent to #{event.fd}."
when LibIPC::EventType::Error
puts "And error occured on fd #{event.fd}."
else
puts "Unhandled IPC event: #{event.class}."
if event.responds_to?(:fd)
puts "closing #{event.fd}"
ipc_proxy.close event.fd
end
end
rescue exception
puts "exception: #{typeof(exception)} - #{exception.message}"
end
end
end
end
def read_input(fd : LibC::Int, buffer : LibC::Char*, buflen : LibC::UInt64T*) : LibC::Char
io = IO::FileDescriptor.new fd, close_on_finalize: false
slice = Bytes.new buffer, buflen.value
len = io.read slice
buflen.value = len.to_u64
return 2_u8 if (len == 0)
0_u8
rescue e
puts "read_input exception! #{e}"
1_u8
end
def keepalive?(buffer : LibC::Char*) : Bool
return (buffer[4] == 250)
end
def print_hexa(buffer : LibC::Char*, buflen : LibC::UInt64T, title : String)
hexa = Hexa.new 50_000
bytes = Bytes.new buffer, buflen
puts hexa.dump title, bytes
end
def fn_input(fd : LibC::Int, buffer : LibC::Char*, buflen : LibC::UInt64T*) : LibC::Char
# First, get the content.
ret = read_input fd, buffer, buflen
return ret if ret != 0
# Second, is this a keepalive message?
return ret if keepalive? buffer
# Finally, print an hexadecimal presentation of the content.
print_hexa buffer, buflen.value, "message received from #{fd}"
ret
end
def write_output(fd : LibC::Int, buffer : LibC::Char*, buflen : LibC::UInt64T) : LibC::Char
slice = Bytes.new buffer, buflen
io = IO::FileDescriptor.new fd, close_on_finalize: false
io.write slice
io.flush
0_u8
rescue e
puts "write_output exception! #{e}"
1_u8
end
def fn_output(fd : LibC::Int, buffer : LibC::Char*, buflen : LibC::UInt64T) : LibC::Char
unless keepalive? buffer
print_hexa buffer, buflen, "message to send to #{fd}"
end
write_output fd, buffer, buflen
end
IPCProxy.start