ipc.cr/src/high-level-bindings.cr

135 lines
3.2 KiB
Crystal

class IPC
# Reception buffer with a big capacity.
# Allocated once.
@reception_buffer = Array(UInt8).new 2_000_000
@reception_buffer_len : LibC::UInt64T = 2_000_000
class Event
property type : LibIPC::EventType
property index : LibC::UInt64T
property fd : Int32
property message : Array(UInt8)? = nil
def initialize(t : UInt8, @index, @fd, buffer, buflen)
@type = LibIPC::EventType.new t
if buflen > 0
# Array -> Pointer -> Slice -> Array
@message = buffer.to_unsafe.to_slice(buflen).to_a
end
end
end
def initialize
@context = Pointer(Void).null
LibIPC.init(pointerof(@context))
at_exit { deinit }
end
# Closes all connections then remove the structure from memory.
def deinit
LibIPC.deinit(pointerof(@context))
end
def service_init(name : String) : Int
fd = uninitialized Int32
if LibIPC.service_init(@context, pointerof(fd), name, name.size) != 0
raise "oh noes, 'service_init' iz brkn"
end
fd
end
def connect(name : String) : Int32
fd = uninitialized Int32
if LibIPC.connect_service(@context, pointerof(fd), name, name.size) != 0
raise "oh noes, 'connect_service' iz brkn"
end
fd
end
def timer(value : LibC::Int)
LibIPC.timer(@context, value)
end
def write(fd : Int, string : String)
self.write(fd, string.to_unsafe, string.size.to_u64)
end
def write(fd : Int, buffer : UInt8*, buflen : UInt64)
if LibIPC.write(@context, fd, buffer, buflen) != 0
raise "oh noes, 'write' iz brkn"
end
end
def write(fd : Int32, buffer : Bytes)
self.write(fd, buffer.to_unsafe, buffer.size.to_u64)
end
def read(fd : Int32) : Slice(UInt8)
buffer : Bytes = Bytes.new 2000000
size = buffer.size.to_u64
LibIPC.read(@context, fd, buffer.to_unsafe, pointerof(size))
buffer[0..size - 1]
end
def schedule(fd : Int32, string : String)
self.schedule(fd, string.to_unsafe, string.size.to_u64)
end
def schedule(fd : Int32, buffer : Array(UInt8), buflen : Int32)
self.schedule(fd, buffer.to_unsafe, buflen.to_u64)
end
def schedule(fd : Int32, buffer : Bytes)
self.schedule(fd, buffer.to_unsafe, buffer.size.to_u64)
end
def schedule(fd : Int32, buffer : UInt8*, buflen : UInt64)
if LibIPC.schedule(@context, fd, buffer, buflen) != 0
raise "oh noes, 'schedule' iz brkn"
end
end
def close(index : LibC::UInt64T)
if LibIPC.close(@context, index) != 0
raise "Oh noes, 'close index' iz brkn"
end
end
def close(fd : LibC::Int)
if LibIPC.close_fd(@context, fd) != 0
raise "Oh noes, 'close fd' iz brkn"
end
end
def close
if LibIPC.close_all(@context) != 0
raise "Oh noes, 'close all' iz brkn"
end
end
def wait : IPC::Event
eventtype : UInt8 = 0
index : LibC::UInt64T = 0
fd : Int32 = 0
buflen = @reception_buffer_len
ret = LibIPC.wait(@context,
pointerof(eventtype),
pointerof(index),
pointerof(fd),
@reception_buffer.to_unsafe,
pointerof(buflen))
if ret != 0
raise "Oh noes, 'wait' iz brkn"
end
Event.new(eventtype, index, fd, @reception_buffer, buflen)
end
def loop(&block : Proc(IPC::Event, Nil))
::loop do
yield wait
end
end
end