Skip to content

Commit

Permalink
Ufs serve fix - makes it work better on esp32cam (ai thinker style) (#…
Browse files Browse the repository at this point in the history
…21486)

* Add yield() in file listing, so watchdog does not trigger with very large folders

* update UFSServe function to be like download function.
This removes the use of server.streamFile, and provides a much more reliable download.
Make UFSServe always use this function, regardless of auth requirement.  (i.e. no use of the original in the original class, as it still uses streaming.)
Note that UFSServe is enab;ed with #define UFILESYS_STATIC_SERVING
  • Loading branch information
btsimonh committed May 24, 2024
1 parent e5521bb commit 3e0b70a
Showing 1 changed file with 65 additions and 11 deletions.
76 changes: 65 additions & 11 deletions tasmota/tasmota_xdrv_driver/xdrv_50_filesystem.ino
Original file line number Diff line number Diff line change
Expand Up @@ -889,15 +889,20 @@ void UFSRename(void) {
*/
#include "detail/RequestHandlersImpl.h"

//#define SERVING_DEBUG

// class to allow us to request auth when required.
// StaticRequestHandler is in the above header
class StaticRequestHandlerAuth : public StaticRequestHandler {
public:
StaticRequestHandlerAuth(FS& fs, const char* path, const char* uri, const char* cache_header):
StaticRequestHandlerAuth(FS& fs, const char* path, const char* uri, const char* cache_header, bool requireAuth):
StaticRequestHandler(fs, path, uri, cache_header)
{
_requireAuth = requireAuth;
}

bool _requireAuth;

// we replace the handle method,
// and look for authentication only if we would serve the file.
// if we check earlier, then we will reject as unauth even though a later
Expand All @@ -906,8 +911,10 @@ public:
if (!canHandle(requestMethod, requestUri))
return false;

log_v("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());

//log_v("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
#ifdef SERVING_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handle: request=%s _uri=%s"), requestUri.c_str(), _uri.c_str());
#endif
String path(_path);

if (!_isFile) {
Expand All @@ -919,8 +926,9 @@ public:
// Append whatever follows this URI in request to get the file path.
path += requestUri.substring(_baseUriLength);
}
log_v("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);

#ifdef SERVING_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handle: path=%s, isFile=%d"), path.c_str(), _isFile);
#endif
String contentType = getContentType(path);

// look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for
Expand All @@ -932,19 +940,63 @@ public:
}

File f = _fs.open(path, "r");
if (!f || !f.available())
if (!f || !f.available()){
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler missing file?"));
return false;

if (!WebAuthenticate()) {
}
#ifdef SERVING_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler file open %d"), f.available());
#endif
if (_requireAuth && !WebAuthenticate()) {
#ifdef SERVING_DEBUG
AddLog(LOG_LEVEL_ERROR, PSTR("UFS: serv of %s denied"), requestUri.c_str());
#endif
server.requestAuthentication();
return true;
}

if (_cache_header.length() != 0)
server.sendHeader("Cache-Control", _cache_header);

server.streamFile(f, contentType);
#ifdef SERVING_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler sending"));
#endif
uint8_t buff[512];
uint32_t bread;
uint32_t flen = f.available();
WiFiClient download_Client = server.client();
server.setContentLength(flen);
server.send(200, contentType, "");

// transfer is about 150kb/s
uint32_t cnt = 0;
while (f.available()) {
bread = f.read(buff, sizeof(buff));
cnt += bread;
#ifdef SERVING_DEBUG
//AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler sending %d/%d"), cnt, flen);
#endif
uint32_t bw = download_Client.write((const char*)buff, bread);
if (!bw) { break; }
yield();
}
#ifdef SERVING_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler sent %d/%d"), cnt, flen);
#endif

if (cnt != flen){
AddLog(LOG_LEVEL_ERROR, PSTR("UFS: ::handler incomplete file send: sent %d/%d"), cnt, flen);
}

// It does seem that on lesser ESP32, this causes a problem? A lockup...
//server.streamFile(f, contentType);

f.close();
download_Client.stop();

#ifdef SERVING_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("UFS: ::handler done"));
#endif
return true;
}
};
Expand All @@ -959,9 +1011,9 @@ void UFSServe(void) {
if (Webserver) { // fail if no Webserver yet.
StaticRequestHandlerAuth *staticHandler;
if (noauth && *noauth == '1'){
staticHandler = (StaticRequestHandlerAuth *) new StaticRequestHandler(*ffsp, fpath, url, (char *)nullptr);
staticHandler = new StaticRequestHandlerAuth(*ffsp, fpath, url, (char *)nullptr, false);
} else {
staticHandler = new StaticRequestHandlerAuth(*ffsp, fpath, url, (char *)nullptr);
staticHandler = new StaticRequestHandlerAuth(*ffsp, fpath, url, (char *)nullptr, true);
}
if (staticHandler) {
//Webserver->serveStatic(url, *ffsp, fpath);
Expand Down Expand Up @@ -1319,6 +1371,8 @@ void UfsListDir(char *path, uint8_t depth) {
HtmlEscape(name).c_str(), tstr.c_str(), entry.size(), delpath, editpath);
}
entry.close();

yield(); // trigger watchdog reset
}
}
dir.close();
Expand Down

0 comments on commit 3e0b70a

Please sign in to comment.