mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
httpd: parse a configuration upload once the whole request has arrived
Saving the configuration works in Chrome and fails in Firefox, and the difference is only how each browser splits the request. The handler erased the config sector as soon as the request started and then parsed the multipart body one TCP segment at a time, which requires every boundary and every part header to fall inside a single segment. Firefox splits inside a part header, so the parser lost its place and the erased sector was left holding a truncated body or nothing at all. A single-burst scripted post lost the whole body the same way. The configuration is limited to two kilobytes, so the whole request body now accumulates in xdata and is parsed only after the closing boundary has arrived. The parts are walked in one pass, the part carrying a filename is written to a freshly erased sector, and the client receives a 200 instead of the previous silent close. No segmentation can confuse this, since the parser only ever sees a complete body. Locating the closing boundary first also bounds the walk over the parts, since none can lie beyond it, so the length of the buffer is no longer the bound and the test for the two trailing dashes is unnecessary. The walk matches at offsets inside a buffer that is not terminated, so neither existing helper fits: strcmp() goes on to compare the byte after the match and is_word_x() demands a separator there. Add strstart() and strstart_x() for that case, and use strlen_x() for the boundary length. The firmware upload path still streams, since a megabyte cannot be buffered, and is untouched.
This commit is contained in:
@@ -360,6 +360,32 @@ char strcmp(register __xdata const uint8_t *a, register __code const uint8_t *b)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* True when b is a prefix of a. Unlike strcmp() the byte after the match is not
|
||||
* compared, and unlike is_word_x() it need not be a separator.
|
||||
*/
|
||||
bool strstart(__xdata const uint8_t *a, __code const uint8_t *b)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
while (b[i] && (b[i] == a[i]))
|
||||
i++;
|
||||
|
||||
return !b[i];
|
||||
}
|
||||
|
||||
|
||||
bool strstart_x(__xdata const uint8_t *a, __xdata const uint8_t *b)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
while (b[i] && (b[i] == a[i]))
|
||||
i++;
|
||||
|
||||
return !b[i];
|
||||
}
|
||||
|
||||
|
||||
void print_short(uint16_t a)
|
||||
{
|
||||
// allocating the registers first improves the sdcc code here
|
||||
|
||||
Reference in New Issue
Block a user