diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp index 4223517f..08f74ed3 100644 --- a/src/output/output_http.cpp +++ b/src/output/output_http.cpp @@ -351,4 +351,76 @@ namespace Mist { execv(argarr[0], argarr); } + /// 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 6fe05c03..bdf00151 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; }; diff --git a/src/output/output_progressive_mp4.cpp b/src/output/output_progressive_mp4.cpp index 0afb0317..a424e245 100644 --- a/src/output/output_progressive_mp4.cpp +++ b/src/output/output_progressive_mp4.cpp @@ -424,77 +424,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::onHTTP() { if(H.method == "OPTIONS" || H.method == "HEAD"){ H.Clean(); @@ -527,7 +456,9 @@ namespace Mist { sortSet.insert(temp); } 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]; } H.Clean(); //make sure no parts of old requests are left in any buffers diff --git a/src/output/output_progressive_mp4.h b/src/output/output_progressive_mp4.h index 3f26812e..99f66ac2 100644 --- a/src/output/output_progressive_mp4.h +++ b/src/output/output_progressive_mp4.h @@ -27,7 +27,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); std::string DTSCMeta2MP4Header(uint64_t & size); void findSeekPoint(uint64_t byteStart, uint64_t & seekPoint, uint64_t headerSize);