summaryrefslogtreecommitdiff
path: root/rhnop-server/tcpserver.lua
diff options
context:
space:
mode:
Diffstat (limited to 'rhnop-server/tcpserver.lua')
-rwxr-xr-xrhnop-server/tcpserver.lua128
1 files changed, 128 insertions, 0 deletions
diff --git a/rhnop-server/tcpserver.lua b/rhnop-server/tcpserver.lua
new file mode 100755
index 0000000..bd945b6
--- /dev/null
+++ b/rhnop-server/tcpserver.lua
@@ -0,0 +1,128 @@
+--
+-- rhnop
+--
+-- Copyright (C) 2011 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"
+
+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 = assert(output.hdl:send(output.buffer))
+ output.buffer = string.sub(output.buffer, ret+1)
+ end
+ end
+ end
+
+ server:close()
+ cleanup_clients()
+
+ return 0
+end