-- -- rhnop -- -- Copyright (C) 2011-2016 Christian Pointner -- -- This file is part of rhnop. -- -- rhnop 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. -- -- rhnop 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 rhnop. If not, see . -- socket = require "socket" package.path = package.path .. ";" .. rhnoplibdir .. "/?.lua" conf = require "conf" function init_server() local server = assert(socket.tcp()) cnf = conf.load(rhnopescdir .. "/nopfetchd.conf") assert(server:setoption('reuseaddr', true)) assert(server:bind(cnf.tcp_host, cnf.tcp_port)) assert(server:listen(5)) print("TCPServer: listening on " .. cnf.tcp_host .. ":" .. cnf.tcp_port) return server end local clients = {} function add_client(hdl) -- print("new client(" .. hdl:getfd() .. ") from " .. hdl:getpeername()) local client = {} client.buffer = "" client.hdl = hdl client.getfd = function() return hdl:getfd() end client.dirty = function() return hdl:dirty() end table.insert(clients, client) end function remove_client(c) local idx = -1 for n, client in ipairs(clients) do if client.getfd() == c.getfd() then idx = n break end end if idx > 0 then -- print("removing client(" .. c.getfd() .. ")") c.hdl:close() table.remove(clients, idx) end end function cleanup_clients() for _, client in ipairs(clients) do client:close() end end function clients_get_writeables() local fds = {} for _, client in ipairs(clients) do if client.buffer ~= "" then table.insert(fds, client) end end return fds end function clients_senddata(timestamp) for _, client in ipairs(clients) do client.buffer = client.buffer .. timestamp .. "\n" end end function main_loop() local pipefd = pipe.getreadfd() server = init_server() while true do local readables, writeables, err = socket.select({ pipefd , server , unpack(clients) } , clients_get_writeables()) if err then print("select returned with error: " .. err) return -1 else for _, input in ipairs(readables) do if input == pipefd then local timestamp = pipe.consume() if timestamp == nil then return 2 end -- print("pipe was signaled with timestamp: " .. timestamp) clients_senddata(timestamp) elseif input == server then local client = assert(server:accept()) add_client(client) else if input.hdl then -- receive is insanely stupid, therefore we must always read one byte only local _, err = input.hdl:receive(1) if err then remove_client(input) end end end end for _, output in ipairs(writeables) do local ret = output.hdl:send(output.buffer) if(ret == nil) then remove_client(output) else output.buffer = string.sub(output.buffer, ret+1) end end end end server:close() cleanup_clients() return 0 end