[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 ¶ms, 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 ¶ms_)
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 ¶ms_) 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 ¶ms_) 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 ¶ms)
+AbstractConnection * LibVLCHTTPConnectionFactory::createConnection(vlc_object_t *p_object,
+ const ConnectionParams ¶ms)
{
- 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