httpserver-connection.lua 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. -- httpserver-connection
  2. -- Part of nodemcu-httpserver, provides a buffered connection object that can handle multiple
  3. -- consecutive send() calls, and buffers small payloads to send once they get big.
  4. -- For this to work, it must be used from a coroutine and owner is responsible for the final
  5. -- flush() and for closing the connection.
  6. -- Author: Philip Gladstone, Marcos Kirsch
  7. BufferedConnection = {}
  8. -- parameter is the nodemcu-firmware connection
  9. function BufferedConnection:new(connection)
  10. local newInstance = {}
  11. newInstance.connection = connection
  12. newInstance.size = 0
  13. newInstance.data = {}
  14. function newInstance:flush()
  15. if self.size > 0 then
  16. self.connection:send(table.concat(self.data, ""))
  17. self.data = {}
  18. self.size = 0
  19. return true
  20. end
  21. return false
  22. end
  23. function newInstance:send(payload)
  24. local flushthreshold = 1400
  25. local newsize = self.size + payload:len()
  26. while newsize > flushthreshold do
  27. --STEP1: cut out piece from payload to complete threshold bytes in table
  28. local piecesize = flushthreshold - self.size
  29. local piece = payload:sub(1, piecesize)
  30. payload = payload:sub(piecesize + 1, -1)
  31. --STEP2: insert piece into table
  32. table.insert(self.data, piece)
  33. self.size = self.size + piecesize --size should be same as flushthreshold
  34. --STEP3: flush entire table
  35. if self:flush() then
  36. coroutine.yield()
  37. end
  38. --at this point, size should be 0, because the table was just flushed
  39. newsize = self.size + payload:len()
  40. end
  41. --at this point, whatever is left in payload should be <= flushthreshold
  42. local plen = payload:len()
  43. if plen == flushthreshold then
  44. --case 1: what is left in payload is exactly flushthreshold bytes (boundary case), so flush it
  45. table.insert(self.data, payload)
  46. self.size = self.size + plen
  47. if self:flush() then
  48. coroutine.yield()
  49. end
  50. elseif payload:len() then
  51. --case 2: what is left in payload is less than flushthreshold, so just leave it in the table
  52. table.insert(self.data, payload)
  53. self.size = self.size + plen
  54. --else, case 3: nothing left in payload, so do nothing
  55. end
  56. end
  57. return newInstance
  58. end
  59. return BufferedConnection