diff options
author | Christian Pointner <equinox@spreadspace.org> | 2015-05-02 19:29:38 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2015-05-02 19:29:38 (GMT) |
commit | cbce382e9cc06bb284f4d9f632e903bca6de0c67 (patch) | |
tree | 1c15435cfb430e48ad42687f9fe87e4bdae90aa9 /src/tcpserver.lua | |
parent | 4242679dc99da37f7d2b926f8eb6d86f4a09722c (diff) |
moved to single directory
Diffstat (limited to 'src/tcpserver.lua')
-rw-r--r-- | src/tcpserver.lua | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/tcpserver.lua b/src/tcpserver.lua new file mode 100644 index 0000000..85992c3 --- /dev/null +++ b/src/tcpserver.lua @@ -0,0 +1,133 @@ +-- +-- rhnop +-- +-- Copyright (C) 2011-2015 Christian Pointner <equinox@helsinki.at> +-- +-- 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 <http://www.gnu.org/licenses/>. +-- + +require "socket" + +package.path = package.path .. ";" .. rhnoplibdir .. "/?.lua" +conf = require "conf" + +function init_server() + local server = assert(socket.tcp()) + + assert(server:setoption('reuseaddr', true)) + assert(server:bind(conf.tcp_host, conf.tcp_port)) + assert(server:listen(5)) + + 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 = 0 + for idx, client in ipairs(clients) do + if client == c then + break + end + end + + -- print("removing client(" .. c.hdl:getfd() .. ")") + c.hdl:close() + table.remove(clients, idx) +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 |