ipcd with new libipc API (v 0.7)
parent
9912ef8a5e
commit
53ed216132
195
src/ipcd.cr
195
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 <in|out> <service> <url>
|
||||
# --allow <in|ou> <service> <url>
|
||||
# --redirect <service> <service>
|
||||
# --redirect <service-name> <new-service-name> <origin-url> <dest-url>
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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(' ')}"
|
Reference in New Issue