Archived
3
0

v0.2 - new API

This commit is contained in:
Philippe PITTOLI 2019-07-27 15:29:27 +02:00
parent dab7e4adec
commit 0330f384ef
10 changed files with 628 additions and 371 deletions

View File

@ -1,7 +1,8 @@
name: ipc name: ipc
version: 0.1.0 version: 0.2.0
authors: authors:
- Philippe Pittoli <karchnu@karchnu.fr>
- Luka Vandervelden <lukc@upyum.com> - Luka Vandervelden <lukc@upyum.com>
description: | description: |
@ -10,4 +11,4 @@ description: |
libraries: libraries:
libipc: ">= 0.1" libipc: ">= 0.1"
license: MIT license: ISC

View File

@ -1,371 +1,11 @@
# TODO: more typing stuff. # TODO: more typing stuff.
# Functions return enum error not just int, for instance. # Functions return enum error not just int, for instance.
@[Link("ipc")] require "./ipc/lowlevel.cr"
lib LibIPC require "./ipc/exception.cr"
struct Connection require "./ipc/message.cr"
version : LibC::UInt require "./ipc/connection.cr"
index : LibC::UInt require "./ipc/event.cr"
fd : LibC::Int require "./ipc/client.cr"
type : UInt8 require "./ipc/service.cr"
spath : LibC::Char* # [4096] # [PATH_MAX] require "./ipc/switch.cr"
end
struct Connections
cinfos : Connection**
size : LibC::Int
end
enum Errors
None = 0
NotEnoughMemory
ClosedRecipient
ServerInitNoEnvironmentParam
ServerInitNoServiceParam
ServerInitNoServerNameParam
ServerInitMalloc
ConnectionNoServer
ConnectionNoServiceName
ConnectionNoEnvironmentParam
ConnectionGenNoCinfo
AcceptNoServiceParam
AcceptNoClientParam
Accept
HandleNewConnectionNoCinfoParam
HandleNewConnectionNoCinfosParam
WaitEventSelect
WaitEventNoClientsParam
WaitEventNoEventParam
HandleNewConnectionMalloc
AddEmptyList
AddNoParamClients
AddNoParamClient
AddFdNoParamCinfos
DelEmptyList
DelEmptiedList
DelCannotFindClient
DelNoClientsParam
DelNoClientParam
UsockSend
UsockConnectSocket
UsockConnectWrongFileDescriptor
UsockConnectEmptyPath
UsockClose
UsockRemoveUnlink
UsockRemoveNoFile
UsockInitEmptyFileDescriptor
UsockInitWrongFileDescriptor
UsockInitEmptyPath
UsockInitBind
UsockInitListen
UsockAcceptPathFileDescriptor
UsockAccept
UsockRecvNoBuffer
UsockRecvNoLength
UsockRecv
MessageNewNoMessageParam
MessageReadNomessageparam
MessageWriteNoMessageParam
MessageWriteNotEnoughData
MessageFormatNoMessageParam
MessageFormatInconsistentParams
MessageFormatLength
MessageFormatWriteEmptyMessage
MessageFormatWriteEmptyMsize
MessageFormatWriteEmptyBuffer
MessageFormatReadEmptyMessage
MessageFormatReadEmptyBuffer
MessageFormatReadMessageSize
MessageEmptyEmptyMessageList
end
enum MessageType
ServerClose
Error
Data
end
struct Message
type : UInt8
user_type : UInt8
length : LibC::UInt
payload : LibC::Char*
end
enum EventType
NotSet
Error
ExtraSocket
Connection
Disconnection
Message
end
struct Event
type : EventType
origin : Connection*
message : Message*
end
fun ipc_server_init(env : LibC::Char**, connection : Connection*, sname : LibC::Char*) : LibC::Int
fun ipc_server_close(Connection*) : LibC::Int
fun ipc_close(Connection*) : LibC::Int
# connection to a service
fun ipc_connection(LibC::Char**, Connection*, LibC::Char*) : LibC::Int
fun ipc_read(Connection*, Message*) : LibC::Int
fun ipc_write(Connection*, Message*) : LibC::Int
fun ipc_wait_event(Connections*, Connection*, Event*) : LibC::Int
fun ipc_add(Connections*, Connection*) : LibC::Int
fun ipc_del(Connections*, Connection*) : LibC::Int
fun ipc_add_fd (Connections*, LibC::Int) : LibC::Int
fun ipc_connection_copy(Connection*) : Connection*
fun ipc_connection_eq(Connection*, Connection*) : LibC::Int
fun ipc_connection_gen(Connection*, LibC::UInt, LibC::UInt)
fun ipc_connections_free(Connections*)
fun ipc_get(Connections*)
fun ipc_errors_get (LibC::Int) : LibC::Char*
end
class IPC::Exception < ::Exception
end
class IPC::Message
getter mtype : UInt8 # libipc message type
getter type : UInt8 # libipc user message type
getter payload : Bytes
def initialize(message : Pointer(LibIPC::Message))
if message.null?
@mtype = LibIPC::MessageType::Error.to_u8
@type = 0
@payload = Bytes.new "".to_unsafe, 0
else
m = message.value
@mtype = m.type
@type = m.user_type
@payload = Bytes.new m.payload, m.length
end
end
def initialize(mtype, type, payload : Bytes)
@mtype = mtype.to_u8
@type = type
@payload = payload
end
def initialize(mtype, type, payload : String)
initialize(mtype, type, Bytes.new(payload.to_unsafe, payload.bytesize))
end
end
class IPC::Event
class Connection
getter connection : IPC::Connection
def initialize(@connection)
end
end
class Disconnection
getter connection : IPC::Connection
def initialize(@connection)
end
end
class Message
getter message : ::IPC::Message
getter connection : IPC::Connection
def initialize(@message, @connection)
end
end
class ExtraSocket < IPC::Event::Message
end
end
class IPC::Connection
getter connection : LibIPC::Connection
getter closed = false
# connection already established
def initialize(c : LibIPC::Connection)
@connection = c
end
def initialize(service_name : String)
@connection = LibIPC::Connection.new
r = LibIPC.ipc_connection(LibC.environ, pointerof(@connection), service_name)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "error during connection establishment: #{m}"
end
end
def initialize(name, &block)
initialize(name)
yield self
close
end
def send(type : UInt8, payload : Bytes)
message = LibIPC::Message.new type: LibIPC::MessageType::Data.to_u8, user_type: type, length: payload.bytesize, payload: payload.to_unsafe
r = LibIPC.ipc_write(pointerof(@connection), pointerof(message))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "error writing a message: #{m}"
end
end
def send(type : UInt8, payload : String)
send(type, Bytes.new(payload.to_unsafe, payload.bytesize))
end
def send(message : IPC::Message)
send(message.type, message.payload)
end
def read
message = LibIPC::Message.new
r = LibIPC.ipc_read(pointerof(@connection), pointerof(message))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "error reading a message: #{m}"
end
IPC::Message.new pointerof(message)
end
def close
return if @closed
r = LibIPC.ipc_close(pointerof(@connection))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot correctly close the connection: #{m}"
end
@closed = true
end
end
alias Events = IPC::Event::Connection | IPC::Event::Disconnection | IPC::Event::Message | IPC::Event::ExtraSocket
class IPC::Service
@closed = false
@connections = LibIPC::Connections.new
@service_info = LibIPC::Connection.new
def initialize(name : String)
r = LibIPC.ipc_server_init(LibC.environ, pointerof(@service_info), name)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot initialize the server named #{name}: #{m}"
end
# Very important as there are filesystem side-effects.
at_exit { close }
end
def initialize(name : String, &block : Proc(Events|Exception, Nil))
initialize name
loop &block
close
end
def << (connection : IPC::Connection)
c = connection.connection
r = LibIPC.ipc_add(pointerof(@connections), pointerof(c))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot add an arbitrary file descriptor: #{m}"
end
end
def << (fd : Int)
r = LibIPC.ipc_add_fd(pointerof(@connections), fd)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot add an arbitrary file descriptor: #{m}"
end
end
def remove_fd (fd : Int)
r = LibIPC.ipc_del_fd(pointerof(@connections), fd)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot remove an arbitrary file descriptor: #{m}"
end
end
def close
return if @closed
r = LibIPC.ipc_server_close(pointerof(@service_info))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot close the server correctly: #{m}"
end
@closed = true
end
def finalize
close
end
def wait_event(&block) : Tuple(LibIPC::EventType, IPC::Message, IPC::Connection)
event = LibIPC::Event.new
r = LibIPC.ipc_wait_event pointerof(@connections), pointerof(@service_info), pointerof(event)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
yield IPC::Exception.new "error waiting for a new event: #{m}"
end
connection = IPC::Connection.new event.origin.unsafe_as(Pointer(LibIPC::Connection)).value
pp! event
message = event.message.unsafe_as(Pointer(LibIPC::Message))
unless message.null?
pp! message.value
end
return event.type, IPC::Message.new(message), connection
end
def loop(&block : Proc(Events|Exception, Nil))
::loop do
type, message, connection = wait_event &block
case type
when LibIPC::EventType::Connection
yield IPC::Event::Connection.new connection
when LibIPC::EventType::NotSet
yield IPC::Exception.new "even type not set"
when LibIPC::EventType::Error
yield IPC::Exception.new "even type indicates an error"
when LibIPC::EventType::ExtraSocket
yield IPC::Event::ExtraSocket.new message, connection
when LibIPC::EventType::Message
yield IPC::Event::Message.new message, connection
when LibIPC::EventType::Disconnection
yield IPC::Event::Disconnection.new connection
end
end
end
end

43
src/ipc/client.cr Normal file
View File

@ -0,0 +1,43 @@
require "./lowlevel"
require "./message"
require "./event"
require "./service"
require "./connection"
class IPC::Client < IPC::Connections
@connection : IPC::Connection
def initialize(name : String)
super()
@connection = IPC::Connection.new name
self << @connection
end
def initialize(name : String, &block : Proc(Events|Exception, Nil))
initialize name
::loop &block
close
end
def send(*args)
@connection.send *args
end
def read(*args)
@connection.read *args
end
# sanitizer
def fd
@connection.fd
end
def loop(&block : Proc(Events|Exception, Nil))
super(nil, &block)
end
def close
@connection.close
end
end

202
src/ipc/connection.cr Normal file
View File

@ -0,0 +1,202 @@
require "./lowlevel"
require "./message"
require "./event"
class IPC::Connection
getter connection : LibIPC::Connection
getter closed = false
# connection already established
def initialize(c : LibIPC::Connection)
@connection = c
end
def initialize(service_name : String)
@connection = LibIPC::Connection.new
r = LibIPC.ipc_connection(LibC.environ, self.pointer, service_name)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "error during connection establishment: #{m}"
end
end
def initialize(name, &block)
initialize(name)
yield self
close
end
# sanitizer
def fd
@connection.fd
end
def send(type : UInt8, payload : Bytes)
message = LibIPC::Message.new type: LibIPC::MessageType::Data.to_u8, user_type: type, length: payload.bytesize, payload: payload.to_unsafe
r = LibIPC.ipc_write(self.pointer, pointerof(message))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "error writing a message: #{m}"
end
end
def send(type : UInt8, payload : String)
send(type, Bytes.new(payload.to_unsafe, payload.bytesize))
end
def send(message : IPC::Message)
send(message.type, message.payload)
end
def read
message = LibIPC::Message.new
r = LibIPC.ipc_read(pointerof(@connection), pointerof(message))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "error reading a message: #{m}"
end
IPC::Message.new pointerof(message)
end
def close
return if @closed
r = LibIPC.ipc_close(self.pointer)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot correctly close the connection: #{m}"
end
@closed = true
end
def pointer
pointerof(@connection)
end
def type
@connection.type
end
end
# This class is designed for stand alone connections, where the StandAloneConnection object
# should NOT be garbage collected (which means the end of the communication)
class IPC::StandAloneConnection
# close the connection in case the object is garbage collected
def finalize
close
end
end
class IPC::Connections
getter connections : LibIPC::Connections
def initialize
@connections = LibIPC::Connections.new
end
def initialize(@connections : LibIPC::Connections)
end
def << (client : IPC::Connection)
r = LibIPC.ipc_add(self.pointer, client.pointer)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot add an arbitrary file descriptor: #{m}"
end
end
def << (fd : Int)
r = LibIPC.ipc_add_fd(self.pointer, fd)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot add an arbitrary file descriptor: #{m}"
end
end
def remove (client : IPC::Connection)
c = client.connection
r = LibIPC.ipc_del(self.pointer, pointerof(c))
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot remove a client: #{m}"
end
end
def remove_fd (fd : Int)
r = LibIPC.ipc_del_fd(self.pointer, fd)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot remove an arbitrary file descriptor: #{m}"
end
end
def wait_event(server : IPC::Connection | Nil, &block) : Tuple(LibIPC::EventType, IPC::Message, IPC::Connection)
event = LibIPC::Event.new
serverp = nil
unless server.nil?
serverp = server.pointer
end
r = LibIPC.ipc_wait_event self.pointer, serverp, pointerof(event)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
yield IPC::Exception.new "error waiting for a new event: #{m}"
end
connection = IPC::Connection.new event.origin.unsafe_as(Pointer(LibIPC::Connection)).value
eventtype = event.type.unsafe_as(LibIPC::EventType)
message = event.message.unsafe_as(Pointer(LibIPC::Message))
return eventtype, IPC::Message.new(message), connection
end
def loop(server : IPC::Connection | IPC::Server | ::Nil, &block : Proc(Events|Exception, Nil))
::loop do
type, message, connection = wait_event server, &block
case type
when LibIPC::EventType::Connection
yield IPC::Event::Connection.new connection
when LibIPC::EventType::NotSet
yield IPC::Exception.new "even type not set"
when LibIPC::EventType::Error
yield IPC::Exception.new "even type indicates an error"
when LibIPC::EventType::ExtraSocket
yield IPC::Event::ExtraSocket.new message, connection
when LibIPC::EventType::Switch
yield IPC::Event::Switch.new message, connection
when LibIPC::EventType::Message
yield IPC::Event::Message.new message, connection
# for now, the libipc does not provide lookup events
# networkd uses a simple LibIPC::EventType::Message
# when LibIPC::EventType::LookUp
# yield IPC::Event::LookUp.new message, connection
when LibIPC::EventType::Disconnection
yield IPC::Event::Disconnection.new connection
end
end
end
# sanitizer
def pointer
pointerof(@connections)
end
def pp
LibIPC.ipc_connections_print @connections
end
end

36
src/ipc/event.cr Normal file
View File

@ -0,0 +1,36 @@
require "./lowlevel"
require "./message"
require "./connection"
class IPC::Event
class Connection
getter connection : IPC::Connection
def initialize(@connection)
end
end
class Disconnection
getter connection : IPC::Connection
def initialize(@connection)
end
end
class Message
getter message : ::IPC::Message
getter connection : IPC::Connection
def initialize(@message, @connection)
end
end
class ExtraSocket < IPC::Event::Message
end
class Switch < IPC::Event::Message
end
class LookUp < IPC::Event::Message
end
end
alias Events = IPC::Event::Connection | IPC::Event::Disconnection | IPC::Event::Message | IPC::Event::ExtraSocket | IPC::Event::Switch | IPC::Event::LookUp

3
src/ipc/exception.cr Normal file
View File

@ -0,0 +1,3 @@
class IPC::Exception < ::Exception
end

167
src/ipc/lowlevel.cr Normal file
View File

@ -0,0 +1,167 @@
@[Link("ipc")]
lib LibIPC
struct Connection
version : LibC::UInt
index : LibC::UInt
fd : LibC::Int
type : UInt8
spath : LibC::Char* # [4096] # [PATH_MAX]
end
struct Connections
cinfos : Connection**
size : LibC::Int
end
struct Switching
origin : LibC::Int
dest : LibC::Int
end
struct Switchings
collection : Switching*
size : LibC::UInt
end
enum Errors
None = 0
NotEnoughMemory
ClosedRecipient
ServerInitNoEnvironmentParam
ServerInitNoServiceParam
ServerInitNoServerNameParam
ServerInitMalloc
ConnectionNoServer
ConnectionNoServiceName
ConnectionNoEnvironmentParam
ConnectionGenNoCinfo
AcceptNoServiceParam
AcceptNoClientParam
Accept
HandleNewConnectionNoCinfoParam
HandleNewConnectionNoCinfosParam
WaitEventSelect
WaitEventNoClientsParam
WaitEventNoEventParam
HandleNewConnectionMalloc
AddEmptyList
AddNoParamClients
AddNoParamClient
AddFdNoParamCinfos
DelEmptyList
DelEmptiedList
DelCannotFindClient
DelNoClientsParam
DelNoClientParam
UsockSend
UsockConnectSocket
UsockConnectWrongFileDescriptor
UsockConnectEmptyPath
UsockConnectConnect
UsockClose
UsockRemoveUnlink
UsockRemoveNoFile
UsockInitEmptyFileDescriptor
UsockInitWrongFileDescriptor
UsockInitEmptyPath
UsockInitBind
UsockInitListen
UsockAcceptPathFileDescriptor
UsockAccept
UsockRecvNoBuffer
UsockRecvNoLength
UsockRecv
MessageNewNoMessageParam
MessageReadNomessageparam
MessageWriteNoMessageParam
MessageWriteNotEnoughData
MessageFormatNoMessageParam
MessageFormatInconsistentParams
MessageFormatLength
MessageFormatWriteEmptyMessage
MessageFormatWriteEmptyMsize
MessageFormatWriteEmptyBuffer
MessageFormatReadEmptyMessage
MessageFormatReadEmptyBuffer
MessageFormatReadMessageSize
MessageEmptyEmptyMessageList
end
enum MessageType
ServerClose
Error
Data
LookUp
end
struct Message
type : UInt8
user_type : UInt8
length : LibC::UInt
payload : LibC::Char*
end
enum EventType
NotSet
Error
ExtraSocket
Switch
Connection
Disconnection
Message
LookUp
end
struct Event
type : EventType
origin : Connection*
message : Message*
end
fun ipc_server_init(env : LibC::Char**, connection : Connection*, sname : LibC::Char*) : LibC::Int
fun ipc_server_close(Connection*) : LibC::Int
fun ipc_close(Connection*) : LibC::Int
# connection to a service
fun ipc_connection(LibC::Char**, Connection*, LibC::Char*) : LibC::Int
fun ipc_read(Connection*, Message*) : LibC::Int
fun ipc_write(Connection*, Message*) : LibC::Int
fun ipc_wait_event(Connections*, Connection*, Event*) : LibC::Int
fun ipc_add(Connections*, Connection*) : LibC::Int
fun ipc_del(Connections*, Connection*) : LibC::Int
fun ipc_add_fd(Connections*, LibC::Int) : LibC::Int
fun ipc_del_fd(Connections*, LibC::Int) : LibC::Int
fun ipc_connection_copy(Connection*) : Connection*
fun ipc_connection_eq(Connection*, Connection*) : LibC::Int
fun ipc_connection_gen(Connection*, LibC::UInt, LibC::UInt)
fun ipc_connections_free(Connections*)
fun ipc_connections_close(Connections*)
fun ipc_get(Connections*)
fun ipc_errors_get (LibC::Int) : LibC::Char*
# networkd-related functions
fun ipc_wait_event_networkd(Connections*, Connection*, Event*, Switchings*) : LibC::Int
fun ipc_receive_fd (sock : LibC::Int, fd : LibC::Int*) : LibC::Int
fun ipc_provide_fd (sock : LibC::Int, fd : LibC::Int) : LibC::Int
fun ipc_switching_add (switch : Switchings*, fd1 : LibC::Int, fd2 : LibC::Int)
fun ipc_switching_del (switch : Switchings*, fd : LibC::Int ) : LibC::Int
fun ipc_switching_get (switch : Switchings*, fd : LibC::Int ) : LibC::Int
fun ipc_switching_free (switch : Switchings* ) : LibC::Int
fun ipc_switching_print (switch : Switchings*)
# non public functions (for testing purposes)
fun service_path (path : LibC::Char*, sname : LibC::Char*, index : Int32, version : Int32) : LibC::Int
fun log_get_logfile_dir (buf : LibC::Char*, size : LibC::UInt) : LibC::Char*
fun log_get_logfile_name (buf : LibC::Char*, size : LibC::UInt)
fun ipc_connections_print(Connections*)
end

40
src/ipc/message.cr Normal file
View File

@ -0,0 +1,40 @@
require "./lowlevel"
class IPC::Message
getter mtype : UInt8 # libipc message type
property type : UInt8 # libipc user message type
property payload : Bytes
def initialize(message : Pointer(LibIPC::Message))
if message.null?
@mtype = LibIPC::MessageType::Error.to_u8
@type = 0
@payload = Bytes.new "".to_unsafe, 0
else
m = message.value
@mtype = m.type
@type = m.user_type
@payload = Bytes.new m.payload, m.length
end
end
def initialize(message : LibIPC::Message)
initialize pointerof(message)
end
def initialize(mtype, type, payload : Bytes)
@mtype = mtype.to_u8
@type = type
@payload = payload
end
def initialize(mtype, type, payload : String)
initialize(mtype, type, Bytes.new(payload.to_unsafe, payload.bytesize))
end
def to_s
"(internal) type #{@mtype}, (user) type #{@type}, payload #{String.new @payload}"
end
end

92
src/ipc/service.cr Normal file
View File

@ -0,0 +1,92 @@
require "./lowlevel"
require "./message"
require "./event"
require "./connection"
# the server is a connection with two different function calls
# ipc_connection => ipc_server_init
# ipc_close => ipc_server_close
class IPC::Server < IPC::Connection
def initialize(name : String)
@connection = LibIPC::Connection.new
r = LibIPC.ipc_server_init(LibC.environ, self.pointer, name)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot initialize the server named #{name}: #{m}"
end
# Very important as there are filesystem side-effects.
at_exit { close }
end
def close
return if @closed
r = LibIPC.ipc_server_close(self.pointer)
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
raise Exception.new "cannot close the server correctly: #{m}"
end
@closed = true
end
end
class IPC::Service < IPC::Connections
@service_info : IPC::Server
def initialize(name : String)
@service_info = IPC::Server.new name
super()
end
def initialize(name : String, &block : Proc(Events|Exception, Nil))
initialize name
loop &block
close
end
# sanitizer
def fd
@service_info.fd
end
def loop(&block : Proc(Events|Exception, Nil))
super(@service_info, &block)
end
def close
@service_info.close
end
end
# TODO: replacing IPC::Service by the IPC::NetworkD class?
class IPC::SwitchingService < IPC::Service
property switch = IPC::Switch.new
# automatic removal of the fd in the switching list
def remove_fd (fd : Int)
super
@switch.del fd
end
def wait_event(server : IPC::Connection , &block) : Tuple(LibIPC::EventType, IPC::Message, IPC::Connection)
event = LibIPC::Event.new
serverp = server.pointer
r = LibIPC.ipc_wait_event_networkd self.pointer, serverp, pointerof(event), @switch.pointer
if r != 0
m = String.new LibIPC.ipc_errors_get (r)
yield IPC::Exception.new "error waiting for a new event: #{m}"
end
connection = IPC::Connection.new event.origin.unsafe_as(Pointer(LibIPC::Connection)).value
message = event.message.unsafe_as(Pointer(LibIPC::Message))
eventtype = event.type.unsafe_as(LibIPC::EventType)
return eventtype, IPC::Message.new(message), connection
end
end

33
src/ipc/switch.cr Normal file
View File

@ -0,0 +1,33 @@
require "./lowlevel"
class IPC::Switch
@switch = LibIPC::Switchings.new
def inilialize
end
def add (fd1 : Int32, fd2 : Int32)
LibIPC.ipc_switching_add self.pointer, fd1, fd2
end
def del (fd : Int32)
LibIPC.ipc_switching_del self.pointer, fd
end
def close
LibIPC.ipc_switching_free self.pointer
end
def print
LibIPC.ipc_switching_print self.pointer
end
def finalize
close
end
# sanitizer
def pointer
pointerof(@switch)
end
end