diff --git a/makefile b/makefile index f873b93..af956e7 100644 --- a/makefile +++ b/makefile @@ -4,9 +4,12 @@ OPTS ?= --progress Q ?= @ bin/ipcd: src/ipcd.cr - $(Q)shards build $(OPTS) + $(Q)shards build ipcd $(OPTS) -build: bin/ipcd +bin/ipcproxy: src/ipcproxy.cr + $(Q)shards build ipcproxy $(OPTS) + +build: bin/ipcd bin/ipcproxy release: $(Q)make build OPTS="--release --progress --no-debug" diff --git a/shard.yml b/shard.yml index 2f7f902..007c500 100644 --- a/shard.yml +++ b/shard.yml @@ -8,6 +8,9 @@ targets: ipcd: main: src/ipcd.cr + ipcproxy: + main: src/ipcproxy.cr + dependencies: ipc: git: https://git.baguette.netlib.re/Baguette/ipc.cr diff --git a/src/ipcproxy.cr b/src/ipcproxy.cr new file mode 100644 index 0000000..67a917f --- /dev/null +++ b/src/ipcproxy.cr @@ -0,0 +1,101 @@ +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}" + + 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 fn_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) + + hexa = Hexa.new 50_000 + bytes = Bytes.new buffer, buflen.value + puts hexa.dump "message received from #{fd}", bytes + + 0_u8 +rescue e + puts "fn_input exception! #{e}" + 1_u8 +end + +def fn_output(fd : LibC::Int, buffer : LibC::Char*, buflen : LibC::UInt64T) : LibC::Char + hexa = Hexa.new 50_000 + bytes = Bytes.new buffer, buflen + puts hexa.dump "message to send to #{fd}", bytes + + slice = Bytes.new buffer, buflen + io = IO::FileDescriptor.new fd, close_on_finalize: false + io.write slice + io.flush + 0_u8 +rescue e + puts "fn_output exception! #{e}" + 1_u8 +end + +IPCProxy.start