[vlc-commits] [Git][videolan/vlc][master] 9 commits: adaptive: add missing virtual keyword

François Cartegnie (@fcartegnie) gitlab at videolan.org
Thu Sep 16 14:59:52 UTC 2021



François Cartegnie pushed to branch master at VideoLAN / VLC


Commits:
708a1871 by Francois Cartegnie at 2021-09-16T14:44:04+00:00
adaptive: add missing virtual keyword

- - - - -
7501fae4 by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: store redirection into abstractconnection

- - - - -
087f81bb by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: use connection bytesRead instead of readsize

- - - - -
3db241a3 by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: remove useless parent method indirection

- - - - -
f5c33933 by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: add libvlchttp based connection

- - - - -
207a2c15 by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: use libvlchttp for default connections

- - - - -
238baeb8 by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: replace maxconnect const var with namespaced constexpr

- - - - -
98fd0b74 by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: remove native connection

- - - - -
be436e0e by Francois Cartegnie at 2021-09-16T14:44:04+00:00
demux: adaptive: request optional compression

Allow server to compress manifests and text subtitles

- - - - -


11 changed files:

- modules/demux/Makefile.am
- modules/demux/adaptive/SharedResources.cpp
- modules/demux/adaptive/http/AuthStorage.cpp
- modules/demux/adaptive/http/AuthStorage.hpp
- modules/demux/adaptive/http/Chunk.cpp
- modules/demux/adaptive/http/Chunk.h
- modules/demux/adaptive/http/HTTPConnection.cpp
- modules/demux/adaptive/http/HTTPConnection.hpp
- modules/demux/adaptive/http/HTTPConnectionManager.cpp
- − modules/demux/adaptive/http/Transport.cpp
- − modules/demux/adaptive/http/Transport.hpp


Changes:

=====================================
modules/demux/Makefile.am
=====================================
@@ -368,8 +368,6 @@ libvlc_adaptive_la_SOURCES = \
     demux/adaptive/http/HTTPConnection.hpp \
     demux/adaptive/http/HTTPConnectionManager.cpp \
     demux/adaptive/http/HTTPConnectionManager.h \
-    demux/adaptive/http/Transport.hpp \
-    demux/adaptive/http/Transport.cpp \
     demux/adaptive/plumbing/CommandsQueue.cpp \
     demux/adaptive/plumbing/CommandsQueue.hpp \
     demux/adaptive/plumbing/Demuxer.cpp \
@@ -491,6 +489,10 @@ libvlc_adaptive_la_SOURCES += \
 libvlc_adaptive_la_CXXFLAGS = $(AM_CXXFLAGS) -I$(srcdir)/demux/adaptive
 libvlc_adaptive_la_LIBADD = $(SOCKET_LIBS) $(LIBM)
 libvlc_adaptive_la_LDFLAGS = -static
+if !HAVE_WIN32
+libvlc_adaptive_la_LDFLAGS += -lpthread
+endif
+libvlc_adaptive_la_LIBADD += libvlc_http.la
 if HAVE_ZLIB
 libvlc_adaptive_la_LIBADD += -lz
 endif


=====================================
modules/demux/adaptive/SharedResources.cpp
=====================================
@@ -66,7 +66,7 @@ SharedResources * SharedResources::createDefault(vlc_object_t *obj,
     Keyring *keyring = new Keyring(obj);
     HTTPConnectionManager *m = new HTTPConnectionManager(obj);
     if(!var_InheritBool(obj, "adaptive-use-access")) /* only use http from access */
-        m->addFactory(new NativeConnectionFactory(auth));
+        m->addFactory(new LibVLCHTTPConnectionFactory(auth));
     m->addFactory(new StreamUrlConnectionFactory());
     ConnectionParams params(playlisturl);
     if(params.isLocal())


=====================================
modules/demux/adaptive/http/AuthStorage.cpp
=====================================
@@ -62,3 +62,8 @@ std::string AuthStorage::getCookie( const ConnectionParams &params, bool secure
     }
     return ret;
 }
+
+vlc_http_cookie_jar_t *AuthStorage::getJar() const
+{
+    return p_cookies_jar;
+}


=====================================
modules/demux/adaptive/http/AuthStorage.hpp
=====================================
@@ -38,6 +38,7 @@ namespace adaptive
                 ~AuthStorage();
                 void addCookie( const std::string &cookie, const ConnectionParams & );
                 std::string getCookie( const ConnectionParams &, bool secure );
+                vlc_http_cookie_jar_t *getJar() const;
 
             private:
                 vlc_http_cookie_jar_t *p_cookies_jar;


=====================================
modules/demux/adaptive/http/Chunk.cpp
=====================================
@@ -234,10 +234,11 @@ block_t * HTTPChunkSource::read(size_t readsize)
             eof = true;
             downloadEndTime = vlc_tick_now();
         }
-        if(ret && p_block->i_buffer &&
+        if(ret && connection->getBytesRead() &&
            downloadEndTime > requestStartTime && type == ChunkType::Segment)
         {
-            connManager->updateDownloadRate(sourceid, p_block->i_buffer,
+            connManager->updateDownloadRate(sourceid,
+                                            connection->getBytesRead(),
                                             downloadEndTime - requestStartTime,
                                             downloadEndTime - responseTime);
         }
@@ -268,7 +269,7 @@ bool HTTPChunkSource::prepare()
     requestStartTime = vlc_tick_now();
 
     unsigned int i_redirects = 0;
-    while(i_redirects++ < HTTPConnection::MAX_REDIRECTS)
+    while(i_redirects++ < http::MAX_REDIRECTS)
     {
         if(!connection)
         {
@@ -282,12 +283,10 @@ bool HTTPChunkSource::prepare()
         {
             if(requeststatus == RequestStatus::Redirection)
             {
-                HTTPConnection *httpconn = dynamic_cast<HTTPConnection *>(connection);
-                if(httpconn)
-                    connparams = httpconn->getRedirection();
+                connparams = connection->getRedirection();
                 connection->setUsed(false);
                 connection = nullptr;
-                if(httpconn)
+                if(!connparams.getUrl().empty())
                     continue;
             }
             break;
@@ -431,13 +430,6 @@ void HTTPChunkBufferedSource::bufferize(size_t readsize)
     avail.signal();
 }
 
-bool HTTPChunkBufferedSource::prepare()
-{
-    if(!prepared)
-        return HTTPChunkSource::prepare();
-    return true;
-}
-
 bool HTTPChunkBufferedSource::hasMoreData() const
 {
     mutex_locker locker {lock};


=====================================
modules/demux/adaptive/http/Chunk.h
=====================================
@@ -159,7 +159,6 @@ namespace adaptive
                 HTTPChunkBufferedSource(const std::string &url, AbstractConnectionManager *,
                                         const ID &, ChunkType, const BytesRange &,
                                         bool = false);
-                virtual bool       prepare()  override;
                 void               bufferize(size_t);
                 bool               isDone() const;
                 void               hold();


=====================================
modules/demux/adaptive/http/HTTPConnection.cpp
=====================================
@@ -24,13 +24,19 @@
 #include "HTTPConnection.hpp"
 #include "ConnectionParams.hpp"
 #include "AuthStorage.hpp"
-#include "Transport.hpp"
-#include "../tools/Helper.h"
+#include "../AbstractSource.hpp"
+#include "../plumbing/SourceStream.hpp"
 
-#include <cstdio>
-#include <sstream>
-#include <algorithm>
 #include <vlc_stream.h>
+#include <vlc_keystore.h>
+
+extern "C"
+{
+    #include "../access/http/resource.h"
+    #include "../access/http/connmgr.h"
+    #include "../access/http/conn.h"
+    #include "../access/http/message.h"
+}
 
 using namespace adaptive::http;
 
@@ -52,6 +58,7 @@ bool AbstractConnection::prepare(const ConnectionParams &params_)
     if (!available)
         return false;
     params = params_;
+    locationparams = ConnectionParams();
     available = false;
     return true;
 }
@@ -61,417 +68,356 @@ size_t AbstractConnection::getContentLength() const
     return contentLength;
 }
 
-const std::string & AbstractConnection::getContentType() const
-{
-    return contentType;
-}
-
-HTTPConnection::HTTPConnection(vlc_object_t *p_object_, AuthStorage *auth,
-                               Transport *socket_, const ConnectionParams &proxy)
-    : AbstractConnection( p_object_ )
+size_t AbstractConnection::getBytesRead() const
 {
-    transport = socket_;
-    char *psz_useragent = var_InheritString(p_object_, "http-user-agent");
-    useragent = psz_useragent ? std::string(psz_useragent) : std::string("");
-    free(psz_useragent);
-    char *psz_referer = var_InheritString(p_object_, "http-referrer");
-    referer = psz_referer ? std::string(psz_referer) : std::string("");
-    free(psz_referer);
-    std::replace_if(useragent.begin(), useragent.end(), [](const char &c){return !::isprint(c);}, ' ');
-    std::replace_if(referer.begin(), referer.end(), [](const char &c){return !::isprint(c);}, ' ');
-    queryOk = false;
-    retries = 0;
-    authStorage = auth;
-    connectionClose = false;
-    chunked = false;
-    chunked_eof = false;
-    chunkLength = 0;
-    proxyparams = proxy;
-}
-
-HTTPConnection::~HTTPConnection()
-{
-    delete transport;
-}
-
-bool HTTPConnection::canReuse(const ConnectionParams &params_) const
-{
-    if( !available || params_.usesAccess() )
-        return false;
-
-    char *psz_proxy_url = vlc_getProxyUrl(params_.getUrl().c_str());
-    if(psz_proxy_url)
-    {
-        ConnectionParams proxy(psz_proxy_url);
-        free(psz_proxy_url);
-        return (proxyparams.getHostname() == proxy.getHostname() &&
-                proxyparams.getScheme() == proxy.getScheme() &&
-                proxyparams.getPort() == proxy.getPort());
-    }
-    else return (params.getHostname() == params_.getHostname() &&
-                 params.getScheme() == params_.getScheme() &&
-                 params.getPort() == params_.getPort());
-}
-
-bool HTTPConnection::connect()
-{
-    if(proxyparams.getHostname().empty())
-        return transport->connect(p_object, params.getHostname().c_str(),
-                                         params.getPort());
-    else
-        return transport->connect(p_object, proxyparams.getHostname().c_str(),
-                                         proxyparams.getPort());
+    return bytesRead;
 }
 
-bool HTTPConnection::connected() const
+const std::string & AbstractConnection::getContentType() const
 {
-    return transport->connected();
+    return contentType;
 }
 
-void HTTPConnection::disconnect()
+const ConnectionParams & AbstractConnection::getRedirection() const
 {
-    queryOk = false;
-    bytesRead = 0;
-    contentLength = 0;
-    connectionClose = false;
-    chunked = false;
-    chunkLength = 0;
-    bytesRange = BytesRange();
-    contentType = std::string();
-    transport->disconnect();
+    return locationparams;
 }
 
-RequestStatus HTTPConnection::request(const std::string &path,
-                                      const BytesRange &range)
+class adaptive::http::LibVLCHTTPSource : public adaptive::AbstractSource
 {
-    queryOk = false;
-    chunked = false;
-    chunked_eof = false;
-    chunkLength = 0;
+     friend class LibVLCHTTPConnection;
 
-    /* Set new path for this query */
-    params.setPath(path);
-    locationparams = ConnectionParams();
-
-    msg_Dbg(p_object, "Retrieving %s @%zu", params.getUrl().c_str(),
-                       range.isValid() ? range.getStartByte() : 0);
-
-    std::string querypath;
-    if(!proxyparams.getHostname().empty())
-    {
-        msg_Dbg(p_object, "Using proxy %s", proxyparams.getUrl().c_str());
-        querypath = params.getUrl();
-    }
-    else querypath = path;
+     public:
+        LibVLCHTTPSource(vlc_object_t *p_object, struct vlc_http_cookie_jar_t *jar)
+        {
+            http_mgr = vlc_http_mgr_create(p_object, jar);
+            http_res = nullptr;
+            totalRead = 0;
+        }
+        virtual ~LibVLCHTTPSource()
+        {
+            if(http_mgr)
+                vlc_http_mgr_destroy(http_mgr);
+        }
+        virtual block_t *readNextBlock() override
+        {
+            if(http_res == nullptr)
+                return nullptr;
+            block_t *b = vlc_http_res_read(http_res);
+            if(b == vlc_http_error)
+                return nullptr;
+            if(b)
+                totalRead += b->i_buffer;
+            return b;
+        }
+        void reset()
+        {
+            if(http_res)
+            {
+                vlc_http_res_destroy(http_res);
+                http_res = nullptr;
+                totalRead = 0;
+            }
+        }
 
-    if(!connected() && ( params.getHostname().empty() || !connect() ))
-        return RequestStatus::GenericError;
+    private:
+        struct restuple
+        {
+            struct vlc_http_resource resource;
+            LibVLCHTTPSource *source;
+        };
 
-    bytesRange = range;
-    if(range.isValid() && range.getEndByte() > 0)
-        contentLength = range.getEndByte() - range.getStartByte() + 1;
+        int formatRequest(const struct vlc_http_resource *,
+                          struct vlc_http_msg *req)
+        {
+            vlc_http_msg_add_header(req, "Accept-Encoding", "deflate, gzip");
+            vlc_http_msg_add_header(req, "Cache-Control", "no-cache");
+            if(range.isValid())
+            {
+                if(range.getEndByte() > 0)
+                {
+                    if (vlc_http_msg_add_header(req, "Range", "bytes=%" PRIuMAX "-%" PRIuMAX,
+                                                range.getStartByte(), range.getEndByte()))
+                        return -1;
+                }
+                else
+                {
+                    if (vlc_http_msg_add_header(req, "Range", "bytes=%" PRIuMAX "-",
+                                                range.getStartByte()))
+                        return -1;
+                }
+            }
+            return 0;
+        }
 
-    std::string header = buildRequestHeader(querypath);
-    if(connectionClose)
-        header.append("Connection: close\r\n");
-    header.append("\r\n");
+        int validateResponse(const struct vlc_http_resource *, const struct vlc_http_msg *resp)
+        {
+            if (vlc_http_msg_get_status(resp) == 206)
+            {
+                const char *str = vlc_http_msg_get_header(resp, "Content-Range");
+                if (str == NULL)
+                    /* A multipart/byteranges response. This is not what we asked for
+                     * and we do not support it. */
+                    return -1;
+
+                uintmax_t start, end;
+                if (sscanf(str, "bytes %" SCNuMAX "-%" SCNuMAX, &start, &end) != 2
+                 || start != range.getStartByte() || start > end ||
+                 (range.getEndByte() > range.getStartByte() && range.getEndByte() != end) )
+                    /* A single range response is what we asked for, but not at that
+                     * start offset. */
+                    return -1;
+            }
+            return 0;
+        }
 
-    if(!send( header ))
-    {
-        transport->disconnect();
-        if(!connectionClose)
+        static int formatrequest_handler(const struct vlc_http_resource *res,
+                                         struct vlc_http_msg *req, void *opaque)
         {
-            /* server closed connection pipeline after last req. need new */
-            connectionClose = true;
-            return request(path, range);
+            return (*static_cast<LibVLCHTTPSource **>(opaque))->formatRequest(res, req);
         }
-        return RequestStatus::GenericError;
-    }
 
-    RequestStatus status = parseReply();
-    if(status == RequestStatus::Success)
-    {
-        queryOk = true;
-    }
-    else if(status == RequestStatus::Redirection)
-    {
-        transport->disconnect();
-    }
-    else if(status == RequestStatus::GenericError)
-    {
-        transport->disconnect();
-        if(!connectionClose)
+        static int validateresponse_handler(const struct vlc_http_resource *res,
+                                            const struct vlc_http_msg *resp, void *opaque)
         {
-            connectionClose = true;
-            return request(path, range);
+            return (*static_cast<LibVLCHTTPSource **>(opaque))->validateResponse(res, resp);
         }
-    }
 
-    return status;
-}
+        static const struct vlc_http_resource_cbs callbacks;
+        size_t totalRead;
+        struct vlc_http_mgr *http_mgr;
+        BytesRange range;
 
-ssize_t HTTPConnection::read(void *p_buffer, size_t len)
-{
-    if( !connected() ||
-       (!queryOk && bytesRead == 0) )
-        return VLC_EGENERIC;
+    public:
+        struct vlc_http_resource *http_res;
+        int create(const char *uri,const std::string &ua,
+                   const std::string &ref, const BytesRange &range)
+        {
+            struct restuple *tpl = new struct restuple;
+            tpl->source = this;
+            this->range = range;
+            if (vlc_http_res_init(&tpl->resource, &this->callbacks, http_mgr, uri,
+                                  ua.empty() ? nullptr : ua.c_str(),
+                                  ref.empty() ? nullptr : ref.c_str()))
+            {
+                delete tpl;
+                return -1;
+            }
+            http_res = &tpl->resource;
+            return 0;
+        }
 
-    if(len == 0)
-        return VLC_SUCCESS;
+        int abortandlogin(const char *user, const char *pass)
+        {
+            if(http_res == nullptr)
+                return -1;
 
-    queryOk = false;
+            free(http_res->username);
+            http_res->username = user ? strdup(user) : nullptr;
+            free(http_res->password);
+            http_res->password = pass ? strdup(pass) : nullptr;
 
-    const size_t toRead = (contentLength) ? contentLength - bytesRead : len;
-    if (toRead == 0)
-        return VLC_SUCCESS;
+            struct vlc_http_msg *resp = vlc_http_res_open(http_res, &http_res[1]);
+            if (resp == nullptr)
+                return -1;
 
-    if(len > toRead)
-        len = toRead;
+            if (http_res->response != nullptr)
+                vlc_http_msg_destroy(http_res->response);
 
-    ssize_t ret = ( chunked ) ? readChunk(p_buffer, len)
-                              : transport->read(p_buffer, len);
-    if(ret >= 0)
-        bytesRead += ret;
+            http_res->response = resp;
+            return 0;
+        }
+};
 
-    if(ret < 0 || (size_t)ret < len || /* set EOF */
-       (contentLength == bytesRead && connectionClose))
+const struct vlc_http_resource_cbs LibVLCHTTPSource::callbacks =
+{
+    LibVLCHTTPSource::formatrequest_handler,
+    LibVLCHTTPSource::validateresponse_handler,
+};
+
+LibVLCHTTPConnection::LibVLCHTTPConnection(vlc_object_t *p_object_, AuthStorage *auth)
+    : AbstractConnection( p_object_ )
+{
+    source = new adaptive::http::LibVLCHTTPSource(p_object_, auth->getJar());
+    sourceStream = new ChunksSourceStream(p_object, source);
+    stream = nullptr;
+    char *psz_useragent = var_InheritString(p_object_, "http-user-agent");
+    if(psz_useragent)
     {
-        transport->disconnect();
-        return ret;
+        useragent = std::string(psz_useragent);
+        free(psz_useragent);
+    }
+    char *psz_referer = var_InheritString(p_object_, "http-referrer");
+    if(psz_referer)
+    {
+        referer = std::string(psz_referer);
+        free(psz_referer);
     }
-
-    return ret;
 }
 
-bool HTTPConnection::send(const std::string &data)
+LibVLCHTTPConnection::~LibVLCHTTPConnection()
 {
-    return send(data.c_str(), data.length());
+    reset();
+    delete sourceStream;
+    delete source;
 }
 
-bool HTTPConnection::send(const void *buf, size_t size)
+void LibVLCHTTPConnection::reset()
 {
-    return transport->send(buf, size);
+    source->reset();
+    sourceStream->Reset();
+    if(stream)
+    {
+        vlc_stream_Delete(stream);
+        stream = nullptr;
+    }
+    bytesRange = BytesRange();
+    contentType = std::string();
+    bytesRead = 0;
+    contentLength = 0;
 }
 
-RequestStatus HTTPConnection::parseReply()
+bool LibVLCHTTPConnection::canReuse(const ConnectionParams &params_) const
 {
-    std::string statusline = readLine();
+    if(!available)
+        return false;
+    return (params.getHostname() == params_.getHostname() &&
+            params.getScheme() == params_.getScheme() &&
+            params.getPort() == params_.getPort());
+}
 
-    if(statusline.empty())
+RequestStatus LibVLCHTTPConnection::request(const std::string &path,
+                                            const BytesRange &range)
+{
+    if(source->http_mgr == nullptr)
         return RequestStatus::GenericError;
 
-    if (statusline.compare(0, 9, "HTTP/1.1 ")!=0)
-    {
-        if(statusline.compare(0, 9, "HTTP/1.0 ")!=0)
-            return RequestStatus::NotFound;
-        else
-            connectionClose = true;
-    }
+    reset();
 
-    std::istringstream ss(statusline.substr(9));
-    ss.imbue(std::locale("C"));
-    int replycode;
-    ss >> replycode;
+    /* Set new path for this query */
+    params.setPath(path);
 
-    std::string lines;
-    for( ;; )
-    {
-        std::string l = readLine();
-        if(l.empty())
-            break;
-        lines.append(l);
+    if(range.isValid())
+        msg_Dbg(p_object, "Retrieving %s @%zu-%zu", params.getUrl().c_str(),
+                           range.getStartByte(), range.getEndByte());
+    else
+        msg_Dbg(p_object, "Retrieving %s", params.getUrl().c_str());
 
-        size_t split = lines.find_first_of(':');
-        if(split != std::string::npos)
-        {
-            size_t value = lines.find_first_not_of(' ', split + 1);
-            if(value == std::string::npos)
-                value = lines.length();
-            onHeader(lines.substr(0, split), lines.substr(value));
-            lines = std::string();
-        }
-    }
+    if(source->create(params.getUrl().c_str(), useragent,referer, range))
+        return RequestStatus::GenericError;
+
+    struct vlc_credential crd;
+    struct vlc_url_t crd_url;
+    vlc_UrlParse(&crd_url, params.getUrl().c_str());
 
-    if((replycode == 301 || replycode == 302 || replycode == 307 || replycode == 308) &&
-       !locationparams.getUrl().empty())
+    vlc_credential_init(&crd, &crd_url);
+    if (vlc_credential_get(&crd, p_object, NULL, NULL, NULL, NULL))
     {
-        msg_Info(p_object, "%d redirection to %s", replycode, locationparams.getUrl().c_str());
-        if(locationparams.isLocal() && !params.isLocal())
-        {
-            msg_Err(p_object, "redirection to local rejected");
-            return RequestStatus::GenericError;
-        }
-        return RequestStatus::Redirection;
+        vlc_http_res_set_login(source->http_res,
+                               crd.psz_username, crd.psz_password);
     }
-    else if (replycode != 200 && replycode != 206)
+
+    int status = vlc_http_res_get_status(source->http_res);
+    if (status < 0)
     {
-        msg_Err(p_object, "Failed reading %s: %s", params.getUrl().c_str(), statusline.c_str());
-        return RequestStatus::NotFound;
+        vlc_credential_clean(&crd);
+        vlc_UrlClean(&crd_url);
+        return RequestStatus::GenericError;
     }
 
-    return RequestStatus::Success;
-}
-
-ssize_t HTTPConnection::readChunk(void *p_buffer, size_t len)
-{
-    size_t copied = 0;
-
-    for( ; copied < len && !chunked_eof; )
+    char *psz_realm = nullptr;
+    if (status == 401) /* authentication */
     {
-        /* adapted from access/http/chunked.c */
-        if(chunkLength == 0)
+        psz_realm = vlc_http_res_get_basic_realm(source->http_res);
+        if (psz_realm)
         {
-            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 = transport->read(&((uint8_t*)p_buffer)[copied], toread);
-            if(in < 0)
-            {
-                return (copied == 0) ? in : copied;
-            }
-            else if((size_t)in < toread)
+            vlc_credential_init(&crd, &crd_url);
+            crd.psz_authtype = "Basic";
+            crd.psz_realm = psz_realm;
+            if (vlc_credential_get(&crd, p_object, NULL, NULL,
+                                   _("HTTP authentication"),
+                                   _("Please enter a valid login name and a "
+                                   "password for realm %s."), psz_realm))
             {
-               return copied + in;
+                if(source->abortandlogin(crd.psz_username, crd.psz_password))
+                {
+                    vlc_credential_clean(&crd);
+                    vlc_UrlClean(&crd_url);
+                    free(psz_realm);
+                    return RequestStatus::Unauthorized;
+                }
+                status = vlc_http_res_get_status(source->http_res);
             }
-            copied += in;
-            chunkLength -= in;
-        }
-        else chunked_eof = true;
-
-        if(chunkLength == 0)
-        {
-            char crlf[2];
-            ssize_t in = transport->read(&crlf, 2);
-            if(in < 2 || memcmp(crlf, "\r\n", 2))
-                return (copied == 0) ? -1 : copied;
         }
     }
 
-    return copied;
-}
-
-std::string HTTPConnection::readLine()
-{
-    return transport->readline();
-}
-
-void HTTPConnection::setUsed( bool b )
-{
-    available = !b;
-    if(available)
+    if(status > 0 && status < 400 && crd.psz_realm &&
+       crd.i_get_order > decltype(crd.i_get_order)::GET_FROM_MEMORY_KEYSTORE)
     {
-        if(!connectionClose && contentLength == bytesRead && (!chunked || chunked_eof))
-        {
-            queryOk = false;
-            bytesRead = 0;
-            contentLength = 0;
-            bytesRange = BytesRange();
-        }
-        else  /* We can't resend request if we haven't finished reading */
-            disconnect();
+        /* Force caching into memory keystore */
+        crd.b_from_keystore = false;
+        crd.b_store = false;
+        vlc_credential_store(&crd, p_object);
     }
-}
 
-void HTTPConnection::onHeader(const std::string &key,
-                              const std::string &value)
-{
-    if(Helper::icaseEquals(key, "Content-Length"))
-    {
-        std::istringstream ss(value);
-        ss.imbue(std::locale("C"));
-        size_t length;
-        ss >> length;
-        contentLength = length;
-    }
-    else if (Helper::icaseEquals(key, "Connection") &&
-             Helper::icaseEquals(value, "close"))
-    {
-        connectionClose = true;
-    }
-    else if (Helper::icaseEquals(key, "Transfer-Encoding") &&
-             Helper::icaseEquals(value, "chunked"))
-    {
-        chunked = true;
-    }
-    else if(Helper::icaseEquals(key, "Content-Type"))
-    {
-        contentType = value;
-    }
-    else if(Helper::icaseEquals(key, "Location"))
+    vlc_credential_clean(&crd);
+    vlc_UrlClean(&crd_url);
+    free(psz_realm);
+
+    if (status >= 400)
+        return RequestStatus::GenericError;
+
+    char *psz_redir = vlc_http_res_get_redirect(source->http_res);
+    if(psz_redir)
     {
-        locationparams = ConnectionParams();
-        ConnectionParams loc = ConnectionParams( value );
+        ConnectionParams loc = ConnectionParams(psz_redir);
+        free(psz_redir);
         if(loc.getScheme().empty())
         {
             locationparams = params;
             locationparams.setPath(loc.getPath());
         }
         else locationparams = loc;
+        return RequestStatus::Redirection;
     }
-    else if(Helper::icaseEquals(key, "Set-Cookie") && authStorage)
-    {
-        authStorage->addCookie( value, params );
-    }
-}
 
-std::string HTTPConnection::buildRequestHeader(const std::string &path) const
-{
-    std::stringstream req;
-    req.imbue(std::locale("C"));
-    req << "GET " << path << " HTTP/1.1\r\n";
-    if((params.getScheme() == "http" && params.getPort() != 80) ||
-            (params.getScheme() == "https" && params.getPort() != 443))
-    {
-        req << "Host: " << params.getHostname() << ":" << params.getPort() << "\r\n";
-    }
-    else
-    {
-        req << "Host: " << params.getHostname() << "\r\n";
-    }
-    if(authStorage)
+    sourceStream->Reset();
+    stream = sourceStream->makeStream();
+    if(stream == nullptr)
+        return RequestStatus::GenericError;
+
+    contentLength = vlc_http_msg_get_size(source->http_res->response);
+
+    const char *s = vlc_http_msg_get_header(source->http_res->response, "Content-Type");
+    if(s)
+        contentType = std::string(s);
+
+    s = vlc_http_msg_get_header(source->http_res->response, "Content-Encoding");
+    if(s && stream && (strstr(s, "deflate") || strstr(s, "gzip")))
     {
-        std::string cookie = authStorage->getCookie(params,
-                                                    params.getScheme() == "https" ||
-                                                    params.getPort() == 443);
-        if(!cookie.empty())
-            req << "Cookie: " << cookie << "\r\n";
+        stream_t *decomp = vlc_stream_FilterNew(stream, "inflate");
+        if(decomp)
+        {
+            stream = decomp;
+            contentLength = 0;
+        }
     }
-    req << "Cache-Control: no-cache" << "\r\n";
-    if(!useragent.empty())
-        req << "User-Agent: " << useragent << "\r\n";
-    if(!referer.empty())
-        req << "Referer: " << referer << "\r\n";
-    req << extraRequestHeaders();
-    return req.str();
+
+    return RequestStatus::Success;
 }
 
-std::string HTTPConnection::extraRequestHeaders() const
+ssize_t LibVLCHTTPConnection::read(void *p_buffer, size_t len)
 {
-    std::stringstream ss;
-    ss.imbue(std::locale("C"));
-    if(bytesRange.isValid())
-    {
-        ss << "Range: bytes=" << bytesRange.getStartByte() << "-";
-        if(bytesRange.getEndByte())
-            ss << bytesRange.getEndByte();
-        ss << "\r\n";
-    }
-    return ss.str();
+    ssize_t read = vlc_stream_Read(stream, p_buffer, len);
+    bytesRead = source->totalRead;
+    return read;
 }
 
-const ConnectionParams & HTTPConnection::getRedirection() const
+void LibVLCHTTPConnection::setUsed( bool b )
 {
-    return locationparams;
+    available = !b;
+    if(available)
+       reset();
 }
 
 StreamUrlConnection::StreamUrlConnection(vlc_object_t *p_object)
@@ -589,49 +535,19 @@ void StreamUrlConnection::setUsed( bool b )
        reset();
 }
 
-NativeConnectionFactory::NativeConnectionFactory( AuthStorage *auth )
+LibVLCHTTPConnectionFactory::LibVLCHTTPConnectionFactory( AuthStorage *auth )
     : AbstractConnectionFactory()
 {
     authStorage = auth;
 }
 
-NativeConnectionFactory::~NativeConnectionFactory()
-{
-}
-
-AbstractConnection * NativeConnectionFactory::createConnection(vlc_object_t *p_object,
-                                                         const ConnectionParams &params)
+AbstractConnection * LibVLCHTTPConnectionFactory::createConnection(vlc_object_t *p_object,
+                                                                  const ConnectionParams &params)
 {
-    if(params.usesAccess() ||
-       (params.getScheme() != "http" && params.getScheme() != "https") ||
+    if((params.getScheme() != "http" && params.getScheme() != "https") ||
        params.getHostname().empty())
         return nullptr;
-
-    ConnectionParams proxy;
-
-    std::string scheme;
-    char *psz_proxy_url = vlc_getProxyUrl(params.getUrl().c_str());
-    if(psz_proxy_url)
-    {
-        proxy = ConnectionParams(psz_proxy_url);
-        free(psz_proxy_url);
-        scheme = proxy.getScheme();
-    }
-    else scheme = params.getScheme();
-
-    Transport *socket = new (std::nothrow) Transport(params.getScheme() == "https");
-    if(!socket)
-        return nullptr;
-
-    HTTPConnection *conn = new (std::nothrow)
-            HTTPConnection(p_object, authStorage, socket, proxy);
-    if(!conn)
-    {
-        delete socket;
-        return nullptr;
-    }
-
-    return conn;
+    return new LibVLCHTTPConnection(p_object, authStorage);
 }
 
 StreamUrlConnectionFactory::StreamUrlConnectionFactory()


=====================================
modules/demux/adaptive/http/HTTPConnection.hpp
=====================================
@@ -32,11 +32,14 @@
 
 namespace adaptive
 {
+    class ChunksSourceStream;
+
     namespace http
     {
-        class Transport;
         class AuthStorage;
 
+        constexpr unsigned MAX_REDIRECTS = 3;
+
         class AbstractConnection
         {
             public:
@@ -51,11 +54,14 @@ namespace adaptive
                 virtual ssize_t read        (void *p_buffer, size_t len) = 0;
 
                 virtual size_t  getContentLength() const;
+                virtual size_t  getBytesRead() const;
                 virtual const std::string & getContentType() const;
+                virtual const ConnectionParams &getRedirection() const;
                 virtual void    setUsed( bool ) = 0;
 
             protected:
                 vlc_object_t      *p_object;
+                ConnectionParams   locationparams;
                 ConnectionParams   params;
                 bool               available;
                 size_t             contentLength;
@@ -64,53 +70,26 @@ namespace adaptive
                 size_t             bytesRead;
         };
 
-        class HTTPConnection : public AbstractConnection
-        {
-            public:
-                HTTPConnection(vlc_object_t *, AuthStorage *,  Transport *,
-                               const ConnectionParams &);
-                virtual ~HTTPConnection();
+       class LibVLCHTTPSource;
 
-                virtual bool    canReuse     (const ConnectionParams &) const override;
-                virtual RequestStatus request(const std::string& path,
-                                              const BytesRange & = BytesRange()) override;
-                virtual ssize_t read        (void *p_buffer, size_t len) override;
-
-                void setUsed( bool ) override;
-                const ConnectionParams &getRedirection() const;
-                static const unsigned MAX_REDIRECTS = 3;
-
-            protected:
-                virtual bool    connected   () const;
-                virtual bool    connect     ();
-                virtual void    disconnect  ();
-                virtual bool    send        (const void *buf, size_t size);
-                virtual bool    send        (const std::string &data);
-
-                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;
-
-                ssize_t         readChunk   (void *p_buffer, size_t len);
-                RequestStatus parseReply();
-                std::string readLine();
-                std::string useragent;
-                std::string referer;
-
-                AuthStorage        *authStorage;
-                ConnectionParams    locationparams;
-                ConnectionParams    proxyparams;
-                bool                connectionClose;
-                bool                chunked;
-                bool                chunked_eof;
-                size_t              chunkLength;
-                bool                queryOk;
-                int                 retries;
-                static const int    retryCount = 5;
+       class LibVLCHTTPConnection : public AbstractConnection
+       {
+            public:
+               LibVLCHTTPConnection(vlc_object_t *, AuthStorage *);
+               virtual ~LibVLCHTTPConnection();
+               virtual bool    canReuse     (const ConnectionParams &) const override;
+               virtual RequestStatus request(const std::string& path,
+                                             const BytesRange & = BytesRange()) override;
+               virtual ssize_t read         (void *p_buffer, size_t len) override;
+               virtual void    setUsed      ( bool ) override;
 
             private:
-                Transport *transport;
+               void reset();
+               std::string useragent;
+               std::string referer;
+               LibVLCHTTPSource *source;
+               ChunksSourceStream *sourceStream;
+               stream_t *stream;
        };
 
        class StreamUrlConnection : public AbstractConnection
@@ -140,11 +119,11 @@ namespace adaptive
                virtual AbstractConnection * createConnection(vlc_object_t *, const ConnectionParams &) = 0;
        };
 
-       class NativeConnectionFactory : public AbstractConnectionFactory
+       class LibVLCHTTPConnectionFactory : public AbstractConnectionFactory
        {
            public:
-               NativeConnectionFactory( AuthStorage * );
-               virtual ~NativeConnectionFactory();
+               LibVLCHTTPConnectionFactory( AuthStorage * );
+               virtual ~LibVLCHTTPConnectionFactory() = default;
                virtual AbstractConnection * createConnection(vlc_object_t *, const ConnectionParams &) override;
            private:
                AuthStorage *authStorage;


=====================================
modules/demux/adaptive/http/HTTPConnectionManager.cpp
=====================================
@@ -28,7 +28,6 @@
 #include "HTTPConnectionManager.h"
 #include "HTTPConnection.hpp"
 #include "ConnectionParams.hpp"
-#include "Transport.hpp"
 #include "Downloader.hpp"
 #include "tools/Debug.hpp"
 #include <vlc_url.h>


=====================================
modules/demux/adaptive/http/Transport.cpp deleted
=====================================
@@ -1,113 +0,0 @@
-/*
- * Transport.cpp
- *****************************************************************************
- * Copyright (C) 2015-2018 VideoLabs, VideoLAN and VLC authors
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "Transport.hpp"
-
-using namespace adaptive::http;
-
-Transport::Transport(bool b_secure_)
-{
-    creds = nullptr;
-    tls = nullptr;
-    b_secure = b_secure_;
-}
-
-Transport::~Transport()
-{
-    if(connected())
-        disconnect();
-}
-
-bool Transport::connect(vlc_object_t *p_object, const std::string &hostname, int port)
-{
-    if(connected())
-        disconnect();
-
-    if(b_secure)
-    {
-        creds = vlc_tls_ClientCreate(p_object);
-        if(!creds)
-            return false;
-        tls = vlc_tls_SocketOpenTLS(creds, hostname.c_str(), port, "https",
-                                    nullptr, nullptr );
-        if(!tls)
-        {
-            vlc_tls_ClientDelete(creds);
-            creds = nullptr;
-        }
-    }
-    else
-    {
-        tls = vlc_tls_SocketOpenTCP(p_object, hostname.c_str(), port);
-    }
-
-    return tls != nullptr;
-}
-
-bool Transport::connected() const
-{
-    return tls != nullptr;
-}
-
-void Transport::disconnect()
-{
-    if(tls)
-    {
-        vlc_tls_Close(tls);
-        tls = nullptr;
-    }
-
-    if(creds)
-    {
-        vlc_tls_ClientDelete(creds);
-        creds = nullptr;
-    }
-}
-
-ssize_t Transport::read(void *p_buffer, size_t len)
-{
-    return vlc_tls_Read(tls, p_buffer, len, true);
-}
-
-std::string Transport::readline()
-{
-    char *line = ::vlc_tls_GetLine(tls);
-    if(line == nullptr)
-        return "";
-
-    std::string ret(line);
-    ::free(line);
-    return ret;
-}
-
-bool Transport::send(const void *buf, size_t size)
-{
-    if (!connected())
-        return false;
-
-    if (size == 0)
-        return true;
-
-    return vlc_tls_Write(tls, buf, size) == (ssize_t)size;
-}
-


=====================================
modules/demux/adaptive/http/Transport.hpp deleted
=====================================
@@ -1,51 +0,0 @@
-/*
- * Transport.hpp
- *****************************************************************************
- * Copyright (C) 2015-2018 - VideoLabs, VideoLAN and VLC authors
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-#ifndef TRANSPORT_HPP
-#define TRANSPORT_HPP
-
-#include <vlc_common.h>
-#include <vlc_tls.h>
-#include <string>
-
-namespace adaptive
-{
-    namespace http
-    {
-        class Transport
-        {
-            public:
-                Transport(bool b_secure = false);
-                ~Transport();
-                bool    connect     (vlc_object_t *, const std::string&, int port = 80);
-                bool    connected   () const;
-                bool    send        (const void *buf, size_t size);
-                ssize_t read        (void *p_buffer, size_t len);
-                std::string readline();
-                void    disconnect  ();
-
-            protected:
-                vlc_tls_client_t *creds;
-                vlc_tls_t *tls;
-                bool b_secure;
-        };
-    }
-}
-
-#endif // TRANSPORT_HPP



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1491d2c0e57d9f0928e0b1db8239ca4e646c6d7f...be436e0ed29642489af90a1ca2cabbca38a511c6

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1491d2c0e57d9f0928e0b1db8239ca4e646c6d7f...be436e0ed29642489af90a1ca2cabbca38a511c6
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list