Obsolete
/
libipc-old
Archived
3
0
Fork 0
This repository has been archived on 2024-06-18. You can view files and clone it, but cannot push or open issues/pull-requests.
libipc-old/core/ipc.cr

269 lines
6.3 KiB
Crystal
Raw Normal View History

2018-10-04 12:57:05 +02:00
@[Link("ipc")]
lib LibIPC
struct Service
version : LibC::UInt
index : LibC::UInt
spath : LibC::Char[4096] # [PATH_MAX]
fd : LibC::Int
end
struct Client
version : LibC::UInt
index : LibC::UInt
fd : LibC::Int
end
struct Message
type : LibC::Char
length : LibC::UShort
payload : LibC::Char*
end
2018-10-05 22:57:08 +02:00
struct Clients
2018-10-04 12:57:05 +02:00
clients : Client**
size : LibC::Int
end
# FIXME: IPC.initialize:
# - throw exceptions on error.
# - Make most arguments optional.
2018-10-09 16:36:51 +02:00
fun ipc_server_init(env : LibC::Char**, service : Service*, sname : LibC::Char*) : LibC::Int
2018-10-04 12:57:05 +02:00
# FIXME: IPC.(destroy?)
fun ipc_server_close(Service*) : LibC::Int
fun ipc_server_close_client(Client*) : LibC::Int
fun ipc_server_accept(Service*, Client*) : LibC::Int
fun ipc_server_read(Client*, Message*) : LibC::Int
fun ipc_server_write(Client*, Message*) : LibC::Int
2018-10-05 22:57:08 +02:00
fun ipc_server_select(Clients*, Service*, Clients*, LibC::Int*) : LibC::Int
2018-10-04 12:57:05 +02:00
2018-10-09 16:36:51 +02:00
fun ipc_application_connection(LibC::Char**, Service*, LibC::Char*) : LibC::Int
2018-10-04 22:53:51 +02:00
fun ipc_application_close(Service*) : LibC::Int
fun ipc_application_read(Service*, Message*) : LibC::Int
fun ipc_application_write(Service*, Message*) : LibC::Int
2018-10-05 22:57:08 +02:00
fun ipc_client_add(Clients*, Client*) : LibC::Int
fun ipc_client_del(Clients*, Client*) : LibC::Int
2018-10-04 22:53:51 +02:00
fun ipc_server_client_copy(Client*) : Client*
fun ipc_server_client_eq(Client*, Client*) : LibC::Int
fun ipc_server_client_gen(Client*, LibC::UInt, LibC::UInt)
2018-10-05 22:57:08 +02:00
fun ipc_clients_free(Clients*)
2018-10-04 22:53:51 +02:00
end
class IPC::Exception < ::Exception
2018-10-04 12:57:05 +02:00
end
class IPC::Service
2018-10-04 22:53:51 +02:00
@closed = false
2018-10-05 22:57:08 +02:00
@clients = LibIPC::Clients.new
2018-10-04 12:57:05 +02:00
# FIXME: getter only as long as proper bindings are unfinished
getter service = LibIPC::Service.new
def initialize(name : String)
2018-10-09 16:36:51 +02:00
if LibIPC.ipc_server_init(LibC.environ, pointerof(@service), name) < 0
2018-10-04 22:53:51 +02:00
raise Exception.new "ipc_server_init < 0" # FIXME: Add proper descriptions here.
2018-10-04 12:57:05 +02:00
end
2018-10-04 22:53:51 +02:00
# Very important as there are filesystem side-effects.
at_exit { close }
2018-10-04 12:57:05 +02:00
end
2018-10-11 11:31:48 +02:00
def initialize(name : String, &block : Proc(IPC::Event::Connection | IPC::Event::Disconnection | IPC::Event::Message, Nil))
initialize name
loop &block
close
end
2018-10-04 22:53:51 +02:00
def close
return if @closed
# FIXME: Probably check its not been closed already.
2018-10-04 12:57:05 +02:00
if LibIPC.ipc_server_close(pointerof(@service)) < 0
2018-10-04 22:53:51 +02:00
raise Exception.new "ipc_server_close < 0"
2018-10-04 12:57:05 +02:00
end
2018-10-04 22:53:51 +02:00
@closed = true
end
def finalize
close
end
def accept
2018-10-09 16:36:51 +02:00
::IPC::Server::Client.new pointerof(@service)
2018-10-04 12:57:05 +02:00
end
2018-10-05 22:57:08 +02:00
def loop(&block)
active_clients = LibIPC::Clients.new
anyone_joined = 0_i32
message = LibIPC::Message.new
::loop do
if LibIPC.ipc_server_select(pointerof(@clients), pointerof(@service), pointerof(active_clients), pointerof(anyone_joined)) < 0
raise Exception.new "ipc_server_select < 0"
end
if anyone_joined > 0
client = LibIPC::Client.new
if LibIPC.ipc_server_accept(pointerof(@service), pointerof(client)) < 0
raise Exception.new "ipc_server_accept < 0"
end
if LibIPC.ipc_client_add(pointerof(@clients), pointerof(client)) < 0
raise Exception.new "ipc_client_add < 0"
end
2018-10-09 16:36:51 +02:00
yield ::IPC::Event::Connection.new ::IPC::Server::Client.new client
2018-10-05 22:57:08 +02:00
end
i = 0
while i < active_clients.size
client_pointer = active_clients.clients[i]
return_value = LibIPC.ipc_server_read(client_pointer, pointerof(message))
if return_value < 0
2018-10-05 22:57:08 +02:00
raise Exception.new "ipc_server_read < 0"
elsif return_value == 1
LibIPC.ipc_client_del pointerof(@clients), client_pointer
2018-10-05 22:57:08 +02:00
2018-10-09 16:36:51 +02:00
# FIXME: Should probably not be a new Server::Client. Having unique
# variables helps in using Server::Clients as keys.
yield Event::Disconnection.new Server::Client.new client_pointer.value
2018-10-05 22:57:08 +02:00
else
2018-10-09 16:36:51 +02:00
yield Event::Message.new(IPC::Message.new(message.type, message.length, message.payload), Server::Client.new client_pointer.value)
2018-10-05 22:57:08 +02:00
end
i += 1
end
LibIPC.ipc_clients_free(pointerof(active_clients))
2018-10-05 22:57:08 +02:00
end
close
end
2018-10-04 12:57:05 +02:00
end
2018-10-04 22:53:51 +02:00
class IPC::Message
enum Type
2018-10-09 16:36:51 +02:00
CLOSE
CONNECTION
SYN
ACK
2018-10-04 22:53:51 +02:00
DATA
end
2018-10-04 12:57:05 +02:00
2018-10-04 22:53:51 +02:00
getter type : UInt8
getter payload : String
2018-10-04 12:57:05 +02:00
2018-10-04 22:53:51 +02:00
def initialize(type, length, payload)
@type = type
@payload = String.new payload, length
end
end
2018-10-04 12:57:05 +02:00
2018-10-09 16:36:51 +02:00
class IPC::Server::Client
2018-10-04 22:53:51 +02:00
@closed = false
getter client = LibIPC::Client.new
2018-10-04 12:57:05 +02:00
2018-10-04 22:53:51 +02:00
def initialize(service : LibIPC::Service*)
if LibIPC.ipc_server_accept(service, pointerof(@client)) < 0
raise Exception.new "ipc_server_accept < 0"
end
end
2018-10-05 22:57:08 +02:00
def initialize(@client)
end
2018-10-04 22:53:51 +02:00
def read
message = LibIPC::Message.new
if LibIPC.ipc_server_read(pointerof(@client), pointerof(message)) < 0
raise Exception.new "ipc_server_read < 0"
end
Message.new message.type, message.length, message.payload
end
def send(type : UInt8, payload : String)
message = LibIPC::Message.new type: type, length: payload.size, payload: payload.to_unsafe
if LibIPC.ipc_server_write(pointerof(@client), pointerof(message)) < 0
2018-10-05 22:57:08 +02:00
raise Exception.new "ipc_server_write < 0"
2018-10-04 22:53:51 +02:00
end
end
def close
return if @closed
2018-10-04 12:57:05 +02:00
2018-10-04 22:53:51 +02:00
LibIPC.ipc_server_close_client pointerof(@client)
end
def finalize
close
end
2018-10-04 12:57:05 +02:00
end
2018-10-05 22:57:08 +02:00
class IPC::Event
class Connection
2018-10-09 16:36:51 +02:00
getter client : ::IPC::Server::Client
2018-10-05 22:57:08 +02:00
def initialize(@client)
end
end
2018-10-04 22:53:51 +02:00
2018-10-05 22:57:08 +02:00
class Disconnection
2018-10-09 16:36:51 +02:00
getter client : ::IPC::Server::Client
2018-10-05 22:57:08 +02:00
def initialize(@client)
end
end
class Message
getter message : ::IPC::Message
2018-10-09 16:36:51 +02:00
getter client : ::IPC::Server::Client
2018-10-05 22:57:08 +02:00
def initialize(@message, @client)
end
end
end
2018-10-04 22:53:51 +02:00
2018-10-09 16:36:51 +02:00
class IPC::Client
@service = LibIPC::Service.new
def initialize(@service_name : String)
if LibIPC.ipc_application_connection(LibC.environ, pointerof(@service), @service_name) < 0
raise Exception.new "ipc_application_connection < 0"
end
end
def initialize(name, &block)
initialize(name)
yield self
close
end
def send(type, payload : String)
message = LibIPC::Message.new type: type, length: payload.size, payload: payload.to_unsafe
if LibIPC.ipc_application_write(pointerof(@service), pointerof(message)) < 0
raise Exception.new "ipc_application_write < 0"
end
end
2018-10-05 22:57:08 +02:00
2018-10-09 16:36:51 +02:00
def read
message = LibIPC::Message.new
if LibIPC.ipc_application_read(pointerof(@service), pointerof(message)) < 0
raise Exception.new "ipc_application_read < 0"
end
IPC::Message.new message.type, message.length, message.payload
end
def close
if LibIPC.ipc_application_close(pointerof(@service)) < 0
raise Exception.new "ipc_application_close < 0"
end
2018-10-04 22:53:51 +02:00
end
end
2018-10-04 12:57:05 +02:00