Skip to content
This repository was archived by the owner on Nov 30, 2019. It is now read-only.

Commit 1ca8d27

Browse files
committed
Memory footprint reduction, tbconnection, cleanup
*Greatly reduced memory footprint to about 7K plus 6K for the tbconnection totals about 13K. Done mostly by unfolding chained functions into sequenced functions, and by offloading code into .lua files which are then loaded on demand with dofile() *Implemented tbconnection: an encapsulation of a threaded-buffered connection. Takes a function and runs it in a coroutine, takes a connection which it then uses to send() data and see-saw between the coroutine and the onSent() callback set up for the connection. *Changed wifigui to 1st serve the form, then close the connection, and finally set up the wifi *Added favicon.ico *Some cleanups *Momentarily commented underconstruction.gif from index.html: makes server crash due to concurrent connections eating up all heap *Fixed set up of wifi phymode
1 parent 8384606 commit 1ca8d27

13 files changed

+375
-291
lines changed

Diff for: http/favicon.ico

1.12 KB
Binary file not shown.

Diff for: http/index.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
</head>
77
<body>
88
<h1>NodeMCU Platform</h1>
9-
<div align="center">
10-
<img src="underconstruction.gif">
11-
</div>
9+
<!div align="center">
10+
<!img src="underconstruction.gif">
11+
<!/div>
1212
<p>
1313
This page is served by <b>nodemcu-httpserver</b> variant running on an ESP8266 that uses the <a href="http://nodemcu.com/index_en.html">NodeMCU</a> firmware.
1414
NodeMCU puts a <a href="http://www.lua.org">Lua</a> interpreter inside the ESP8266. This is surely one of the smallest web servers to date!<br>

Diff for: http/wifigui.lua

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
return function (connection, req, args)
2+
--print("wifigui.lc heap="..node.heap())
23
local wifiConfig = dofile("wifi-conf.lc")
34
collectgarbage()
45
assert(wifiConfig ~= nil, "wifiConfig is nil")
@@ -29,13 +30,17 @@ return function (connection, req, args)
2930
--write out the config, compile, apply config
3031
dofile("wifi-confwrite.lc")(wifiConfig, "wifi-conf.lua")
3132
dofile("compile.lc")("wifi-conf.lua")
33+
--serve the form again (has to be done before wigi.lc, or connection could be due to wifi reset
34+
dofile("http/wifigui-form.lc")(req.method, connection, wifiConfig)
35+
--wifi reset
36+
connection:close() --need to close connection 1st, or memleak, but no more sends after!
3237
dofile("wifi.lc")
3338
collectgarbage()
39+
else
40+
--serve the form again
41+
dofile("http/wifigui-form.lc")(req.method, connection, wifiConfig)
42+
collectgarbage()
3443
end
35-
36-
--serve the form again
37-
dofile("http/wifigui-form.lc")(req.method, connection, wifiConfig)
38-
collectgarbage()
3944
else
4045
dofile("http/wifigui-form.lc")(req.method, connection, wifiConfig, rd, badvalues)
4146
end
@@ -44,4 +49,5 @@ return function (connection, req, args)
4449
end
4550

4651
collectgarbage()
52+
--print("wifigui.lc end heap="..node.heap())
4753
end

Diff for: httpserver-header.lua

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ return function (connection, code, extension, gzip)
88
local codez = {[200]="OK", [400]="Bad Request", [404]="Not Found",}
99
local myResult = codez[code] --
1010
-- enforce returning valid http codes all the way throughout?
11-
if myResult then return myResult else return "Not Implemented" end
11+
if myResult then
12+
return myResult
13+
end
14+
return "Not Implemented"
1215
end
1316

1417
local function getMimeType(ext)

Diff for: httpserver-payload.lua

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
return function(payload, fullPayload, bBodyMissing)
2+
-- collect data packets until the size of http body meets the Content-Length stated in header
3+
4+
if payload:find("Content%-Length:") or bBodyMissing then
5+
if fullPayload then
6+
fullPayload = fullPayload .. payload
7+
else
8+
fullPayload = payload
9+
end
10+
if (tonumber(string.match(fullPayload, "%d+", fullPayload:find("Content%-Length:")+16)) > #fullPayload:sub(fullPayload:find("\r\n\r\n", 1, true)+4, #fullPayload)) then
11+
bBodyMissing = true
12+
else
13+
--print("HTTP packet assembled! size: "..#tmp_payload)
14+
payload = fullPayload
15+
fullPayload, bBodyMissing = nil
16+
end
17+
end
18+
return payload, fullPayload, bBodyMissing
19+
end

Diff for: httpserver-servefunction.lua

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
-- httpserver-servefunction
2+
-- Author: Daniel Salazar
3+
-- Based on work by Marcos Kirsch
4+
5+
6+
return function (connection, payload)
7+
local conf = dofile("confload.lc")("httpserver-conf.lc")
8+
local auth
9+
local user = "Anonymous"
10+
11+
-- parse payload and decide what to serve.
12+
if conf.auth.enabled then
13+
auth = dofile("httpserver-basicauth.lc")
14+
user = auth.authenticate(payload, conf) -- authenticate returns nil on failed auth
15+
end
16+
17+
local req = dofile("httpserver-request.lc")(payload)
18+
print(req.method .. ": " .. req.request)
19+
20+
local serveFunction = nil
21+
local methodIsAllowed = {GET=true, POST=true, PUT=true}
22+
23+
if user and req.methodIsValid and methodIsAllowed[req.method] and #(req.uri.file) <= 31 then
24+
local uri = req.uri
25+
26+
local fileExists = file.exists(uri.file)
27+
if not fileExists then
28+
fileExists = file.exists(uri.file .. ".gz")
29+
if fileExists then
30+
uri.file = uri.file .. ".gz"
31+
uri.isGzipped = true
32+
end
33+
end
34+
35+
if not fileExists then
36+
uri.args = {code = 404, errorString = "Not Found"}
37+
serveFunction = dofile("httpserver-error.lc")
38+
elseif uri.isScript then
39+
serveFunction = dofile(uri.file)
40+
else
41+
local allowStatic = {GET=true, HEAD=true, POST=false, PUT=false, DELETE=false, TRACE=false, OPTIONS=false, CONNECT=false, PATCH=false}
42+
if allowStatic[req.method] then
43+
uri.args = {file = uri.file, ext = uri.ext, gzipped = uri.isGzipped}
44+
serveFunction = dofile("httpserver-static.lc")
45+
else
46+
uri.args = {code = 405, errorString = "Method not supported"}
47+
serveFunction = dofile("httpserver-error.lc")
48+
end
49+
end
50+
else
51+
serveFunction = dofile("httpserver-error.lc")
52+
if not user then
53+
req.uri.args = {code = 401, errorString = "Not Authorized", headers = {auth.authErrorHeader(conf)}}
54+
elseif req.methodIsValid then
55+
req.uri.args = {code = 501, errorString = "Not Implemented"}
56+
else
57+
req.uri.args = {code = 400, errorString = "Bad Request"}
58+
end
59+
end
60+
return serveFunction, req
61+
end

0 commit comments

Comments
 (0)