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
|
--[[
HTTP server implementation for LuCI - core
(c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
module("luci.httpd", package.seeall)
require("socket")
require("luci.util")
function Socket(ip, port)
local sock, err = socket.bind( ip, port )
if sock then
sock:settimeout( 0, "t" )
end
return sock, err
end
Daemon = luci.util.class()
function Daemon.__init__(self, threadlimit, timeout)
self.reading = {}
self.running = {}
self.handler = {}
self.debug = false
self.threadlimit = threadlimit
self.timeout = timeout or 0.1
end
function Daemon.dprint(self, msg)
if self.debug then
io.stderr:write("[daemon] " .. msg .. "\n")
end
end
function Daemon.register(self, sock, clhandler, errhandler)
table.insert( self.reading, sock )
self.handler[sock] = { clhandler = clhandler, errhandler = errhandler }
end
function Daemon.run(self)
while true do
self:step()
end
end
function Daemon.step(self)
local input, output, err = socket.select( self.reading, nil, 0 )
if err == "timeout" and #self.running == 0 then
socket.sleep(self.timeout)
end
-- accept new connections
for i, connection in ipairs(input) do
local sock = connection:accept()
-- check capacity
if not self.threadlimit or #self.running < self.threadlimit then
self:dprint("Accepted incoming connection from " .. sock:getpeername())
table.insert( self.running, {
coroutine.create( self.handler[connection].clhandler ),
sock
} )
self:dprint("Created " .. tostring(self.running[#self.running][1]))
-- reject client
else
self:dprint("Rejected incoming connection from " .. sock:getpeername())
if self.handler[connection].errhandler then
self.handler[connection].errhandler( sock )
end
sock:close()
end
end
-- create client handler
for i, client in ipairs( self.running ) do
-- reap dead clients
if coroutine.status( client[1] ) == "dead" then
self:dprint("Completed " .. tostring(client[1]))
table.remove( self.running, i )
else
self:dprint("Resuming " .. tostring(client[1]))
local stat, err = coroutine.resume( client[1], client[2] )
self:dprint(tostring(client[1]) .. " returned")
if not stat then
self:dprint("Error in " .. tostring(client[1]) .. " " .. err)
end
end
end
end
|