HLS/HTTP fixes:

- Optimize URIReader class to not close connections if not needed
- reConnector now works for non-GET requests with GET params
- Chunk sending mode correctly kept for HLS
- Removed lots of H.Clean() from HLS that weren't needed
- Improved HTTP output class request handling logic
- Removed firstRun from HTTP output class; no longer needed
This commit is contained in:
Thulinma 2021-09-20 13:09:27 +02:00
parent 5774ce3b9e
commit 194b6e1388
5 changed files with 13 additions and 27 deletions

View file

@ -148,7 +148,7 @@ std::string &HTTP::Parser::BuildRequest(){
/// \todo Include POST variable handling for vars?
std::map<std::string, std::string>::iterator it;
if (protocol.size() < 5 || protocol[4] != '/'){protocol = "HTTP/1.0";}
if (method == "GET" && vars.size() && url.find('?') == std::string::npos){
if (method != "POST" && vars.size() && url.find('?') == std::string::npos){
builder = method + " " + Encodings::URL::encode(url, "/:=@[]") + allVars() + " " + protocol + "\r\n";
}else{
builder = method + " " + Encodings::URL::encode(url, "/:=@[]") + " " + protocol + "\r\n";
@ -277,9 +277,10 @@ void HTTP::Parser::SendResponse(std::string code, std::string message, Socket::C
void HTTP::Parser::StartResponse(std::string code, std::string message, const HTTP::Parser &request,
Socket::Connection &conn, bool bufferAllChunks){
std::string prot = request.protocol;
sendingChunks =
bool willSendChunks =
(!bufferAllChunks && request.protocol == "HTTP/1.1" && request.GetHeader("Connection") != "close");
CleanPreserveHeaders();
sendingChunks = willSendChunks;
protocol = prot;
if (sendingChunks){
SetHeader("Transfer-Encoding", "chunked");

View file

@ -45,13 +45,13 @@ namespace HTTP{
void URIReader::dataCallback(const char *ptr, size_t size){allData.append(ptr, size);}
bool URIReader::open(const HTTP::URL &uri){
close();
myURI = uri;
curPos = 0;
allData.truncate(0);
bufPos = 0;
if (!myURI.protocol.size() || myURI.protocol == "file"){
close();
if (!myURI.path.size() || myURI.path == "-"){
downer.getSocket().open(-1, fileno(stdin));
stateType = HTTP::Stream;

View file

@ -230,13 +230,11 @@ namespace Mist{
std::string sessId = H.GetVar("sessId");
if (H.url == "/crossdomain.xml"){
H.Clean();
H.SetHeader("Content-Type", "text/xml");
H.SetHeader("Server", APPIDENT);
H.setCORSHeaders();
if (method == "OPTIONS" || method == "HEAD"){
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
}
H.SetBody("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM "
@ -244,13 +242,11 @@ namespace Mist{
"cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" "
"/><site-control permitted-cross-domain-policies=\"all\"/></cross-domain-policy>");
H.SendResponse("200", "OK", myConn);
H.Clean(); // clean for any possible next requests
return;
}// crossdomain.xml
if (H.method == "OPTIONS"){
bool isTS = (HTTP::URL(H.url).getExt().substr(0, 3) != "m3u");
H.Clean();
H.setCORSHeaders();
if (isTS){
H.SetHeader("Content-Type", "video/mp2t");
@ -266,7 +262,6 @@ namespace Mist{
}
H.SetBody("");
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
}
@ -294,11 +289,9 @@ namespace Mist{
if (sscanf(tmpStr.c_str(), "/%zu_%zu/%" PRIu64 "_%" PRIu64 ".ts", &vidTrack, &audTrack, &from, &until) != 4){
if (sscanf(tmpStr.c_str(), "/%zu/%" PRIu64 "_%" PRIu64 ".ts", &vidTrack, &from, &until) != 3){
MEDIUM_MSG("Could not parse URL: %s", H.getUrl().c_str());
H.Clean();
H.setCORSHeaders();
H.SetBody("The HLS URL wasn't understood - what did you want, exactly?\n");
myConn.SendNow(H.BuildResponse("404", "URL mismatch"));
H.Clean(); // clean for any possible next requests
return;
}
userSelect.clear();
@ -314,12 +307,10 @@ namespace Mist{
}
if (M.getLive() && from < M.getFirstms(vidTrack)){
H.Clean();
H.setCORSHeaders();
H.SetBody("The requested fragment is no longer kept in memory on the server and cannot be "
"served.\n");
myConn.SendNow(H.BuildResponse("404", "Fragment out of range"));
H.Clean(); // clean for any possible next requests
WARN_MSG("Fragment @ %" PRIu64 " too old", from);
return;
}
@ -335,7 +326,6 @@ namespace Mist{
}
if (method == "OPTIONS" || method == "HEAD"){
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
}
@ -353,17 +343,14 @@ namespace Mist{
}else{
initialize();
std::string request = H.url.substr(H.url.find("/", 5) + 1);
H.Clean();
H.setCORSHeaders();
H.SetHeader("Content-Type", "application/vnd.apple.mpegurl");
if (!M.getValidTracks().size()){
H.SendResponse("404", "Not online or found", myConn);
H.Clean();
return;
}
if (method == "OPTIONS" || method == "HEAD"){
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
}
std::string manifest;
@ -373,7 +360,6 @@ namespace Mist{
size_t idx = atoi(request.substr(0, request.find("/")).c_str());
if (!M.getValidTracks().count(idx)){
H.SendResponse("404", "No corresponding track found", myConn);
H.Clean();
return;
}
@ -389,7 +375,6 @@ namespace Mist{
if (thisPacket.getTime() >= until){
stop();
wantRequest = true;
parseData = false;
// Ensure alignment of contCounters, to prevent discontinuities.
for (std::map<size_t, uint16_t>::iterator it = contCounters.begin(); it != contCounters.end(); it++){
@ -407,6 +392,7 @@ namespace Mist{
// Signal end of data
H.Chunkify("", 0, myConn);
H.Clean();
return;
}
// Invoke the generic TS output sendNext handler

View file

@ -14,7 +14,6 @@ namespace Mist{
idleInterval = 0;
idleLast = 0;
if (config->getString("ip").size()){myConn.setHost(config->getString("ip"));}
firstRun = true;
if (config->getString("prequest").size()){
myConn.Received().prepend(config->getString("prequest"));
}
@ -197,14 +196,11 @@ namespace Mist{
if (!isBlocking && !parseData){Util::sleep(100);}
return;
}
// If we can't read anything more and we're non-blocking, sleep some.
if (!firstRun && !myConn.spool()){
if (!isBlocking && !parseData){Util::sleep(100);}
return;
}
firstRun = false;
//Attempt to read a HTTP request, regardless of data being available
bool sawRequest = false;
while (H.Read(myConn)){
sawRequest = true;
std::string handler = getHandler();
if (handler != capa["name"].asStringRef() || H.GetVar("stream") != streamName){
INFO_MSG("Received request: %s => %s (%s)", H.getUrl().c_str(), handler.c_str(), H.GetVar("stream").c_str());
@ -307,8 +303,12 @@ namespace Mist{
if (!myConn){return;}
onHTTP();
idleLast = Util::bootMS();
if (!H.bufferChunks){H.Clean();}
// Prevent the clean as well as the loop when we're in the middle of handling a request now
if (!wantRequest){return;}
H.Clean();
}
// If we can't read anything more and we're non-blocking, sleep some.
if (!sawRequest && !myConn.spool() && !isBlocking && !parseData){Util::sleep(100);}
}
/// Default HTTP handler.

View file

@ -27,7 +27,6 @@ namespace Mist{
bool parseRange(std::string header, uint64_t &byteStart, uint64_t &byteEnd);
protected:
bool firstRun;
bool responded;
HTTP::Parser H;
HTTP::Websocket *webSock;