[vlc-commits] demux: adaptive: add chunked transfert support

Francois Cartegnie git at videolan.org
Wed Nov 2 19:16:16 CET 2016


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Nov  2 19:14:31 2016 +0100| [b99bc394843b4967e1f54904608027154e683896] | committer: Francois Cartegnie

demux: adaptive: add chunked transfert support

refs #17551

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b99bc394843b4967e1f54904608027154e683896
---

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

diff --git a/modules/demux/adaptive/http/HTTPConnection.cpp b/modules/demux/adaptive/http/HTTPConnection.cpp
index 7c6d07b..824fe4c 100644
--- a/modules/demux/adaptive/http/HTTPConnection.cpp
+++ b/modules/demux/adaptive/http/HTTPConnection.cpp
@@ -66,6 +66,9 @@ HTTPConnection::HTTPConnection(vlc_object_t *p_object_, Socket *socket_, bool pe
     queryOk = false;
     retries = 0;
     connectionClose = !persistent;
+    chunked = false;
+    chunked_eof = false;
+    chunkLength = 0;
 }
 
 HTTPConnection::~HTTPConnection()
@@ -98,6 +101,8 @@ void HTTPConnection::disconnect()
     queryOk = false;
     bytesRead = 0;
     contentLength = 0;
+    chunked = false;
+    chunkLength = 0;
     bytesRange = BytesRange();
     socket->disconnect();
 }
@@ -105,6 +110,9 @@ void HTTPConnection::disconnect()
 int HTTPConnection::request(const std::string &path, const BytesRange &range)
 {
     queryOk = false;
+    chunked = false;
+    chunked_eof = false;
+    chunkLength = 0;
 
     /* Set new path for this query */
     params.setPath(path);
@@ -172,7 +180,8 @@ ssize_t HTTPConnection::read(void *p_buffer, size_t len)
     if(len > toRead)
         len = toRead;
 
-    ssize_t ret = socket->read(p_object, p_buffer, len);
+    ssize_t ret = ( chunked ) ? readChunk(p_buffer, len)
+                              : socket->read(p_object, p_buffer, len);
     if(ret >= 0)
         bytesRead += ret;
 
@@ -235,6 +244,54 @@ int HTTPConnection::parseReply()
     return VLC_SUCCESS;
 }
 
+ssize_t HTTPConnection::readChunk(void *p_buffer, size_t len)
+{
+    size_t copied = 0;
+
+    for( ; copied < len && !chunked_eof; )
+    {
+        /* adapted from access/http/chunked.c */
+        if(chunkLength == 0)
+        {
+            std::string line = readLine();
+            int end;
+            if (std::sscanf(line.c_str(), "%zx%n", &chunkLength, &end) < 1
+                    || (line[end] != '\0' && line[end] != ';' /* ignore extension(s) */))
+                return -1;
+        }
+
+        if(chunkLength > 0)
+        {
+            size_t toread = len - copied;
+            if(toread > chunkLength)
+                toread = chunkLength;
+
+            ssize_t in = socket->read(p_object, &((uint8_t*)p_buffer)[copied], toread);
+            if(in < 0)
+            {
+                return (copied == 0) ? in : copied;
+            }
+            else if((size_t)in < toread)
+            {
+               return copied + in;
+            }
+            copied += in;
+            chunkLength -= in;
+        }
+        else chunked_eof = true;
+
+        if(chunkLength == 0)
+        {
+            char crlf[2];
+            ssize_t in = socket->read(p_object, &crlf, 2);
+            if(in < 2 || memcmp(crlf, "\r\n", 2))
+                return (copied == 0) ? -1 : copied;
+        }
+    }
+
+    return copied;
+}
+
 std::string HTTPConnection::readLine()
 {
     return socket->readline(p_object);
@@ -272,6 +329,10 @@ void HTTPConnection::onHeader(const std::string &key,
     {
         connectionClose = true;
     }
+    else if (key == "Transfer-Encoding" && value == "chunked")
+    {
+        chunked = true;
+    }
 }
 
 std::string HTTPConnection::buildRequestHeader(const std::string &path) const
@@ -280,7 +341,6 @@ std::string HTTPConnection::buildRequestHeader(const std::string &path) const
     req << "GET " << path << " HTTP/1.1\r\n" <<
            "Host: " << params.getHostname() << "\r\n" <<
            "Cache-Control: no-cache" << "\r\n" <<
-           "Accept-Encoding: identity" << "\r\n" <<
            "User-Agent: " << std::string(psz_useragent) << "\r\n";
     req << extraRequestHeaders();
     return req.str();
diff --git a/modules/demux/adaptive/http/HTTPConnection.hpp b/modules/demux/adaptive/http/HTTPConnection.hpp
index c9ee3bb..1a1a955 100644
--- a/modules/demux/adaptive/http/HTTPConnection.hpp
+++ b/modules/demux/adaptive/http/HTTPConnection.hpp
@@ -84,11 +84,15 @@ namespace adaptive
                 virtual std::string extraRequestHeaders() const;
                 virtual std::string buildRequestHeader(const std::string &path) const;
 
+                ssize_t         readChunk   (void *p_buffer, size_t len);
                 int parseReply();
                 std::string readLine();
                 char * psz_useragent;
 
                 bool                connectionClose;
+                bool                chunked;
+                bool                chunked_eof;
+                size_t              chunkLength;
                 bool                queryOk;
                 int                 retries;
                 static const int    retryCount = 5;



More information about the vlc-commits mailing list