Skip to content

Commit 3a41e4d

Browse files
committed
[iec] loading media via HTTP is almost as fast as from SD now!
1 parent 9279775 commit 3a41e4d

File tree

5 files changed

+62
-44
lines changed

5 files changed

+62
-44
lines changed

lib/device/iec/drive.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ bool iecDrive::sendFile()
11551155
{
11561156
uint32_t count = 0, startpos;
11571157

1158-
uint8_t buf[128];
1158+
uint8_t buf[256];
11591159
uint16_t load_address = 0;
11601160
uint16_t sys_address = 0;
11611161

lib/meatloaf/disk/d64.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ bool D64MStream::seekEntry(std::string filename)
213213

214214
//Debug_printv("index[%d] track[%d] sector[%d] filename[%s] entry.filename[%.16s]", index, track, sector, filename.c_str(), entryFilename.c_str());
215215

216-
// Debug_printv("filename[%s] entry[%s]", filename.c_str(), entryFilename.c_str());
216+
//Debug_printv("filename[%s] entry[%s]", filename.c_str(), entryFilename.c_str());
217217

218218
if (filename == entryFilename) // Match exact
219219
{
@@ -257,8 +257,8 @@ bool D64MStream::seekEntry(uint16_t index)
257257
uint16_t sectorOffset = index / 8;
258258
uint16_t entryOffset = (index % 8) * 32;
259259

260-
// Debug_printv("----------");
261-
// Debug_printv("index[%d] sectorOffset[%d] entryOffset[%d] entry_index[%d]", index, sectorOffset, entryOffset, entry_index);
260+
//Debug_printv("----------");
261+
//Debug_printv("index[%d] sectorOffset[%d] entryOffset[%d] entry_index[%d]", index, sectorOffset, entryOffset, entry_index);
262262

263263
if (index == 0 || index != entry_index)
264264
{
@@ -297,7 +297,7 @@ bool D64MStream::seekEntry(uint16_t index)
297297
if (next_track == 0)
298298
return false;
299299

300-
// Debug_printv("Follow link track[%d] sector[%d] entryOffset[%d]", next_track, next_sector, entryOffset);
300+
//Debug_printv("Follow link track[%d] sector[%d] entryOffset[%d]", next_track, next_sector, entryOffset);
301301
if (!seekSector(next_track, next_sector, entryOffset))
302302
return false;
303303
}
@@ -312,7 +312,8 @@ bool D64MStream::seekEntry(uint16_t index)
312312
next_sector = entry.next_sector;
313313
}
314314

315-
// Debug_printv("r[%d] file_type[%02X] file_name[%.16s]", r, entry.file_type, entry.filename);
315+
//std::string e = mstr::toHex((uint8_t *)&entry, sizeof(entry));
316+
//Debug_printv("file_type[%02X] file_name[%.16s] entry[%s]", entry.file_type, entry.filename, e.c_str());
316317

317318
// if ( next_track == 0 && next_sector == 0xFF )
318319
entry_index = index + 1;
@@ -425,15 +426,15 @@ bool D64MStream::seekPath(std::string path)
425426
// return D64Image.seekFile(containerIStream, path);
426427
if (mstr::endsWith(path, "#")) // Direct Access Mode
427428
{
428-
Debug_printv("Direct Access Mode track[1] sector[0] path[%s]", path.c_str());
429+
//Debug_printv("Direct Access Mode track[1] sector[0] path[%s]", path.c_str());
429430
seekCalled = false;
430431
return seekSector(1, 0);
431432
}
432433
else if (seekEntry(path))
433434
{
434435
// auto entry = containerImage->entry;
435436
auto type = decodeType(entry.file_type).c_str();
436-
Debug_printv("filename[%.16s] type[%s] start_track[%d] start_sector[%d]", entry.filename, type, entry.start_track, entry.start_sector);
437+
//Debug_printv("filename[%.16s] type[%s] start_track[%d] start_sector[%d]", entry.filename, type, entry.start_track, entry.start_sector);
437438

438439
// Calculate file size
439440
uint8_t t = entry.start_track;
@@ -443,7 +444,7 @@ bool D64MStream::seekPath(std::string path)
443444
// Set position to beginning of file
444445
bool r = seekSector(t, s);
445446

446-
Debug_printv("blocks[%d] size[%d] available[%d] r[%d]", entry.blocks, _size, available(), r);
447+
//Debug_printv("blocks[%d] size[%d] available[%d] r[%d]", entry.blocks, _size, available(), r);
447448

448449
return r;
449450
}

lib/meatloaf/meat_media.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,11 @@ class ImageBroker {
219219
// Are we at the root of the pathInStream?
220220
if ( newFile->pathInStream == "")
221221
{
222-
Debug_printv("DIRECTORY [%s]", url.c_str());
222+
//Debug_printv("DIRECTORY [%s]", url.c_str());
223223
}
224224
else
225225
{
226-
Debug_printv("SINGLE FILE [%s]", url.c_str());
226+
//Debug_printv("SINGLE FILE [%s]", url.c_str());
227227
}
228228

229229
repo.insert(std::make_pair(url, newStream));

lib/meatloaf/network/http.cpp

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -220,17 +220,19 @@ bool MeatHttpClient::HEAD(std::string dstUrl) {
220220
return rc;
221221
}
222222

223-
bool MeatHttpClient::processRedirectsAndOpen(int range) {
223+
bool MeatHttpClient::processRedirectsAndOpen(uint32_t position, uint32_t size) {
224224
wasRedirected = false;
225-
_size = -1;
226225

227226
//Debug_printv("reopening url[%s] from position:%d", url.c_str(), range);
228-
lastRC = openAndFetchHeaders(lastMethod, range);
227+
lastRC = openAndFetchHeaders(lastMethod, position, size);
228+
229+
if (lastRC == 206)
230+
isFriendlySkipper = true;
229231

230232
while(lastRC == HttpStatus_MovedPermanently || lastRC == HttpStatus_Found || lastRC == 303)
231233
{
232234
//Debug_printv("--- Page moved, doing redirect to [%s]", url.c_str());
233-
lastRC = openAndFetchHeaders(lastMethod, range);
235+
lastRC = openAndFetchHeaders(lastMethod, position, size);
234236
wasRedirected = true;
235237
}
236238

@@ -242,9 +244,9 @@ bool MeatHttpClient::processRedirectsAndOpen(int range) {
242244

243245
_is_open = true;
244246
_exists = true;
245-
_position = 0;
247+
_position = position;
246248

247-
Debug_printv("size[%d] avail[%d] isFriendlySkipper[%d] isText[%d] httpCode[%d] method[%d]", _size, available(), isFriendlySkipper, isText, lastRC, lastMethod);
249+
//Debug_printv("size[%d] avail[%d] isFriendlySkipper[%d] isText[%d] httpCode[%d] method[%d]", _size, available(), isFriendlySkipper, isText, lastRC, lastMethod);
248250

249251
return true;
250252
}
@@ -274,30 +276,32 @@ void MeatHttpClient::setOnHeader(const std::function<int(char*, char*)> &lambda)
274276
}
275277

276278
bool MeatHttpClient::seek(uint32_t pos) {
277-
if(pos==_position)
278-
return true;
279279

280280
if(isFriendlySkipper) {
281281

282282
if (_is_open) {
283283
// Read to end of the stream
284284
//Debug_printv("Skipping to end!");
285-
char c[256];
286-
while( esp_http_client_read(_http, c, 256) > 0 );
285+
while(1)
286+
{
287+
char c[HTTP_BLOCK_SIZE];
288+
int bytes = esp_http_client_read(_http, c, HTTP_BLOCK_SIZE);
289+
if ( bytes < HTTP_BLOCK_SIZE )
290+
break;
291+
}
287292
}
288293

289294
bool op = processRedirectsAndOpen(pos);
290295

291296
//Debug_printv("SEEK in HttpIStream %s: range request RC=%d", url.c_str(), lastRC);
292-
297+
293298
if(!op)
294299
return false;
295300

296301
// 200 = range not supported! according to https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
297302
if(lastRC == 206)
298303
{
299304
//Debug_printv("Seek successful");
300-
301305
_position = pos;
302306
return true;
303307
}
@@ -345,20 +349,24 @@ uint32_t MeatHttpClient::read(uint8_t* buf, uint32_t size) {
345349

346350
if (!_is_open) {
347351
Debug_printv("Opening HTTP Stream!");
348-
processRedirectsAndOpen(0);
352+
processRedirectsAndOpen(0, size);
349353
}
350354

351355
if (_is_open) {
352356
//Debug_printv("Reading HTTP Stream!");
353357
auto bytesRead= esp_http_client_read(_http, (char *)buf, size );
354358

355-
if(bytesRead>0) {
359+
if (bytesRead >= 0) {
356360
_position+=bytesRead;
361+
362+
if (bytesRead < size)
363+
openAndFetchHeaders(lastMethod, _position);
357364
}
358-
if(bytesRead<0)
365+
if (bytesRead < 0)
359366
return 0;
360367

361-
return bytesRead;
368+
//Debug_printv("size[%d] bytesRead[%d] _position[%d]", size, bytesRead, _position);
369+
return bytesRead;
362370
}
363371
return 0;
364372
};
@@ -378,34 +386,32 @@ uint32_t MeatHttpClient::write(const uint8_t* buf, uint32_t size) {
378386
return 0;
379387
};
380388

381-
int MeatHttpClient::openAndFetchHeaders(esp_http_client_method_t meth, int resume) {
389+
int MeatHttpClient::openAndFetchHeaders(esp_http_client_method_t method, uint32_t position, uint32_t size) {
382390

383391
if ( url.size() < 5)
384392
return 0;
385393

386394
// Set URL and Method
387395
mstr::replaceAll(url, " ", "%20");
388396
esp_http_client_set_url(_http, url.c_str());
389-
esp_http_client_set_method(_http, meth);
397+
esp_http_client_set_method(_http, method);
390398

391399
// Set Headers
392400
for (const auto& pair : headers) {
393401
std::cout << pair.first << ": " << pair.second << std::endl;
394402
esp_http_client_set_header(_http, pair.first.c_str(), pair.second.c_str());
395403
}
396404

405+
// Set Range Header
406+
char str[40];
407+
snprintf(str, sizeof str, "bytes=%lu-%lu", position, (position + size + 5));
408+
esp_http_client_set_header(_http, "Range", str);
409+
//Debug_printv("seeking range[%s] url[%s]", str, url.c_str());
410+
397411
// POST
398412
// const char *post_data = "{\"field1\":\"value1\"}";
399413
// esp_http_client_set_post_field(client, post_data, strlen(post_data));
400414

401-
402-
if(resume > 0) {
403-
char str[40];
404-
snprintf(str, sizeof str, "bytes=%lu-", (unsigned long)resume);
405-
esp_http_client_set_header(_http, "range", str);
406-
//Debug_printv("seeking range[%s]", str);
407-
}
408-
409415
//Debug_printv("--- PRE OPEN");
410416
esp_err_t rc = esp_http_client_open(_http, 0); // or open? It's not entirely clear...
411417

@@ -417,7 +423,7 @@ int MeatHttpClient::openAndFetchHeaders(esp_http_client_method_t meth, int resum
417423
if(_size == -1 && lengthResp > 0) {
418424
// only if we aren't chunked!
419425
_size = lengthResp;
420-
_position = 0;
426+
_position = position;
421427
}
422428
}
423429

@@ -433,6 +439,7 @@ esp_err_t MeatHttpClient::_http_event_handler(esp_http_client_event_t *evt)
433439
case HTTP_EVENT_ERROR: // This event occurs when there are any errors during execution
434440
Debug_printv("HTTP_EVENT_ERROR");
435441
meatClient->_error = 1;
442+
meatClient->close();
436443
break;
437444

438445
case HTTP_EVENT_ON_CONNECTED: // Once the HTTP has been connected to the server, no data exchange has been performed
@@ -447,15 +454,25 @@ esp_err_t MeatHttpClient::_http_event_handler(esp_http_client_event_t *evt)
447454
// Does this server support resume?
448455
// Accept-Ranges: bytes
449456

450-
if (mstr::equals("Accept-Ranges", evt->header_key, false))
457+
// if (mstr::equals("Accept-Ranges", evt->header_key, false))
458+
// {
459+
// if(meatClient != nullptr) {
460+
// meatClient->isFriendlySkipper = mstr::equals("bytes", evt->header_value,false);
461+
// Debug_printv("Accept-Ranges: %s",evt->header_value);
462+
// }
463+
// }
464+
if (mstr::equals("Content-Range", evt->header_key, false))
451465
{
466+
//Debug_printv("Content-Range: %s",evt->header_value);
452467
if(meatClient != nullptr) {
453-
meatClient->isFriendlySkipper = mstr::equals("bytes", evt->header_value,false);
454-
//Debug_printv("* Ranges info present '%s', comparison=%d!",evt->header_value, strcmp("bytes", evt->header_value)==0);
468+
meatClient->isFriendlySkipper = true;
469+
auto cr = util_tokenize(evt->header_value, '/');
470+
if( cr.size() > 1 )
471+
meatClient->_size = std::stoi(cr[1]);
455472
}
456473
}
457474
// what can we do UTF8<->PETSCII on this stream?
458-
else if (mstr::equals("Content-Type", evt->header_key, false))
475+
if (mstr::equals("Content-Type", evt->header_key, false))
459476
{
460477
std::string asString = evt->header_value;
461478
bool isText = mstr::isText(asString);

lib/meatloaf/network/http.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
class MeatHttpClient {
2929
esp_http_client_handle_t _http = nullptr;
3030
static esp_err_t _http_event_handler(esp_http_client_event_t *evt);
31-
int openAndFetchHeaders(esp_http_client_method_t meth, int resume = 0);
31+
int openAndFetchHeaders(esp_http_client_method_t method, uint32_t position, uint32_t size = HTTP_BLOCK_SIZE);
3232
esp_http_client_method_t lastMethod;
3333
std::function<int(char*, char*)> onHeader = [] (char* key, char* value){
3434
//Debug_printv("HTTP_EVENT_ON_HEADER, key=%s, value=%s", key, value);
@@ -81,7 +81,7 @@ class MeatHttpClient {
8181
bool PUT(std::string url);
8282
bool HEAD(std::string url);
8383

84-
bool processRedirectsAndOpen(int range);
84+
bool processRedirectsAndOpen(uint32_t position, uint32_t size = HTTP_BLOCK_SIZE);
8585
bool open(std::string url, esp_http_client_method_t meth);
8686
void close();
8787
void setOnHeader(const std::function<int(char*, char*)> &f);

0 commit comments

Comments
 (0)