Generalized byte range request parsing
This commit is contained in:
parent
fc707da6b0
commit
105b1677d1
4 changed files with 76 additions and 73 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue