1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
--
-- 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"
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 = assert(output.hdl:send(output.buffer))
output.buffer = string.sub(output.buffer, ret+1)
end
end
end
server:close()
cleanup_clients()
return 0
end
|