diff --git a/fifo.lua b/fifo.lua deleted file mode 100644 index d21b1da..0000000 --- a/fifo.lua +++ /dev/null @@ -1,45 +0,0 @@ --- A generic fifo module. See docs/lua-modules/fifo.md for use examples. - -local tr, ti = table.remove, table.insert - --- Remove an element and pass it to k, together with a boolean indicating that --- this is the last element in the queue; if that returns a value, leave that --- pending at the top of the fifo. --- --- If k returns nil, the fifo will be advanced. Moreover, k may return a --- second result, a boolean, indicating "phantasmic" nature of this element. --- If this boolean is true, then the fifo will advance again, passing the next --- value, if there is one, to k, or priming itself for immediate execution at --- the next call to queue. --- --- If the queue is empty, do not invoke k but flag it to enable immediate --- execution at the next call to queue. --- --- Returns 'true' if the queue contained at least one non-phantom entry, --- 'false' otherwise. -local function dequeue(q,k) - if #q > 0 - then - local new, again = k(q[1], #q == 1) - if new == nil - then tr(q,1) - if again then return dequeue(q, k) end -- note tail call - else q[1] = new - end - return true - else q._go = true ; return false - end -end - --- Queue a on queue q and dequeue with `k` if the fifo had previously emptied. -local function queue(q,a,k) - ti(q,a) - if k ~= nil and q._go then q._go = false; dequeue(q, k) end -end - --- return a table containing just the FIFO constructor -return { - ['new'] = function() - return { ['_go'] = true ; ['queue'] = queue ; ['dequeue'] = dequeue } - end -} diff --git a/fifosock.lua b/fifosock.lua deleted file mode 100644 index c453fb1..0000000 --- a/fifosock.lua +++ /dev/null @@ -1,134 +0,0 @@ --- Wrap a two-staged fifo around a socket's send; see --- docs/lua-modules/fifosock.lua for more documentation. --- --- See fifosocktest.lua for some examples of use or tricky cases. --- --- Our fifos can take functions; these can be useful for either lazy --- generators or callbacks for parts of the stream having been sent. - -local BIGTHRESH = 256 -- how big is a "big" string? -local SPLITSLOP = 16 -- any slop in the big question? -local FSMALLLIM = 32 -- maximum number of small strings held -local COALIMIT = 3 - -local concat = table.concat -local insert = table.insert -local gc = collectgarbage - -local function wrap(sock) - -- the two fifos - local fsmall, lsmall, fbig = {}, 0, (require "fifo").new() - - -- ssend last aggregation string and aggregate count - local ssla, sslan = nil, 0 - local ssend = function(s,islast) - local ns = nil - - -- Optimistically, try coalescing FIFO dequeues. But, don't try to - -- coalesce function outputs, since functions might be staging their - -- execution on the send event implied by being called. - - if type(s) == "function" then - if sslan ~= 0 then - sock:send(ssla) - ssla, sslan = nil, 0; gc() - return s, false -- stay as is and wait for :on("sent") - end - s, ns = s() - elseif type(s) == "string" and sslan < COALIMIT then - if sslan == 0 - then ssla, sslan = s, 1 - else ssla, sslan = ssla .. s, sslan + 1 - end - if islast then - -- this is shipping; if there's room, steal the small fifo, too - if sslan < COALIMIT then - sock:send(ssla .. concat(fsmall)) - fsmall, lsmall = {}, 0 - else - sock:send(ssla) - end - ssla, sslan = "", 0; gc() - return nil, false - else - return nil, true - end - end - - -- Either that was a function or we've hit our coalescing limit or - -- we didn't ship above. Ship now, if there's something to ship. - if s ~= nil then - if sslan == 0 then sock:send(s) else sock:send(ssla .. s) end - ssla, sslan = nil, 0; gc() - return ns or nil, false - elseif sslan ~= 0 then - assert (ns == nil) - sock:send(ssla) - ssla, sslan = nil, 0; gc() - return nil, false - else - assert (ns == nil) - return nil, true - end - end - - -- Move fsmall to fbig; might send if fbig empty - local function promote(f) - if #fsmall == 0 then return end - local str = concat(fsmall) - fsmall, lsmall = {}, 0 - fbig:queue(str, f or ssend) - end - - local function sendnext() - if not fbig:dequeue(ssend) then promote() end - end - - sock:on("sent", sendnext) - - return function(s) - -- don't sweat the petty things - if s == nil or s == "" then return end - - -- Function? Go ahead and queue this thing in the right place. - if type(s) == "function" then promote(); fbig:queue(s, ssend); return; end - - s = tostring(s) - - -- cork sending until the end in case we're the head of line - local corked = false - local function corker(t) corked = true; return t end - - -- small fifo would overfill? promote it - if lsmall + #s > BIGTHRESH or #fsmall >= FSMALLLIM then promote(corker) end - - -- big string? chunk and queue big components immediately - -- behind any promotion that just took place - while #s > BIGTHRESH + SPLITSLOP do - local pfx - pfx, s = s:sub(1,BIGTHRESH), s:sub(BIGTHRESH+1) - fbig:queue(pfx, corker) - end - - -- Big string? queue and maybe tx now - if #s > BIGTHRESH then fbig:queue(s, corker) - -- small and fifo in immediate dequeue mode - elseif fbig._go and lsmall == 0 then fbig:queue(s, corker) - -- small and queue already moving; let it linger in the small fifo - else insert(fsmall, s) ; lsmall = lsmall + #s - end - - -- if it happened that we corked the transmission above... - -- if we queued a good amount of data, go ahead and start transmitting; - -- otherwise, wait a tick and hopefully we will queue more in the interim - -- before transmitting. - if corked then - if #fbig <= COALIMIT - then tmr.create():alarm(1, tmr.ALARM_SINGLE, sendnext) - else sendnext() - end - end - end -end - -return { wrap = wrap } diff --git a/fifosocktest.lua b/fifosocktest.lua deleted file mode 100644 index 4ac9f21..0000000 --- a/fifosocktest.lua +++ /dev/null @@ -1,145 +0,0 @@ --- --- Set verbose to 0 for quiet output (either the first assertion failure or --- "All tests OK"), to 1 to see the events ("SEND", "SENT", "CHECK") without --- the actual bytes, or to 2 to see the events with the bytes. --- -local verbose = 0 - -local vprint = (verbose > 0) and print or function() end - --- --- Mock up enough of the nodemcu tmr structure, but pretend that nothing --- happens between ticks. This won't exercise the optimistic corking logic, --- but that's probably fine. --- luacheck: push ignore -tmr = {} -tmr.ALARM_SINGLE = 0 -function tmr.create() - local r = {} - function r:alarm(_i, _t, cb) vprint("TMR") cb() end - return r -end --- luacheck: pop - --- --- Mock up enough of the nodemcu net.socket type; have it log all the sends --- into this "outs" array so that we can later check against it. --- -local outs = {} -local fakesock = { - cb = nil, - on = function(this, _, cb) this.cb = cb end, - send = function(this, s) vprint("SEND", (verbose > 1) and s) table.insert(outs, s) end -- luacheck: no unused -} -local function sent() vprint("SENT") fakesock.cb() end - --- And wrap a fifosock around this fake socket -local fsend = (require "fifosock").wrap(fakesock) - --- Verify that the next unconsumed output is as indicated -local function fcheck(x) - vprint ("CHECK", (verbose > 1) and x) - assert (#outs > 0) - assert (x == outs[1]) - table.remove(outs, 1) -end - --- Enqueue an empty function to prevent coalescing within the fifosock -local function nocoal() fsend(function() return nil end) end - --- Send and check, for when the string should be sent exactly as is -local function fsendc(x) fsend(x) fcheck(x) end - --- Check that there are no more outputs -local function fchecke() vprint("CHECKE") assert (#outs == 0) end - --- --- And now for the tests, which start easy and grow in complexity --- - -fsendc("abracadabra none") -sent() ; fchecke() - -fsendc("abracadabra three") -fsend("short") -fsend("string") -fsend("build") -sent() ; fcheck("shortstringbuild") -sent() ; fchecke() - --- Hit default FSMALLLIM while building up -fsendc("abracadabra lots small") -for i = 1, 32 do fsend("a") end -- luacheck: no unused -nocoal() -for i = 1, 4 do fsend("a") end -- luacheck: no unused -sent() ; fcheck(string.rep("a", 32)) -sent() ; fcheck(string.rep("a", 4)) -sent() ; fchecke() - --- Hit string length while building up -fsendc("abracadabra overlong") -for i = 1, 10 do fsend(string.rep("a",32)) end -- luacheck: no unused -sent() ; fcheck(string.rep("a", 320)) -sent() ; fchecke() - --- Hit neither before sending a big string -fsendc("abracadabra mid long") -for i = 1, 6 do fsend(string.rep("a",32)) end -- luacheck: no unused -fsend(string.rep("b", 256)) -nocoal() -for i = 1, 6 do fsend(string.rep("c",32)) end -- luacheck: no unused -sent() ; fcheck(string.rep("a", 192) .. string.rep("b", 256)) -sent() ; fcheck(string.rep("c", 192)) -sent() ; fchecke() - --- send a huge string, verify that it coalesces -fsendc(string.rep("a",256) .. string.rep("b", 256) .. string.rep("c", 260)) -sent() ; fchecke() - --- send a huge string, verify that it coalesces save for the short bit at the end -fsend(string.rep("a",256) .. string.rep("b", 256) .. string.rep("c", 256) .. string.rep("d",256)) -fsend("e") -fcheck(string.rep("a",256) .. string.rep("b", 256) .. string.rep("c", 256)) -sent() ; fcheck(string.rep("d",256) .. "e") -sent() ; fchecke() - --- send enough that our 4x lookahead still leaves something in the queue -fsend(string.rep("a",512) .. string.rep("b", 512) .. string.rep("c", 512)) -fcheck(string.rep("a",512) .. string.rep("b", 512)) -sent() ; fcheck(string.rep("c",512)) -sent() ; fchecke() - --- test a lazy generator -do - local ix = 0 - local function gen() vprint("GEN", ix); ix = ix + 1; return ("a" .. ix), ix < 3 and gen end - fsend(gen) - fsend("b") - fcheck("a1") - sent() ; fcheck("a2") - sent() ; fcheck("a3") - sent() ; fcheck("b") - sent() ; fchecke() -end --- test a completion-like callback that does send text -do - local ix = 0 - local function gen() vprint("GEN"); ix = 1; return "efgh", nil end - fsend("abcd"); fsend(gen); fsend("ijkl") - assert (ix == 0) - fcheck("abcd"); assert (ix == 0) - sent() ; fcheck("efgh"); assert (ix == 1); ix = 0 - sent() ; fcheck("ijkl"); assert (ix == 0) - sent() ; fchecke() -end --- and one that doesn't -do - local ix = 0 - local function gen() vprint("GEN"); ix = 1; return nil, nil end - fsend("abcd"); fsend(gen); fsend("ijkl") - assert (ix == 0) - fcheck("abcd"); assert (ix == 0) - sent() ; fcheck("ijkl"); assert (ix == 1); ix = 0 - sent() ; fchecke() ; assert (ix == 0) -end -print("All tests OK") diff --git a/httpserver.lua b/httpserver.lua deleted file mode 100644 index edab602..0000000 --- a/httpserver.lua +++ /dev/null @@ -1,217 +0,0 @@ ------------------------------------------------------------------------------- --- HTTP server module --- --- LICENCE: http://opensource.org/licenses/MIT --- Vladimir Dronnikov ------------------------------------------------------------------------------- -local collectgarbage, tonumber, tostring = collectgarbage, tonumber, tostring - -local http -do - ------------------------------------------------------------------------------ - -- request methods - ------------------------------------------------------------------------------ - local make_req = function(conn, method, url) - return { - conn = conn, - method = method, - url = url, - } - end - - ------------------------------------------------------------------------------ - -- response methods - ------------------------------------------------------------------------------ - local make_res = function(csend, cfini) - local send = function(self, data, status) - -- TODO: req.send should take care of response headers! - if self.send_header then - csend("HTTP/1.1 ") - csend(tostring(status or 200)) - -- TODO: real HTTP status code/name table - csend(" OK\r\n") - -- we use chunked transfer encoding, to not deal with Content-Length: - -- response header - self:send_header("Transfer-Encoding", "chunked") - -- TODO: send standard response headers, such as Server:, Date: - end - if data then - -- NB: no headers allowed after response body started - if self.send_header then - self.send_header = nil - -- end response headers - csend("\r\n") - end - -- chunked transfer encoding - csend(("%X\r\n"):format(#data)) - csend(data) - csend("\r\n") - end - end - - local send_header = function(_, name, value) - -- NB: quite a naive implementation - csend(name) - csend(": ") - csend(value) - csend("\r\n") - end - -- finalize request, optionally sending data - local finish = function(self, data, status) - -- NB: res.send takes care of response headers - if data then - self:send(data, status) - end - -- finalize chunked transfer encoding - csend("0\r\n\r\n") - -- close connection - cfini() - end - -- - local res = { } - res.send_header = send_header - res.send = send - res.finish = finish - return res - end - - ------------------------------------------------------------------------------ - -- HTTP parser - ------------------------------------------------------------------------------ - local http_handler = function(handler) - return function(conn) - local csend = (require "fifosock").wrap(conn) - - local req, res - local buf = "" - local method, url - - local ondisconnect = function(connection) - connection:on("receive", nil) - connection:on("disconnection", nil) - connection:on("sent", nil) - collectgarbage("collect") - end - - local cfini = function() - csend(function() - conn:on("sent", nil) - conn:close() - ondisconnect(conn) - end) - end - - - -- header parser - local cnt_len = 0 - - local onheader = function(_, k, v) - -- TODO: look for Content-Type: header - -- to help parse body - -- parse content length to know body length - if k == "content-length" then - cnt_len = tonumber(v) - end - if k == "expect" and v == "100-continue" then - csend("HTTP/1.1 100 Continue\r\n") - end - -- delegate to request object - if req and req.onheader then - req:onheader(k, v) - end - end - - -- body data handler - local body_len = 0 - local ondata = function(_, chunk) - -- feed request data to request handler - if not req or not req.ondata then return end - req:ondata(chunk) - -- NB: once length of seen chunks equals Content-Length: - -- ondata(conn) is called - body_len = body_len + #chunk - -- print("-B", #chunk, body_len, cnt_len, node.heap()) - if body_len >= cnt_len then - req:ondata() - end - end - - local onreceive = function(connection, chunk) - -- merge chunks in buffer - if buf then - buf = buf .. chunk - else - buf = chunk - end - -- consume buffer line by line - while #buf > 0 do - -- extract line - local e = buf:find("\r\n", 1, true) - if not e then break end - local line = buf:sub(1, e - 1) - buf = buf:sub(e + 2) - -- method, url? - if not method then - do - local _ - -- NB: just version 1.1 assumed - _, _, method, url = line:find("^([A-Z]+) (.-) HTTP/1.1$") - end - if method then - -- make request and response objects - req = make_req(connection, method, url) - res = make_res(csend, cfini) - end - -- spawn request handler - handler(req, res) - -- header line? - elseif #line > 0 then - -- parse header - local _, _, k, v = line:find("^([%w-]+):%s*(.+)") - -- header seems ok? - if k then - k = k:lower() - onheader(connection, k, v) - end - -- headers end - else - -- NB: we explicitly reassign receive handler so that - -- next received chunks go directly to body handler - connection:on("receive", ondata) - -- NB: we feed the rest of the buffer as starting chunk of body - ondata(connection, buf) - -- buffer no longer needed - buf = nil - -- parser done - break - end - end - end - - conn:on("receive", onreceive) - conn:on("disconnection", ondisconnect) - end - end - - ------------------------------------------------------------------------------ - -- HTTP server - ------------------------------------------------------------------------------ - local srv - local createServer = function(port, handler) - -- NB: only one server at a time - if srv then srv:close() end - srv = net.createServer(net.TCP, 15) - -- listen - srv:listen(port, http_handler(handler)) - return srv - end - - ------------------------------------------------------------------------------ - -- HTTP server methods - ------------------------------------------------------------------------------ - http = { - createServer = createServer, - } -end - -return http diff --git a/nodemcu-release-16-modules-2021-10-09-22-33-53-float.bin b/nodemcu-release-16-modules-2021-10-09-22-33-53-float.bin deleted file mode 100644 index 9fd21e1..0000000 Binary files a/nodemcu-release-16-modules-2021-10-09-22-33-53-float.bin and /dev/null differ