parseIOS method

Future<void> parseIOS(
  1. Socket socket,
  2. Uri uri,
  3. List<String> responseHeaders,
  4. int requestRangeStart,
  5. int requestRangeEnd,
  6. Map<String, String> headers,
)

Parses and responds to range requests on iOS.

Handles segmented download and response for large files.

Implementation

Future<void> parseIOS(
  Socket socket,
  Uri uri,
  List<String> responseHeaders,
  int requestRangeStart,
  int requestRangeEnd,
  Map<String, String> headers,
) async {
  if ((requestRangeStart == 0 && requestRangeEnd == 1) ||
      requestRangeEnd == -1) {
    DownloadTask task =
        DownloadTask(uri: uri, startRange: 0, endRange: 1, headers: headers);
    Uint8List? data = await cache(task);
    int contentLength = 0;
    if (data != null) {
      contentLength = int.tryParse(Utf8Codec().decode(data)) ?? 0;
    }
    if (contentLength == 0) {
      contentLength = await head(uri, headers: headers);
      String filePath =
          '${await FileExt.createCachePath(task.uri.generateMd5)}'
          '/${task.saveFileName}';
      File file = File(filePath);
      file.writeAsString(contentLength.toString());
      LruCacheSingleton().storagePut(task.matchUrl, file);
    }
    if (requestRangeStart == 0 && requestRangeEnd == 1) {
      responseHeaders.add('content-range: bytes 0-1/$contentLength');
      await socket.append(responseHeaders.join('\r\n'));
      await socket.append([0]);
      await socket.close();
      return;
    } else if (requestRangeEnd == -1) {
      requestRangeEnd = contentLength - 1;
    }
  }

  int contentLength = requestRangeEnd - requestRangeStart + 1;
  responseHeaders.add('content-length: $contentLength');
  await socket.append(responseHeaders.join('\r\n'));
  logD('content-range:$requestRangeStart-$requestRangeEnd');
  logD('content-length:$contentLength');

  bool downloading = true;
  int startRange =
      requestRangeStart - (requestRangeStart % Config.segmentSize);
  int endRange = startRange + Config.segmentSize - 1;
  int retry = 3;
  while (downloading) {
    DownloadTask task = DownloadTask(
      uri: uri,
      startRange: startRange,
      endRange: endRange,
      headers: headers,
    );
    logD('Request range:${task.startRange}-${task.endRange}');

    Uint8List? data = await cache(task);
    if (data == null) {
      concurrent(task, headers);
      task.priority += 10;
      data = await download(task);
    }
    if (data == null) {
      retry--;
      if (retry == 0) {
        downloading = false;
        break;
      }
      continue;
    }

    int startIndex = 0;
    int? endIndex;
    if (startRange < requestRangeStart) {
      startIndex = requestRangeStart - startRange;
    }
    if (endRange > requestRangeEnd) {
      endIndex = requestRangeEnd - startRange + 1;
    }
    data = data.sublist(startIndex, endIndex);
    socket.done.then((value) {
      downloading = false;
    }).catchError((e) {
      downloading = false;
    });
    bool success = await socket.append(data);
    if (!success) downloading = false;
    startRange += Config.segmentSize;
    endRange = startRange + Config.segmentSize - 1;
    if (startRange > requestRangeEnd) {
      downloading = false;
    }
  }
}