8 #define LOC QString("HTTPRange: ")
10 auto sumrange = [](uint64_t Cum,
HTTPRange Range) {
return ((Range.second + 1) - Range.first) + Cum; };
14 if (!Response ||
Request.isEmpty())
18 auto * data = std::get_if<HTTPData>(&(Response->
m_response));
20 int64_t size = data ? (*data)->size() :
file ? (*file)->size() : 0;
25 HTTPRanges& ranges = data ? (*data)->m_ranges : (*file)->m_ranges;
26 int64_t& partialsize = data ? (*data)->m_partialSize : (*file)->m_partialSize;
37 auto * data = std::get_if<HTTPData>(&(Response->
m_response));
39 int64_t size = data ? (*data)->size() :
file ? (*file)->size() : 0;
43 HTTPRanges& ranges = data ? (*data)->m_ranges : (*file)->m_ranges;
44 if (ranges.size() < 2)
47 auto & mime = data ? (*data)->m_mimeType : (*file)->m_mimeType;
49 for (
auto & range : ranges)
51 auto header = QString(
"\r\n--%1\r\nContent-Type: %2\r\nContent-Range: %3\r\n\r\n")
59 std::reverse(headers.begin(), headers.end());
60 int64_t headersize = 0;
61 for (
auto & header : headers)
62 headersize += header->size();
65 (*data)->m_multipartHeaders = headers;
66 (*data)->m_multipartHeaderSize = headersize;
70 (*file)->m_multipartHeaders = headers;
71 (*file)->m_multipartHeaderSize = headersize;
77 return QString(
"bytes %1-%2/%3").arg(Range.first).arg(Range.second).arg(Size);
84 if (Ranges.size() == 1)
92 auto * data = std::get_if<HTTPData>(&Data);
93 auto *
file = std::get_if<HTTPFile>(&Data);
97 int64_t partialsize = data ? (*data)->m_partialSize : (*file)->m_partialSize;
98 auto written =
static_cast<uint64_t
>(data ? (*data)->m_written : (*file)->m_written);
99 HTTPRanges& ranges = data ? (*data)->m_ranges : (*file)->m_ranges;
100 HTTPContents& headers = data ? (*data)->m_multipartHeaders : (*file)->m_multipartHeaders;
103 for (
const auto& range : ranges)
105 uint64_t newsum =
sumrange(oldsum, range);
106 if (oldsum <= written && written < newsum)
109 if ((oldsum == written) && !headers.empty())
111 result.first = headers.back();
116 ToWrite = std::min(Available,
static_cast<int64_t
>(newsum - written));
119 Offset =
static_cast<int64_t
>(range.first - oldsum);
125 if (((
static_cast<int64_t
>(written) + ToWrite) >= partialsize) && !headers.empty())
127 result.second = headers.back();
159 LOG(VB_HTTP, LOG_DEBUG,
LOC + QString(
"Parsing: '%1'").arg(
Request));
162 QStringList initial =
Request.toLower().split(
"=");
163 if (initial.size() != 2)
165 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Failed to parse ranges: '%1'").arg(
Request));
170 if (!initial.at(0).contains(
"bytes"))
172 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Unkown range units: '%1'").arg(initial.at(0)));
177 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
178 QStringList rangelist = initial.at(1).split(
",", QString::SkipEmptyParts);
180 QStringList rangelist = initial.at(1).split(
",", Qt::SkipEmptyParts);
184 if (rangelist.isEmpty())
186 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Failed to find ranges: '%1'").arg(initial.at(1)));
192 for (
auto & range : rangelist)
194 QStringList parts = range.split(
"-");
195 if (parts.size() != 2)
197 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Failed to parse range: '%1'").arg(range));
201 bool validrange =
false;
202 bool startvalid =
false;
203 bool endvalid =
false;
204 bool startstr = !parts.at(0).isEmpty();
205 bool endstr = !parts.at(1).isEmpty();
206 uint64_t start = parts.at(0).toULongLong(&startvalid);
207 uint64_t end = parts.at(1).toULongLong(&endvalid);
210 if (startstr && endstr && startvalid && endvalid)
212 validrange = ((end < static_cast<uint64_t>(TotalSize)) && (start <= end));
215 else if (startstr && startvalid)
217 end =
static_cast<uint64_t
>(TotalSize - 1);
218 validrange = start <= end;
221 else if (endstr && endvalid)
224 end =
static_cast<uint64_t
>(TotalSize) - 1;
225 start =
static_cast<uint64_t
>(TotalSize) - size;
226 validrange = start <= end;
231 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Invalid HTTP range: '%1'").arg(range));
235 ranges.emplace_back(start, end);
242 static const int s_overhead = 90;
243 if (ranges.size() > 1)
246 {
return (First.first == Second.first) && (First.second == Second.second); };
248 {
return First.first < Second.first; };
251 std::sort(ranges.begin(), ranges.end(), lessthan);
256 for (
const auto & range : ranges)
257 debug.append(QString(
"%1:%2").arg(range.first).arg(range.second));
258 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Sorted ranges: %1").arg(
debug.join(
" ")));
262 bool finished =
false;
266 for (
uint i = 0; i < (ranges.size() - 1); ++i)
268 if ((ranges[i].second + s_overhead) >= ranges[i + 1].first)
271 ranges[i + 1].first = ranges[i].first;
273 uint64_t end = std::max(ranges[i].second, ranges[i + 1].second);
274 ranges[i].second = ranges[i + 1].second = end;
278 auto last = std::unique(ranges.begin(), ranges.end(), equals);
279 ranges.erase(last, ranges.end());
284 PartialSize = std::accumulate(ranges.cbegin(), ranges.cend(),
static_cast<uint64_t
>(0),
sumrange);
290 for (
const auto & range : ranges)
291 debug.append(QString(
"%1:%2").arg(range.first).arg(range.second));
292 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Final ranges : %1").arg(
debug.join(
" ")));
293 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Bytes to send: %1").arg(PartialSize));