diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index e95ec274..454a9968 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -392,6 +392,78 @@ namespace Mist { return trustedProxies.count(ip) > 0; } /*LTS-END*/ + + /// Parses a "Range: " header, setting byteStart and byteEnd. + /// Assumes byteStart and byteEnd are initialized to their minimum respectively maximum values when the function is called. + /// On error, byteEnd is set to zero and the function return false. + bool HTTPOutput::parseRange(uint64_t & byteStart, uint64_t & byteEnd){ + std::string header = H.GetHeader("Range"); + if (header.size() < 6 || header.substr(0, 6) != "bytes="){ + byteEnd = 0; + WARN_MSG("Invalid range header: %s", header.c_str()); + return false; + } + header.erase(0, 6); + //Do parsing of the rest of the header... + if (header.size() && header[0] == '-'){ + //negative range = count from end + byteStart = 0; + for (unsigned int i = 1; i < header.size(); ++i){ + if (header[i] >= '0' && header[i] <= '9'){ + byteStart *= 10; + byteStart += header[i] - '0'; + continue; + } + break; + } + if (byteStart > byteEnd){ + //entire file if starting before byte zero + byteStart = 0; + }else{ + //start byteStart bytes before byteEnd + byteStart = byteEnd - byteStart; + } + MEDIUM_MSG("Range request: %" PRIu64 "-%" PRIu64 " (%s)", byteStart, byteEnd, header.c_str()); + return true; + } + + //Positive range + long long size = byteEnd; + byteEnd = 0; + byteStart = 0; + unsigned int i = 0; + for (; i < header.size(); ++i){ + if (header[i] >= '0' && header[i] <= '9'){ + byteStart *= 10; + byteStart += header[i] - '0'; + continue; + } + break; + } + if (header[i] != '-'){ + WARN_MSG("Invalid range header: %s", header.c_str()); + byteEnd = 0; + return false; + } + ++i; + if (i < header.size()){ + for (; i < header.size(); ++i){ + if (header[i] >= '0' && header[i] <= '9'){ + byteEnd *= 10; + byteEnd += header[i] - '0'; + continue; + } + break; + } + if (byteEnd > size){ + byteEnd = size; + } + }else{ + byteEnd = size; + } + MEDIUM_MSG("Range request: %" PRIu64 "-%" PRIu64 " (%s)", byteStart, byteEnd, header.c_str()); + return true; + } } diff --git a/src/output/output_http.h b/src/output/output_http.h index 001c52cf..daa91a6c 100644 --- a/src/output/output_http.h +++ b/src/output/output_http.h @@ -17,6 +17,7 @@ namespace Mist { static bool listenMode(){return false;} void reConnector(std::string & connector); std::string getHandler(); + bool parseRange(uint64_t & byteStart, uint64_t & byteEnd); protected: HTTP::Parser H; std::string getConnectedHost();//LTS diff --git a/src/output/output_progressive_mp4.cpp b/src/output/output_progressive_mp4.cpp index fb56076f..ae3ae8b8 100644 --- a/src/output/output_progressive_mp4.cpp +++ b/src/output/output_progressive_mp4.cpp @@ -524,78 +524,6 @@ namespace Mist{ //That's technically legal, of course. } -/// Parses a "Range: " header, setting byteStart, byteEnd and seekPoint using data from metadata and tracks to do -/// the calculations. -/// On error, byteEnd is set to zero. - void OutProgressiveMP4::parseRange(std::string header, uint64_t & byteStart, uint64_t & byteEnd, uint64_t & seekPoint, uint64_t headerSize){ - if (header.size() < 6 || header.substr(0, 6) != "bytes="){ - byteEnd = 0; - WARN_MSG("Invalid range header: %s", header.c_str()); - return; - } - header.erase(0, 6); - if (header.size() && header[0] == '-'){ - //negative range = count from end - byteStart = 0; - for (unsigned int i = 1; i < header.size(); ++i){ - if (header[i] >= '0' && header[i] <= '9'){ - byteStart *= 10; - byteStart += header[i] - '0'; - continue; - } - break; - } - if (byteStart > byteEnd){ - //entire file if starting before byte zero - byteStart = 0; - findSeekPoint(byteStart, seekPoint, headerSize); - return; - }else{ - //start byteStart bytes before byteEnd - byteStart = byteEnd - byteStart; - findSeekPoint(byteStart, seekPoint, headerSize); - return; - } - }else{ - long long size = byteEnd; - byteEnd = 0; - byteStart = 0; - unsigned int i = 0; - for (; i < header.size(); ++i){ - if (header[i] >= '0' && header[i] <= '9'){ - byteStart *= 10; - byteStart += header[i] - '0'; - continue; - } - break; - } - if (header[i] != '-'){ - WARN_MSG("Invalid range header: %s", header.c_str()); - byteEnd = 0; - return; - } - ++i; - if (i < header.size()){ - for (; i < header.size(); ++i){ - if (header[i] >= '0' && header[i] <= '9'){ - byteEnd *= 10; - byteEnd += header[i] - '0'; - continue; - } - break; - } - if (byteEnd > size){ - byteEnd = size; - } - }else{ - byteEnd = size; - } - MEDIUM_MSG("Range request: %" PRIu64 "-%" PRIu64 " (%s)", byteStart, byteEnd, header.c_str()); - findSeekPoint(byteStart, seekPoint, headerSize); - return; - } - } - void OutProgressiveMP4::sendFragmentHeader(){ uint64_t mdatSize = 8; MP4::MOOF moofBox; @@ -818,7 +746,9 @@ namespace Mist{ } if (!myMeta.live){ if (H.GetHeader("Range") != ""){ - parseRange(H.GetHeader("Range"), byteStart, byteEnd, seekPoint, headerSize); + if (parseRange(byteStart, byteEnd)){ + findSeekPoint(byteStart, seekPoint, headerSize); + } rangeType = H.GetHeader("Range")[0]; } } diff --git a/src/output/output_progressive_mp4.h b/src/output/output_progressive_mp4.h index 64d5482c..714d47fa 100644 --- a/src/output/output_progressive_mp4.h +++ b/src/output/output_progressive_mp4.h @@ -35,7 +35,6 @@ namespace Mist { OutProgressiveMP4(Socket::Connection & conn); ~OutProgressiveMP4(); static void init(Util::Config * cfg); - void parseRange(std::string header, uint64_t & byteStart, uint64_t & byteEnd, uint64_t & seekPoint, uint64_t headerSize); uint64_t mp4HeaderSize(uint64_t & fileSize, int fragmented = 0); std::string DTSCMeta2MP4Header(uint64_t & size, int fragmented = 0); //int fragmented values: 0 = non fragmented stream, 1 = frag stream main header