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 "./rules"
|
||||||
require "./plumberdcliparser"
|
require "./ipcd_cli_parser"
|
||||||
require "ipc"
|
require "ipc"
|
||||||
require "uri"
|
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
|
# the service name is used unless there is a redirection that is provided to the client through
|
||||||
# a IPC_NETWORK environment variable
|
# 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
|
# parse_lookup_payload extract the right service URI to use from the IPC_NETWORK content
|
||||||
# sent by the client in the form:
|
# sent by the client in the form:
|
||||||
|
@ -36,14 +51,14 @@ class IPC::NetworkD < IPC::Service
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "service: #{service} redirection uri: #{newuri}"
|
Baguette::Log.debug "service: #{service} redirection uri: #{newuri}"
|
||||||
uri = URI.parse newuri
|
uri = URI.parse newuri
|
||||||
services_redirections[service] = uri
|
services_redirections[service] = uri
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
services_redirections.each do |k, v|
|
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
|
if k == requested_service_name
|
||||||
requested_service = v
|
requested_service = v
|
||||||
end
|
end
|
||||||
|
@ -53,128 +68,106 @@ class IPC::NetworkD < IPC::Service
|
||||||
end
|
end
|
||||||
|
|
||||||
# XXX: WIP
|
# XXX: WIP
|
||||||
def service_lookup (message : IPC::Message, origin : IPC::Connection)
|
def service_lookup (message : IPC::Message, fd : Int32)
|
||||||
payload = String.new message.payload
|
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
|
scheme = requested_service.scheme
|
||||||
begin
|
if scheme.nil?
|
||||||
scheme = requested_service.scheme
|
raise "no SCHEME in redirection"
|
||||||
if scheme.nil?
|
end
|
||||||
raise "no SCHEME in redirection"
|
|
||||||
end
|
|
||||||
|
|
||||||
service_name = scheme
|
service_name = scheme
|
||||||
if scheme == "unix"
|
if scheme == "unix"
|
||||||
# scheme == unix => simple redirection
|
# scheme == unix => simple redirection
|
||||||
|
|
||||||
# the URI is "unix:///service" so the path is "/service"
|
# the URI is "unix:///service" so the path is "/service"
|
||||||
# first, remove its slash prefix
|
# first, remove its slash prefix
|
||||||
service_name = requested_service.path.lchop
|
service_name = requested_service.path.lchop
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "service name: #{service_name}"
|
Baguette::Log.info "service name: #{service_name}"
|
||||||
service = IPC::Connection.new 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
|
# TODO: for remote services, we have to connect to communication service
|
||||||
# these communication services need an URI to work on
|
# these communication services need an URI to work on
|
||||||
# The protocol:
|
# The protocol:
|
||||||
# plumberd sends an URI to the communication service, which responds with a "OK" message
|
# ipcd sends an URI to the communication service, which responds with a "OK" message
|
||||||
if scheme != "unix"
|
if scheme != "unix"
|
||||||
service.send 1.to_u8, "#{requested_service.to_s}\n"
|
service.send service_fd, 1.to_u8, "#{requested_service.to_s}\n"
|
||||||
response = service.read
|
response = service.read
|
||||||
payload = String.new response.payload
|
payload = String.new response.payload
|
||||||
if payload.chomp != "OK"
|
if payload.chomp != "OK"
|
||||||
raise "service #{service_name} response was #{payload.chomp}"
|
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"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def wait_event(server : IPC::Connection?, &block) : Tuple(LibIPC::EventType, IPC::Message, IPC::Connection)
|
# Then we provide the file descriptor to the client
|
||||||
event = LibIPC::Event.new
|
r = LibIPC.ipc_provide_fd(fd, service_fd)
|
||||||
|
|
||||||
# TODO: plumberd should be able to transfer messages???
|
|
||||||
r = LibIPC.ipc_wait_event self.pointer, @service_info.pointer, pointerof(event), pointerof(@timer)
|
|
||||||
if r.error_code != 0
|
if r.error_code != 0
|
||||||
m = String.new r.error_message
|
m = String.new r.error_message.to_slice
|
||||||
yield IPC::Exception.new "error waiting for a new event: #{m}"
|
raise Exception.new "cannot send the file descriptor of the requested service: #{m}"
|
||||||
end
|
end
|
||||||
|
|
||||||
connection = IPC::Connection.new event.origin.unsafe_as(Pointer(LibIPC::Connection)).value
|
# finally, the service should be closed in ipcd
|
||||||
message = event.message.unsafe_as(Pointer(LibIPC::Message))
|
service.close
|
||||||
|
|
||||||
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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
ipcd = IPCd::Service.new "network"
|
||||||
plumberd = NetworkD.new "plumber"
|
|
||||||
|
|
||||||
# --deny <in|out> <service> <url>
|
# --deny <in|out> <service> <url>
|
||||||
# --allow <in|ou> <service> <url>
|
# --allow <in|ou> <service> <url>
|
||||||
# --redirect <service> <service>
|
# --redirect <service> <service>
|
||||||
# --redirect <service-name> <new-service-name> <origin-url> <dest-url>
|
# --redirect <service-name> <new-service-name> <origin-url> <dest-url>
|
||||||
|
|
||||||
plumberd.parse_cli ARGV
|
ipcd.parse_cli ARGV
|
||||||
puts plumberd.to_s
|
Baguette::Log.debug ipcd.to_s
|
||||||
|
|
||||||
plumberd.loop do |event|
|
ipcd.base_timer = 30_000
|
||||||
puts "there is an event!"
|
ipcd.timer = 30_000
|
||||||
|
|
||||||
|
ipcd.loop do |event|
|
||||||
case event
|
case event
|
||||||
when IPC::Event::Connection
|
when IPC::Event::Connection
|
||||||
puts "\033[32mConnection:\033[00m fd #{event.connection.fd}"
|
Baguette::Log.debug "Connection: fd #{event.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
|
|
||||||
|
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
class NetworkDCLIParser
|
class IPCdCLIParser
|
||||||
def self.pack_args (argv : Array(String))
|
def self.pack_args (argv : Array(String))
|
||||||
last_flag = nil : String?
|
last_flag = nil : String?
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class NetworkDCLIParser
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.parse_rules (argv : Array(String), rules : RuleSet, redirections : RedirectionSet)
|
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|
|
args.each do |flag, parameters|
|
||||||
# puts "flag: #{flag}, params: #{parameters.join(' ')}"
|
# puts "flag: #{flag}, params: #{parameters.join(' ')}"
|
Reference in New Issue