@@ -21,49 +21,80 @@ return function (conn)
21
21
local bufferedConnection = {}
22
22
function bufferedConnection :flush ()
23
23
if self .size > 0 then
24
+ -- uart.write(0, "httpserver: buff:flush(): size="..self.size.."\n")
24
25
connection :send (table.concat (self .data , " " ))
25
26
self .data = {}
26
- self .size = 0
27
+ self .size = 0
28
+ collectgarbage ()
27
29
return true
28
30
end
29
31
return false
30
32
end
33
+
31
34
function bufferedConnection :send (payload )
32
- local l = payload :len ()
33
- if l + self .size > 1000 then
35
+ local flushthreshold = 1400
36
+
37
+
38
+ local newsize = self .size + payload :len ()
39
+ while newsize > flushthreshold do
40
+ -- STEP1: cut out piece from payload to complete threshold bytes in table
41
+ local piecesize = flushthreshold - self .size
42
+ local piece = payload :sub (1 , piecesize )
43
+ payload = payload :sub (piecesize + 1 , - 1 )
44
+ -- STEP2: insert piece into table
45
+ table.insert (self .data , piece )
46
+ self .size = self .size + piecesize -- size should be same as flushthreshold
47
+ -- STEP3: flush entire table
34
48
if self :flush () then
35
- coroutine.yield ()
49
+ coroutine.yield ()
36
50
end
51
+ -- at this point, size should be 0, because the table was just flushed
52
+ newsize = self .size + payload :len ()
37
53
end
38
- if l > 800 then
39
- connection :send (payload )
40
- coroutine.yield ()
41
- else
54
+
55
+ -- at this point, whatever is left in payload should be <= flushthreshold
56
+ local plen = payload :len ()
57
+ if plen == flushthreshold then
58
+ -- case 1: what is left in payload is exactly flushthreshold bytes (boundary case), so flush it
59
+ table.insert (self .data , payload )
60
+ self .size = self .size + plen
61
+ if self :flush () then
62
+ coroutine.yield ()
63
+ end
64
+ elseif payload :len () then
65
+ -- case 2: what is left in payload is less than flushthreshold, so just leave it in the table
42
66
table.insert (self .data , payload )
43
- self .size = self .size + l
67
+ self .size = self .size + plen
68
+ -- else, case 3: nothing left in payload, so do nothing
44
69
end
45
70
end
71
+
46
72
bufferedConnection .size = 0
47
73
bufferedConnection .data = {}
48
74
49
75
connectionThread = coroutine.create (
50
76
function (fileServeFunction , bconnection , req , args )
77
+ -- uart.write(0, "httpserver: coroutine(): about to fileServeFunction \n")
51
78
fileServeFunction (bconnection , req , args )
52
79
if not bconnection :flush () then
53
80
connection :close ()
54
81
connectionThread = nil
55
82
end
83
+ -- uart.write(0, "httpserver: coroutine(): end\n")
56
84
end
57
85
)
58
86
59
87
local status , err = coroutine.resume (connectionThread , fileServeFunction , bufferedConnection , req , args )
60
88
if not status then
61
- print (err )
89
+ print (" Error: " .. err )
62
90
end
63
91
collectgarbage ()
64
92
end
65
93
94
+
66
95
local function onRequest (connection , req )
96
+ -- uart.write(0, "httpserver: onRequest()\n")
97
+
67
98
collectgarbage ()
68
99
local method = req .method
69
100
local uri = req .uri
@@ -76,16 +107,14 @@ return function (conn)
76
107
uri .args = {code = 400 , errorString = " Bad Request" }
77
108
fileServeFunction = dofile (" httpserver-error.lc" )
78
109
else
79
- local fileExists = file .open (uri .file , " r" )
80
- file .close ()
110
+ local fileExists = file .exists (uri .file )
81
111
82
112
if not fileExists then
83
113
-- gzip check
84
- fileExists = file .open (uri .file .. " .gz" , " r" )
85
- file .close ()
114
+ fileExists = file .exists (uri .file .. " .gz" )
86
115
87
116
if fileExists then
88
- print (" gzip variant exists, serving that one" )
117
+ -- print("gzip variant exists, serving that one")
89
118
uri .file = uri .file .. " .gz"
90
119
uri .isGzipped = true
91
120
end
@@ -107,15 +136,20 @@ return function (conn)
107
136
end
108
137
end
109
138
end
139
+ -- uart.write(0, "httpserver: onRequest(): about to start serving\n")
140
+
110
141
startServing (fileServeFunction , connection , req , uri .args )
142
+ -- uart.write(0, "httpserver: onRequest() end\n")
143
+
111
144
end
112
145
113
146
local tmp_payload = nil
114
147
local bBodyMissing = nil
115
148
149
+
116
150
local function onReceive (connection , payload )
117
151
collectgarbage ()
118
-
152
+ -- uart.write(0, "httpserver: onReceive()\n")
119
153
-- collect data packets until the size of http body meets the Content-Length stated in header
120
154
if payload :find (" Content%-Length:" ) or bBodyMissing then
121
155
if tmp_payload then
@@ -127,33 +161,14 @@ return function (conn)
127
161
bBodyMissing = true
128
162
return
129
163
else
130
- print (" HTTP packet assembled! size: " ..# tmp_payload )
164
+ -- print("HTTP packet assembled! size: "..#tmp_payload)
131
165
payload = tmp_payload
132
166
tmp_payload , bBodyMissing = nil
133
167
end
134
168
end
135
169
136
170
137
- local conf = {}
138
- if file .open (" httpserver-conf-default.lc" , " r" ) == nil then
139
- print (" httpserver-conf-default.lc (default wifi config) not found, creating..." )
140
- conf = dofile (" httpserver-confmakedefault.lc" )
141
- dofile (" httpserver-confwrite.lc" )(conf , " httpserver-conf-default.lua" )
142
- dofile (" compile.lc" )(" httpserver-conf-default.lua" )
143
- end
144
- file .close ()
145
-
146
- -- check if the user config file exists, if not save the default config to it
147
- if file .open (" httpserver-conf.lc" , " r" ) == nil then
148
- print (" httpserver-conf.lc (user httpserver config) not found, creating from default..." )
149
- conf = dofile (" httpserver-confmakedefault.lc" )
150
- dofile (" httpserver-confwrite.lc" )(conf , " httpserver-conf.lua" )
151
- dofile (" compile.lc" )(" httpserver-conf.lua" )
152
- end
153
- file .close ()
154
-
155
-
156
- local conf = dofile (" httpserver-conf.lc" )
171
+ local conf = dofile (" confload.lc" )(" httpserver-conf.lc" )
157
172
local auth
158
173
local user = " Anonymous"
159
174
@@ -181,30 +196,41 @@ return function (conn)
181
196
end
182
197
startServing (fileServeFunction , connection , req , args )
183
198
end
199
+ -- uart.write(0, "httpserver: onReceive() end\n")
184
200
end
185
201
186
202
local function onSent (connection , payload )
203
+ -- uart.write(0, "httpserver: onSent()\n")
187
204
collectgarbage ()
188
205
if connectionThread then
189
206
local connectionThreadStatus = coroutine.status (connectionThread )
190
207
if connectionThreadStatus == " suspended" then
191
208
-- Not finished sending file, resume.
209
+ -- uart.write(0, "httpserver: onSent(): about to resume coroutine\n")
192
210
local status , err = coroutine.resume (connectionThread )
193
211
if not status then
194
- print (err )
212
+ print (" Error: " .. err )
195
213
end
196
214
elseif connectionThreadStatus == " dead" then
197
215
-- We're done sending file.
198
216
connection :close ()
199
217
connectionThread = nil
200
218
end
201
219
end
220
+ -- uart.write(0, "httpserver: onSent() end\n")
221
+
202
222
end
203
223
204
224
local function install (connection )
205
225
connection :on (" receive" , onReceive )
206
226
connection :on (" sent" , onSent )
227
+ connection :on (" disconnection" ,function (c )
228
+ if connectionThread then
229
+ connectionThread = nil
230
+ collectgarbage ()
231
+ end
232
+ end )
207
233
end
208
234
209
- return detect , install , onReceive
235
+ return { detect = detect , install = install , onReceive = onReceive }
210
236
end
0 commit comments