-- -- gcsd -- -- gcsd the generic command sequencer daemon can be used to serialize -- commands sent over various paralell communication channels to a -- single command output. It can be seen as a multiplexer for any -- kind of communication between a single resource and various clients -- which want to submit commands to it or query information from it. -- gcsd is written in C and Lua. The goal is to provide an easy to -- understand high level API based on Lua which can be used to -- implement the business logic of the so formed multiplexer daemon. -- -- -- Copyright (C) 2009-2010 Markus Grueneis -- Christian Pointner -- -- This file is part of gcsd. -- -- gcsd is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- any later version. -- -- gcsd is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with gcsd. If not, see . -- local defines = require("defines") -- stdio module class local stdio = {} stdio.properties = { type=defines.INOUT_MODULE, name="stdio", max_instances=1 } -- create new instance of stdio module class function stdio:new(config) local inst = {} inst.class = self.properties.name inst.config = config if(config.name == nil or config.name == "") then inst.name = self.properties.name else inst.name = config.name end local in_handle = {} in_handle.fd = 0 rawio.setnonblock(in_handle.fd) in_handle.client_instance = nil in_handle.in_buffer = "" function in_handle:getfd() return self.fd end function in_handle:read() -- TODO: which size should we request?? local buffer, err = rawio.read(0, 100) if(buffer == nil) then log.printf(log.ERROR, inst.name .. ": connection error: %s", err) return defines.KILL_MODULE_CLASS end self.in_buffer = self.in_buffer .. buffer self.in_buffer = dispatch_table:dispatch(self.in_buffer) -- TODO: part of expected response handling command_queue:command_completed() return defines.OK end function in_handle:write() end local out_handle = {} out_handle.fd = 1 rawio.setnonblock(out_handle.fd) out_handle.client_instance = nil out_handle.out_buffer = "" function out_handle:getfd() return self.fd end function out_handle:read() end function out_handle:write() local len, err = rawio.write(1, self.out_buffer) if(len == nil) then log.printf(log.ERROR, inst.name .. ": connection error: %s", err) ret = defines.KILL_MODULE_CLASS else self.out_buffer = string.sub(self.out_buffer, len+1) end if(self.out_buffer == "") then command_queue:command_sent() end return defines.OK end local client = {} client.module_instance = inst client.name = inst.name .. "#0" function client:process_response() end function client:process_timeout() end function client:get_read_handles() return { in_handle } end function client:get_write_handles() if(out_handle.out_buffer ~= "") then return { out_handle } else return {} end end function client:cleanup() end in_handle.client_instance = client out_handle.client_instance = client function inst:cleanup() client_list:unregister_by_module(self) end function inst:get_read_handles() return {} end function inst:get_write_handles() return {} end function inst:start_command(command) out_handle.out_buffer = command end setmetatable(inst, {}) getmetatable(inst).__gc = function() inst:cleanup() end client_list:register(client) return inst end return stdio