#include "http_server.h" HTTPServer::HTTPServer(Player* p, Controller* c) { _player = p; _controller = c; _http_server = new ESP8266WebServer(80); //_http_server->onFileUpload([&]() { _handle_upload(); yield();}); _http_server->on("/upload", HTTP_POST, [&]() { _http_server->sendHeader("Connection", "close"); _http_server->send(200, "text/plain", "OK"); }, [&]() { _handle_upload(); yield(); }); _http_server->on("/", HTTP_GET, [&](){ _handle_index(); }); _http_server->on("/status", HTTP_GET, [&](){ _handle_status(); }); _http_server->begin(); MDNS.addService("http", "tcp", 80); } void HTTPServer::_handle_upload() { // https://www.gnu.org/software/tar/manual/html_node/Standard.html // https://www.mkssoftware.com/docs/man4/tar.4.asp HTTPUpload* upload = &_http_server->upload(); DEBUG("_handle_upload Status: %d, length: %d\n", upload->status, upload->currentSize); if (upload->status == UPLOAD_FILE_START) { _chunk = new uint8_t[512]; _chunk_length = 0; _upload_position = 0; _file_size = 0; _file_size_done = 0; _need_header = true; } if (upload->status == UPLOAD_FILE_END || upload->status == UPLOAD_FILE_ABORTED) { // Close the file delete _chunk; return; } uint32_t upload_offset = 0; while (upload_offset < upload->currentSize) { // Load a chunk if (_chunk_length < 512 && upload->currentSize > upload_offset) { uint16_t needed = 512 - _chunk_length; if (needed > upload->currentSize - upload_offset) needed = upload->currentSize - upload_offset; memcpy(_chunk + _chunk_length, upload->buf + upload_offset, needed); _chunk_length += needed; upload_offset += needed; _upload_position += needed; if (_chunk_length == 512) { // Process chunk DEBUG("Chunk.\n"); if (_need_header) { if (_chunk[257]=='u'&&_chunk[258]=='s'&&_chunk[259]=='t'&&_chunk[260]=='a'&&_chunk[261]=='r') { DEBUG("It is a valid header, starting at 0x%X!\n", _upload_position-512); char filename[200]; strncpy(filename, (char*)_chunk, 100); DEBUG("filename: %s\n", filename); _file_size = 0; _file_size_done = 0; for (int i=0; i<11; i++) { //Serial.print(_header_buffer[124 + i]); _file_size = (_file_size<<3) + (_chunk[124 + i] - '0'); } DEBUG("filesize: %d\n", _file_size); uint8_t type = _chunk[156] - '0'; if (type==0) { DEBUG("Is a file.\n"); } else if (type==5) { DEBUG("Is a directory.\n"); } else { ERROR("Unknown file type %d\n", type); } _need_header = (type==5 || _file_size==0); // No chunks needed for directories. } else { bool byte_found = false; for (int i=0; i<512; i++) byte_found = byte_found || _chunk[i]>0; if (!byte_found) { DEBUG("Empty chunk while looking for header -> ignoring.\n"); } else { ERROR("Invalid tar header: %c %c %c %c %c. Looking at header start offset 0x%X.\n", _chunk[257], _chunk[258], _chunk[259], _chunk[260], _chunk[261], _upload_position-512); } } } else { uint16_t bytes_to_write = _file_size - _file_size_done; if (bytes_to_write > 512) bytes_to_write=512; // Write bytes... _file_size_done += bytes_to_write; if (_file_size_done >= _file_size) _need_header = true; } _chunk_length = 0; } } } } void HTTPServer::_handle_index() { String response = String("ESMP3"); response.concat("Albums on SD card:"); std::list files = _player->ls("/", false, true, false); for(std::list::iterator it=files.begin(); it!=files.end(); it++) { response.concat("\n"); } response.concat("
"); response.concat(*it); response.concat("Play
"); _http_server->send(200, "text/html", response); } void HTTPServer::_handle_status() { _http_server->send(200, "application/json", _controller->get_status_json()); } void HTTPServer::loop() { _http_server->handleClient(); MDNS.update(); }