From cdcb71d8a86448b5347ad71279defdd0c8f6b2a0 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Mon, 18 Mar 2013 17:38:01 +0100 Subject: [PATCH] Added support for proper range handling to HTTP-based fragmented protocols (Smooth, Live, Dynamic). --- src/connectors/conn_http.cpp | 15 +++++++++++++++ src/connectors/conn_http_dynamic.cpp | 19 +++++++++++++++++++ src/connectors/conn_http_live.cpp | 20 +++++++++++++++++++- src/connectors/conn_http_smooth.cpp | 19 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/connectors/conn_http.cpp b/src/connectors/conn_http.cpp index 5dfb55ad..71897f86 100644 --- a/src/connectors/conn_http.cpp +++ b/src/connectors/conn_http.cpp @@ -269,6 +269,7 @@ namespace Connector_HTTP { connconn[uid]->conn->SendNow(request); connconn[uid]->lastuse = 0; unsigned int timeout = 0; + unsigned int retries = 0; //wait for a response while (connconn.count(uid) && connconn[uid]->conn->connected() && conn->connected()){ conn->spool(); @@ -285,6 +286,20 @@ namespace Connector_HTTP { } //check if the whole response was received if (H.Read(connconn[uid]->conn->Received().get())){ + //208 means the fragment is too new, retry in 2000ms + if (H.url == "208"){ + retries++; + if (retries >= 5){ + std::cout << "[5 retry-laters, cancelled]" << std::endl; + connconn[uid]->conn->close(); + return Handle_Timeout(H, conn); + } + connconn[uid]->lastuse = 0; + timeout = 0; + Util::sleep(2000); + connconn[uid]->conn->SendNow(request); + continue; + } break; //continue down below this while loop } }else{ diff --git a/src/connectors/conn_http_dynamic.cpp b/src/connectors/conn_http_dynamic.cpp index da9d3f71..5aeef6e4 100644 --- a/src/connectors/conn_http_dynamic.cpp +++ b/src/connectors/conn_http_dynamic.cpp @@ -233,6 +233,25 @@ namespace Connector_HTTP { #if DEBUG >= 5 printf("Quality: %s, Seg %d Frag %d\n", Quality.c_str(), Segment, ReqFragment); #endif + if (Strm.metadata.isMember("live")){ + int seekable = Strm.canSeekFrame(ReqFragment); + if (seekable < 0){ + HTTP_S.Clean(); + HTTP_S.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n"); + conn.SendNow(HTTP_S.BuildResponse("412", "Fragment out of range")); + HTTP_R.Clean(); //clean for any possible next requests + std::cout << "Fragment @ F" << ReqFragment << " too old (F" << Strm.metadata["keynum"][0u].asInt() << " - " << Strm.metadata["keynum"][Strm.metadata["keynum"].size() - 1].asInt() << ")" << std::endl; + continue; + } + if (seekable > 0){ + HTTP_S.Clean(); + HTTP_S.SetBody("Proxy, re-request this in a second or two.\n"); + conn.SendNow(HTTP_S.BuildResponse("208", "Ask again later")); + HTTP_R.Clean(); //clean for any possible next requests + std::cout << "Fragment @ F" << ReqFragment << " not available yet (F" << Strm.metadata["keynum"][0u].asInt() << " - " << Strm.metadata["keynum"][Strm.metadata["keynum"].size() - 1].asInt() << ")" << std::endl; + continue; + } + } std::stringstream sstream; sstream << "f " << ReqFragment << "\no \n"; ss.SendNow(sstream.str().c_str()); diff --git a/src/connectors/conn_http_live.cpp b/src/connectors/conn_http_live.cpp index 55c131d4..ac05057f 100644 --- a/src/connectors/conn_http_live.cpp +++ b/src/connectors/conn_http_live.cpp @@ -167,7 +167,25 @@ namespace Connector_HTTP { Segment = atoi(HTTP_R.url.substr(temp, HTTP_R.url.find("_", temp) - temp).c_str()); temp = HTTP_R.url.find("_", temp) + 1; int frameCount = atoi(HTTP_R.url.substr(temp, HTTP_R.url.find(".ts", temp) - temp).c_str()); - + if (Strm.metadata.isMember("live")){ + int seekable = Strm.canSeekFrame(Segment); + if (seekable < 0){ + HTTP_S.Clean(); + HTTP_S.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n"); + conn.SendNow(HTTP_S.BuildResponse("412", "Fragment out of range")); + HTTP_R.Clean(); //clean for any possible next requests + std::cout << "Fragment @ F" << Segment << " too old (F" << Strm.metadata["keynum"][0u].asInt() << " - " << Strm.metadata["keynum"][Strm.metadata["keynum"].size() - 1].asInt() << ")" << std::endl; + continue; + } + if (seekable > 0){ + HTTP_S.Clean(); + HTTP_S.SetBody("Proxy, re-request this in a second or two.\n"); + conn.SendNow(HTTP_S.BuildResponse("208", "Ask again later")); + HTTP_R.Clean(); //clean for any possible next requests + std::cout << "Fragment @ F" << Segment << " not available yet (F" << Strm.metadata["keynum"][0u].asInt() << " - " << Strm.metadata["keynum"][Strm.metadata["keynum"].size() - 1].asInt() << ")" << std::endl; + continue; + } + } std::stringstream sstream; sstream << "f " << Segment << "\n"; for (int i = 0; i < frameCount; i++){ diff --git a/src/connectors/conn_http_smooth.cpp b/src/connectors/conn_http_smooth.cpp index d52719e3..9d0548ec 100644 --- a/src/connectors/conn_http_smooth.cpp +++ b/src/connectors/conn_http_smooth.cpp @@ -166,6 +166,25 @@ namespace Connector_HTTP { } tempStr = tempStr.substr(tempStr.find("(") + 1); ReqFragment = atoll(tempStr.substr(0, tempStr.find(")")).c_str()); + if (Strm.metadata.isMember("live")){ + int seekable = Strm.canSeekms(ReqFragment / 10000); + if (seekable < 0){ + HTTP_S.Clean(); + HTTP_S.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n"); + conn.SendNow(HTTP_S.BuildResponse("412", "Fragment out of range")); + HTTP_R.Clean(); //clean for any possible next requests + std::cout << "Fragment @ " << ReqFragment / 10000 << "ms too old (" << Strm.metadata["keytime"][0u].asInt() << " - " << Strm.metadata["keytime"][Strm.metadata["keytime"].size() - 1].asInt() << " ms)" << std::endl; + continue; + } + if (seekable > 0){ + HTTP_S.Clean(); + HTTP_S.SetBody("Proxy, re-request this in a second or two.\n"); + conn.SendNow(HTTP_S.BuildResponse("208", "Ask again later")); + HTTP_R.Clean(); //clean for any possible next requests + std::cout << "Fragment @ " << ReqFragment / 10000 << "ms not available yet (" << Strm.metadata["keytime"][0u].asInt() << " - " << Strm.metadata["keytime"][Strm.metadata["keytime"].size() - 1].asInt() << " ms)" << std::endl; + continue; + } + } std::stringstream sstream; sstream << "s " << (ReqFragment / 10000) << "\no \n"; ss.SendNow(sstream.str().c_str());