From b4a2d02431213d82da56c3c80351b0e96219f5a8 Mon Sep 17 00:00:00 2001 From: Philip Gladstone Date: Sun, 22 Nov 2015 13:39:03 -0500 Subject: [PATCH 1/5] Fix the problem with the more modern SDK only allowing one outstanding connection:send at a time. Long and short of it, don't use coroutine.yield any more when serving content. --- README.md | 5 ----- http/file_list.lua | 3 --- httpserver-static.lua | 1 - httpserver.lua | 43 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index aadf9c5..8162cf3 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,6 @@ A (very) simple web server written in Lua for the ESP8266 running the NodeMCU fi For example, if the client requests _http://2.2.2.2/foo.lua?color=red_ then the server will execute the function in your Lua script _foo.lua_ and pass in _connection_ and _args_, where _args.color = "red"_. - If you are going to be sending lots (as in over a KB) of data in your script, you should yield the thread/coroutine - every now and then in order to avoid overflowing the send buffer in the microcontroller. Use: - - coroutine.yield() - Look at the included example scripts for more ideas. ### Example: Garage door opener diff --git a/http/file_list.lua b/http/file_list.lua index 9e92a23..6879900 100644 --- a/http/file_list.lua +++ b/http/file_list.lua @@ -2,7 +2,6 @@ return function (connection, req, args) connection:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nCache-Control: private, no-store\r\n\r\n") connection:send('Server File Listing') connection:send('') - coroutine.yield() connection:send('

Server File Listing

') local remaining, used, total=file.fsinfo() @@ -20,8 +19,6 @@ return function (connection, req, args) if isHttpFile then local url = string.match(name, ".*/(.*)") connection:send('
  • ' .. url .. " (" .. size .. " bytes)
  • \n") - -- this list could be very long, so we'll yield in order to avoid overflowing the send buffer. - coroutine.yield() end end connection:send("\n") diff --git a/httpserver-static.lua b/httpserver-static.lua index 5a57bd5..d7cb86f 100644 --- a/httpserver-static.lua +++ b/httpserver-static.lua @@ -20,7 +20,6 @@ return function (connection, req, args) if chunk == nil then continue = false else - coroutine.yield() connection:send(chunk) bytesSent = bytesSent + #chunk chunk = nil diff --git a/httpserver.lua b/httpserver.lua index 1f8f818..e0970c6 100644 --- a/httpserver.lua +++ b/httpserver.lua @@ -13,9 +13,37 @@ return function (port) -- We do it in a separate thread because we need to yield when sending lots -- of data in order to avoid overflowing the mcu's buffer. local connectionThread - + local allowStatic = {GET=true, HEAD=true, POST=false, PUT=false, DELETE=false, TRACE=false, OPTIONS=false, CONNECT=false, PATCH=false} + local function startServing(fileServeFunction, connection, req, args) + local bufferedConnection = {} + connectionThread = coroutine.create(function(fileServeFunction, connection, req, args) + fileServeFunction(connection, req, args) + connection:flush() + end) + function bufferedConnection:flush() + connection:send(table.concat(self.data, "")) + self.data = {} + self.size = 0 + end + function bufferedConnection:send(payload) + local l = payload:len() + if l + self.size > 1400 then + self:flush() + coroutine.yield() + end + table.insert(self.data, payload) + self.size = self.size + l + end + bufferedConnection.size = 0 + bufferedConnection.data = {} + local status, err = coroutine.resume(connectionThread, fileServeFunction, bufferedConnection, req, args) + if not status then + print(err) + end + end + local function onRequest(connection, req) collectgarbage() local method = req.method @@ -59,8 +87,7 @@ return function (port) end end end - connectionThread = coroutine.create(fileServeFunction) - coroutine.resume(connectionThread, connection, req, uri.args) + startServing(fileServeFunction, connection, req, uri.args) end local function onReceive(connection, payload) @@ -89,18 +116,20 @@ return function (port) else args = {code = 400, errorString = "Bad Request"} end - connectionThread = coroutine.create(fileServeFunction) - coroutine.resume(connectionThread, connection, req, args) + startServing(fileServeFunction, connection, req, args) end end local function onSent(connection, payload) collectgarbage() if connectionThread then - local connectionThreadStatus = coroutine.status(connectionThread) + local connectionThreadStatus = coroutine.status(connectionThread) if connectionThreadStatus == "suspended" then -- Not finished sending file, resume. - coroutine.resume(connectionThread) + local status, err = coroutine.resume(connectionThread) + if not status then + print(err) + end elseif connectionThreadStatus == "dead" then -- We're done sending file. connection:close() From 8a195cb79833592546555a3013ddf81f832ac64d Mon Sep 17 00:00:00 2001 From: Philip Gladstone Date: Sat, 28 Nov 2015 12:22:20 -0500 Subject: [PATCH 2/5] Reduce memory requirements a bit and fix weird issue in node_info.lua example --- http/Thumbs.db | Bin 0 -> 8192 bytes http/node_info.lua | 6 ++++-- http/node_info.lua~ | 29 +++++++++++++++++++++++++++++ httpserver.lua | 31 ++++++++++++++++++++++--------- 4 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 http/Thumbs.db create mode 100644 http/node_info.lua~ diff --git a/http/Thumbs.db b/http/Thumbs.db new file mode 100644 index 0000000000000000000000000000000000000000..9707bc379f96ec6f642f124233766c24e741d296 GIT binary patch literal 8192 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".. attr .. ": " .. val .. "
    \n") + if val then + connection:send("
  • ".. attr .. ": " .. val .. "
  • \n") + end end return function (connection, req, args) collectgarbage() sendHeader(connection) connection:send('A Lua script sample

    Node info

      ') - majorVer, minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed = node.info(); + local majorVer, minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed = node.info(); sendAttr(connection, "NodeMCU version" , majorVer.."."..minorVer.."."..devVer) sendAttr(connection, "chipid" , chipid) sendAttr(connection, "flashid" , flashid) diff --git a/http/node_info.lua~ b/http/node_info.lua~ new file mode 100644 index 0000000..8f9d615 --- /dev/null +++ b/http/node_info.lua~ @@ -0,0 +1,29 @@ +local function sendHeader(connection) + connection:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nCache-Control: private, no-store\r\n\r\n") + +end + +local function sendAttr(connection, attr, val) + if val then + connection:send("
    • ".. attr .. ": " .. val .. "
    • \n") + end +end + +return function (connection, req, args) + collectgarbage() + sendHeader(connection) + connection:send('A Lua script sample

      Node info

        ') + local majorVer, minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed = node.info(); + --local x = (majorVer..".")..(minorVer..".")..devVer + sendAttr(connection, "NodeMCU version" , majorVer.."."..minorVer.."."..devVer) + sendAttr(connection, "chipid" , chipid) + sendAttr(connection, "flashid" , flashid) + sendAttr(connection, "flashsize" , flashsize) + sendAttr(connection, "flashmode" , flashmode) + sendAttr(connection, "flashspeed" , flashspeed) + sendAttr(connection, "node.heap()" , node.heap()) + sendAttr(connection, 'Memory in use (KB)' , collectgarbage("count")) + sendAttr(connection, 'IP address' , wifi.sta.getip()) + sendAttr(connection, 'MAC address' , wifi.sta.getmac()) + connection:send('
      ') +end diff --git a/httpserver.lua b/httpserver.lua index e0970c6..6695196 100644 --- a/httpserver.lua +++ b/httpserver.lua @@ -20,21 +20,34 @@ return function (port) local bufferedConnection = {} connectionThread = coroutine.create(function(fileServeFunction, connection, req, args) fileServeFunction(connection, req, args) - connection:flush() + if not connection:flush() then + connection:close() + connectionThread = nil + end end) function bufferedConnection:flush() - connection:send(table.concat(self.data, "")) - self.data = {} - self.size = 0 + if self.size > 0 then + connection:send(table.concat(self.data, "")) + self.data = {} + self.size = 0 + return true + end + return false end function bufferedConnection:send(payload) local l = payload:len() - if l + self.size > 1400 then - self:flush() - coroutine.yield() + if l + self.size > 1000 then + if self:flush() then + coroutine.yield() + end + end + if l > 800 then + connection:send(payload) + coroutine.yield() + else + table.insert(self.data, payload) + self.size = self.size + l end - table.insert(self.data, payload) - self.size = self.size + l end bufferedConnection.size = 0 bufferedConnection.data = {} From a54159b39fc8828dd0db3205059e4562c8789624 Mon Sep 17 00:00:00 2001 From: Philip Gladstone Date: Sat, 28 Nov 2015 12:23:22 -0500 Subject: [PATCH 3/5] Remove unused file --- http/node_info.lua~ | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 http/node_info.lua~ diff --git a/http/node_info.lua~ b/http/node_info.lua~ deleted file mode 100644 index 8f9d615..0000000 --- a/http/node_info.lua~ +++ /dev/null @@ -1,29 +0,0 @@ -local function sendHeader(connection) - connection:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nCache-Control: private, no-store\r\n\r\n") - -end - -local function sendAttr(connection, attr, val) - if val then - connection:send("
    • ".. attr .. ": " .. val .. "
    • \n") - end -end - -return function (connection, req, args) - collectgarbage() - sendHeader(connection) - connection:send('A Lua script sample

      Node info

        ') - local majorVer, minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed = node.info(); - --local x = (majorVer..".")..(minorVer..".")..devVer - sendAttr(connection, "NodeMCU version" , majorVer.."."..minorVer.."."..devVer) - sendAttr(connection, "chipid" , chipid) - sendAttr(connection, "flashid" , flashid) - sendAttr(connection, "flashsize" , flashsize) - sendAttr(connection, "flashmode" , flashmode) - sendAttr(connection, "flashspeed" , flashspeed) - sendAttr(connection, "node.heap()" , node.heap()) - sendAttr(connection, 'Memory in use (KB)' , collectgarbage("count")) - sendAttr(connection, 'IP address' , wifi.sta.getip()) - sendAttr(connection, 'MAC address' , wifi.sta.getmac()) - connection:send('
      ') -end From 9fee6ee8e8ede9c314363867f00bfb774f9cfc2f Mon Sep 17 00:00:00 2001 From: Philip Gladstone Date: Sat, 28 Nov 2015 16:36:53 -0500 Subject: [PATCH 4/5] Removed another unused file --- http/Thumbs.db | Bin 8192 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 http/Thumbs.db diff --git a/http/Thumbs.db b/http/Thumbs.db deleted file mode 100644 index 9707bc379f96ec6f642f124233766c24e741d296..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 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 Date: Sat, 28 Nov 2015 21:00:34 -0500 Subject: [PATCH 5/5] Handle the null write case --- httpserver.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/httpserver.lua b/httpserver.lua index 6695196..273eb16 100644 --- a/httpserver.lua +++ b/httpserver.lua @@ -18,9 +18,9 @@ return function (port) local function startServing(fileServeFunction, connection, req, args) local bufferedConnection = {} - connectionThread = coroutine.create(function(fileServeFunction, connection, req, args) - fileServeFunction(connection, req, args) - if not connection:flush() then + connectionThread = coroutine.create(function(fileServeFunction, bconnection, req, args) + fileServeFunction(bconnection, req, args) + if not bconnection:flush() then connection:close() connectionThread = nil end