[vlc-devel] [PATCH] demux/adaptive: handle redirections in HTTPConnection

Zhao Zhili wantlamy at gmail.com
Wed Jul 5 12:28:40 CEST 2017


---
 modules/demux/adaptive/http/HTTPConnection.cpp | 66
+++++++++++++++++---------
 modules/demux/adaptive/http/HTTPConnection.hpp | 16 +++++--
 2 files changed, 55 insertions(+), 27 deletions(-)

diff --git a/modules/demux/adaptive/http/HTTPConnection.cpp
b/modules/demux/adaptive/http/HTTPConnection.cpp
index a250d87..0b2f7f8 100644
--- a/modules/demux/adaptive/http/HTTPConnection.cpp
+++ b/modules/demux/adaptive/http/HTTPConnection.cpp
@@ -65,7 +65,6 @@ HTTPConnection::HTTPConnection(vlc_object_t *p_object_,
Socket *socket_, bool pe
     socket = socket_;
     psz_useragent = var_InheritString(p_object_, "http-user-agent");
     queryOk = false;
-    retries = 0;
     connectionClose = !persistent;
     chunked = false;
     chunked_eof = false;
@@ -108,27 +107,24 @@ void HTTPConnection::disconnect()
     socket->disconnect();
 }

-int HTTPConnection::request(const std::string &path, const BytesRange
&range)
+HTTPConnection::HTTPErrorType HTTPConnection::doRequest(const BytesRange
&range)
 {
     queryOk = false;
     chunked = false;
     chunked_eof = false;
     chunkLength = 0;

-    /* Set new path for this query */
-    params.setPath(path);
-
     msg_Dbg(p_object, "Retrieving %s @%zu", params.getUrl().c_str(),
                        range.isValid() ? range.getStartByte() : 0);

     if(!connected() && ( params.getHostname().empty() || !connect() ))
-        return VLC_EGENERIC;
+        return HTTPGenericError;

     bytesRange = range;
     if(range.isValid() && range.getEndByte() > 0)
         contentLength = range.getEndByte() - range.getStartByte() + 1;

-    std::string header = buildRequestHeader(path);
+    std::string header = buildRequestHeader();
     if(connectionClose)
         header.append("Connection: close\r\n");
     header.append("\r\n");
@@ -140,17 +136,20 @@ int HTTPConnection::request(const std::string &path,
const BytesRange &range)
         {
             /* server closed connection pipeline after last req. need new
*/
             connectionClose = true;
-            return request(path, range);
+            return doRequest(range);
+        }
+        else
+        {
+            return HTTPGenericError;
         }
-        return VLC_EGENERIC;
     }

-    int i_ret = parseReply();
-    if(i_ret == VLC_SUCCESS)
+    HTTPConnection::HTTPErrorType i_ret = parseReply();
+    if(i_ret == HTTPSuccess)
     {
         queryOk = true;
     }
-    else if(i_ret == VLC_ETIMEOUT) /* redir */
+    else if(i_ret == HTTPRedirect) /* redir */
     {
         socket->disconnect();
         if(locationparams.getScheme().empty())
@@ -159,19 +158,40 @@ int HTTPConnection::request(const std::string &path,
const BytesRange &range)
             params = locationparams;
         locationparams = ConnectionParams();
     }
-    else if(i_ret == VLC_EGENERIC)
+    else if(i_ret == HTTPGenericError)
     {
         socket->disconnect();
         if(!connectionClose)
         {
             connectionClose = true;
-            return request(path, range);
+            return doRequest(range);
         }
     }

     return i_ret;
 }

+int HTTPConnection::request(const std::string &path, const BytesRange
&range)
+{
+    /* Set new path for this query */
+    params.setPath(path);
+
+    for(int retries = 0; retries < maxRedirectCount; retries++)
+    {
+        HTTPConnection::HTTPErrorType ret = doRequest(range);
+        if (ret == HTTPSuccess)
+            return VLC_SUCCESS;
+        else if (ret == HTTPGenericError)
+            return VLC_EGENERIC;
+        else if (ret == HTTPRedirect)
+            continue;
+        else
+            break;
+    }
+
+    return VLC_EGENERIC;
+}
+
 ssize_t HTTPConnection::read(void *p_buffer, size_t len)
 {
     if( !connected() ||
@@ -215,17 +235,17 @@ bool HTTPConnection::send(const void *buf, size_t
size)
     return socket->send(p_object, buf, size);
 }

-int HTTPConnection::parseReply()
+HTTPConnection::HTTPErrorType HTTPConnection::parseReply()
 {
     std::string line = readLine();

     if(line.empty())
-        return VLC_EGENERIC;
+        return HTTPGenericError;

     if (line.compare(0, 9, "HTTP/1.1 ")!=0)
     {
         if(line.compare(0, 9, "HTTP/1.0 ")!=0)
-            return VLC_ENOOBJ;
+            return HTTPGenericError;
         else
             connectionClose = true;
     }
@@ -254,15 +274,15 @@ int HTTPConnection::parseReply()
        !locationparams.getUrl().empty())
     {
         msg_Info(p_object, "%d redirection to %s", replycode,
locationparams.getUrl().c_str());
-        return VLC_ETIMEOUT;
+        return HTTPRedirect;
     }
     else if (replycode != 200 && replycode != 206)
     {
-        msg_Err(p_object, "Failed reading %s: %s",
params.getUrl().c_str(), line.c_str());
-        return VLC_ENOOBJ;
+        msg_Err(p_object, "%d Failed reading %s: %s", replycode,
params.getUrl().c_str(), line.c_str());
+        return HTTPGenericError;
     }

-    return VLC_SUCCESS;
+    return HTTPSuccess;
 }

 ssize_t HTTPConnection::readChunk(void *p_buffer, size_t len)
@@ -360,10 +380,10 @@ void HTTPConnection::onHeader(const std::string &key,
     }
 }

-std::string HTTPConnection::buildRequestHeader(const std::string &path)
const
+std::string HTTPConnection::buildRequestHeader() const
 {
     std::stringstream req;
-    req << "GET " << path << " HTTP/1.1\r\n" <<
+    req << "GET " << params.getPath() << " HTTP/1.1\r\n" <<
            "Host: " << params.getHostname() << "\r\n" <<
            "Cache-Control: no-cache" << "\r\n" <<
            "User-Agent: " << std::string(psz_useragent) << "\r\n";
diff --git a/modules/demux/adaptive/http/HTTPConnection.hpp
b/modules/demux/adaptive/http/HTTPConnection.hpp
index 85ca53b..707e604 100644
--- a/modules/demux/adaptive/http/HTTPConnection.hpp
+++ b/modules/demux/adaptive/http/HTTPConnection.hpp
@@ -73,6 +73,15 @@ namespace adaptive
                 void setUsed( bool );

             protected:
+                enum HTTPErrorType
+                {
+                    HTTPSuccess = 0,
+                    HTTPGenericError,
+                    HTTPRedirect,
+                };
+
+                virtual HTTPConnection::HTTPErrorType doRequest(const
BytesRange &range);
+
                 virtual bool    connected   () const;
                 virtual bool    connect     ();
                 virtual void    disconnect  ();
@@ -82,10 +91,10 @@ namespace adaptive
                 virtual void    onHeader    (const std::string &line,
                                              const std::string &value);
                 virtual std::string extraRequestHeaders() const;
-                virtual std::string buildRequestHeader(const std::string
&path) const;
+                virtual std::string buildRequestHeader() const;

                 ssize_t         readChunk   (void *p_buffer, size_t len);
-                int parseReply();
+                HTTPConnection::HTTPErrorType parseReply();
                 std::string readLine();
                 char * psz_useragent;

@@ -95,8 +104,7 @@ namespace adaptive
                 bool                chunked_eof;
                 size_t              chunkLength;
                 bool                queryOk;
-                int                 retries;
-                static const int    retryCount = 5;
+                static const int    maxRedirectCount = 5;

             private:
                 Socket *socket;
-- 
2.7.4
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20170705/a9e32251/attachment.html>


More information about the vlc-devel mailing list