diff --git a/src/ipcd.cr b/src/ipcd.cr index 9d162f7..a095940 100644 --- a/src/ipcd.cr +++ b/src/ipcd.cr @@ -1,15 +1,30 @@ +require "baguette-crystal-base" require "./rules" -require "./plumberdcliparser" +require "./ipcd_cli_parser" require "ipc" require "uri" -class IPC::NetworkD < IPC::Service +Baguette::Context.verbosity = 4 - # The client asks to plumberd to open a connection to a service +class IPCd::Service < IPC::Server + + @rules = RuleSet.new + @redirections = RedirectionSet.new + + def parse_cli (argv : Array(String)) + IPCdCLIParser.parse_rules argv, @rules, @redirections + end + + def to_s(io : IO) + io << "ipcd\n" + io << @rules.to_s + "\n" + @redirections.to_s + end + + # The client asks to ipcd to open a connection to a service # the service name is used unless there is a redirection that is provided to the client through # a IPC_NETWORK environment variable - # This environment variable is sent from the client to plumberd, that's what is parsed here + # This environment variable is sent from the client to ipcd, that's what is parsed here # parse_lookup_payload extract the right service URI to use from the IPC_NETWORK content # sent by the client in the form: @@ -36,14 +51,14 @@ class IPC::NetworkD < IPC::Service next end - puts "service: #{service} redirection uri: #{newuri}" + Baguette::Log.debug "service: #{service} redirection uri: #{newuri}" uri = URI.parse newuri services_redirections[service] = uri end end services_redirections.each do |k, v| - puts "\033[36mpossible redirection (from env. var.):\033[00m service: #{k} uri: #{v}" + Baguette::Log.debug "possible redirection (from env. var.): service: #{k} uri: #{v}" if k == requested_service_name requested_service = v end @@ -53,128 +68,106 @@ class IPC::NetworkD < IPC::Service end # XXX: WIP - def service_lookup (message : IPC::Message, origin : IPC::Connection) + def service_lookup (message : IPC::Message, fd : Int32) payload = String.new message.payload - requested_service = IPC::NetworkD.parse_lookup_payload payload + requested_service = IPCd::Service.parse_lookup_payload payload - # TODO: connect to the service then provide the file descriptor to the client - begin - scheme = requested_service.scheme - if scheme.nil? - raise "no SCHEME in redirection" - end + scheme = requested_service.scheme + if scheme.nil? + raise "no SCHEME in redirection" + end - service_name = scheme - if scheme == "unix" - # scheme == unix => simple redirection + service_name = scheme + if scheme == "unix" + # scheme == unix => simple redirection - # the URI is "unix:///service" so the path is "/service" - # first, remove its slash prefix - service_name = requested_service.path.lchop - end + # the URI is "unix:///service" so the path is "/service" + # first, remove its slash prefix + service_name = requested_service.path.lchop + end - puts "service name: #{service_name}" - service = IPC::Connection.new service_name + Baguette::Log.info "service name: #{service_name}" + service = IPC::Client.new service_name + service_fd = service.fd.not_nil! - # TODO: for remote services, we have to connect to communication service - # these communication services need an URI to work on - # The protocol: - # plumberd sends an URI to the communication service, which responds with a "OK" message - if scheme != "unix" - service.send 1.to_u8, "#{requested_service.to_s}\n" - response = service.read - payload = String.new response.payload - if payload.chomp != "OK" - raise "service #{service_name} response was #{payload.chomp}" - end - end - - # Then we provide the file descriptor to the client - r = LibIPC.ipc_provide_fd(origin.fd, service.fd) - if r.error_code != 0 - m = String.new r.error_message - raise Exception.new "cannot send the file descriptor of the requested service: #{m}" - end - - # finally, the service should be closed in plumberd - service.close - rescue e - puts "\033[31mException during the connection to the requested service #{requested_service}: #{e}\033[00m" - # when a problem occurs, close the client connection - - begin - # LibIPC.ipc_connections_print pointerof(@connections) - remove_fd origin.fd - - origin.close - - rescue ex - puts "\033[31mException during a client removal: #{ex}\033[00m" + # TODO: for remote services, we have to connect to communication service + # these communication services need an URI to work on + # The protocol: + # ipcd sends an URI to the communication service, which responds with a "OK" message + if scheme != "unix" + service.send service_fd, 1.to_u8, "#{requested_service.to_s}\n" + response = service.read + payload = String.new response.payload + if payload.chomp != "OK" + raise "service #{service_name} response was #{payload.chomp}" end end - end - def wait_event(server : IPC::Connection?, &block) : Tuple(LibIPC::EventType, IPC::Message, IPC::Connection) - event = LibIPC::Event.new - - # TODO: plumberd should be able to transfer messages??? - r = LibIPC.ipc_wait_event self.pointer, @service_info.pointer, pointerof(event), pointerof(@timer) + # Then we provide the file descriptor to the client + r = LibIPC.ipc_provide_fd(fd, service_fd) if r.error_code != 0 - m = String.new r.error_message - yield IPC::Exception.new "error waiting for a new event: #{m}" + m = String.new r.error_message.to_slice + raise Exception.new "cannot send the file descriptor of the requested service: #{m}" end - connection = IPC::Connection.new event.origin.unsafe_as(Pointer(LibIPC::Connection)).value - message = event.message.unsafe_as(Pointer(LibIPC::Message)) - - return event.type, IPC::Message.new(message), connection - end -end - -class NetworkD < IPC::NetworkD - @rules = RuleSet.new - @redirections = RedirectionSet.new - - def parse_cli (argv : Array(String)) - NetworkDCLIParser.parse_rules argv, @rules, @redirections - end - - def to_s - @rules.to_s + "\n" + @redirections.to_s + # finally, the service should be closed in ipcd + service.close end end - -plumberd = NetworkD.new "plumber" +ipcd = IPCd::Service.new "network" # --deny # --allow # --redirect # --redirect -plumberd.parse_cli ARGV -puts plumberd.to_s +ipcd.parse_cli ARGV +Baguette::Log.debug ipcd.to_s -plumberd.loop do |event| - puts "there is an event!" +ipcd.base_timer = 30_000 +ipcd.timer = 30_000 + +ipcd.loop do |event| case event when IPC::Event::Connection - puts "\033[32mConnection:\033[00m fd #{event.connection.fd}" - when IPC::Event::Disconnection - puts "\033[32mDisconnection:\033[00m fd #{event.connection.fd}" - when IPC::Event::ExtraSocket - puts "\033[32mExtrasocket:\033[00m fd #{event.connection.fd}" - when IPC::Event::Switch - puts "\033[31mSwitch\033[00m" - when IPC::Exception - puts "\033[31mException\033[00m" - when IPC::Event::Message - puts "\033[32mthere is a message\033[00m" - puts event.message.to_s + Baguette::Log.debug "Connection: fd #{event.fd}" - plumberd.service_lookup event.message, event.connection + when IPC::Event::Disconnection + Baguette::Log.debug "Disconnection: fd #{event.fd}" + + when IPC::Event::ExtraSocket + Baguette::Log.debug "Extrasocket: fd #{event.fd}" + + when IPC::Event::Switch + Baguette::Log.debug "Switch" + + when IPC::Event::MessageReceived + Baguette::Log.debug "Message received: #{event.fd}" + Baguette::Log.debug event.message.to_s + begin + ipcd.service_lookup event.message, event.fd + rescue e + Baguette::Log.error "#{e}" + # when a problem occurs, close the client connection + begin + # LibIPC.ipc_connections_print pointerof(@connections) + ipcd.remove_fd event.fd + rescue e + Baguette::Log.error "Exception during a client removal: #{e}" + end + end + + when IPC::Event::MessageSent + Baguette::Log.debug "Message sent: #{event.fd}" + + when IPC::Event::Timer + Baguette::Log.debug "Timer" + + when IPC::Exception + Baguette::Log.debug "IPC::Exception: #{event}" end end diff --git a/src/plumberdcliparser.cr b/src/ipcd_cli_parser.cr similarity index 92% rename from src/plumberdcliparser.cr rename to src/ipcd_cli_parser.cr index 95c7c9e..f801348 100644 --- a/src/plumberdcliparser.cr +++ b/src/ipcd_cli_parser.cr @@ -1,5 +1,5 @@ -class NetworkDCLIParser +class IPCdCLIParser def self.pack_args (argv : Array(String)) last_flag = nil : String? @@ -13,7 +13,7 @@ class NetworkDCLIParser end def self.parse_rules (argv : Array(String), rules : RuleSet, redirections : RedirectionSet) - args = NetworkDCLIParser.pack_args argv + args = IPCdCLIParser.pack_args argv args.each do |flag, parameters| # puts "flag: #{flag}, params: #{parameters.join(' ')}"