[vlc-devel] [PATCH 09/10][RFC][WIP] cloudstorage: replaced microhttpd dependency by using vlc_httpd
Diogo Silva
dbtdsilva at gmail.com
Thu Aug 17 03:08:17 CEST 2017
---
modules/access/Makefile.am | 4 +-
modules/access/cloudstorage/access.cpp | 3 +-
modules/access/cloudstorage/provider_httpd.cpp | 222 +++++++++++++++++++++++++
modules/access/cloudstorage/provider_httpd.h | 109 ++++++++++++
po/POTFILES.in | 2 +
5 files changed, 338 insertions(+), 2 deletions(-)
create mode 100644 modules/access/cloudstorage/provider_httpd.cpp
create mode 100644 modules/access/cloudstorage/provider_httpd.h
diff --git a/modules/access/Makefile.am b/modules/access/Makefile.am
index d1737d5e56..32b80afa2b 100644
--- a/modules/access/Makefile.am
+++ b/modules/access/Makefile.am
@@ -318,7 +318,9 @@ libcloudstorage_plugin_la_SOURCES = \
access/cloudstorage/access.h access/cloudstorage/access.cpp \
access/cloudstorage/services_discovery.h \
access/cloudstorage/services_discovery.cpp \
- access/cloudstorage/provider_callback.h
+ access/cloudstorage/provider_callback.h \
+ access/cloudstorage/provider_httpd.h \
+ access/cloudstorage/provider_httpd.cpp
libcloudstorage_plugin_la_CXXFLAGS = $(CXXFLAGS_cloudstorage) $(AM_CXXFLAGS)
libcloudstorage_plugin_la_LIBADD = $(LIBS_cloudstorage)
libcloudstorage_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(accessdir)'
diff --git a/modules/access/cloudstorage/access.cpp b/modules/access/cloudstorage/access.cpp
index e2c37963fe..c4780e53f6 100644
--- a/modules/access/cloudstorage/access.cpp
+++ b/modules/access/cloudstorage/access.cpp
@@ -30,6 +30,7 @@
#include <IRequest.h>
#include "provider_callback.h"
+#include "provider_httpd.h"
using cloudstorage::ICloudStorage;
using cloudstorage::ICloudProvider;
@@ -179,7 +180,7 @@ static int InitProvider( stream_t * p_access )
std::unique_ptr<Callback>( new Callback( p_access ) ),
nullptr,
nullptr,
- nullptr,
+ std::unique_ptr<HttpdFactory>( new HttpdFactory( p_access ) ),
hints
});
diff --git a/modules/access/cloudstorage/provider_httpd.cpp b/modules/access/cloudstorage/provider_httpd.cpp
new file mode 100644
index 0000000000..e3d0c3f0a0
--- /dev/null
+++ b/modules/access/cloudstorage/provider_httpd.cpp
@@ -0,0 +1,222 @@
+/*****************************************************************************
+ * provider_httpd.cpp: Inherit class IHttpd from libcloudstorage
+ *****************************************************************************
+ * Copyright (C) 2017 VideoLabs and VideoLAN
+ *
+ * Authors: Diogo Silva <dbtdsilva at gmail.com>
+ *
+ * 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.
+ *****************************************************************************/
+
+#include "provider_httpd.h"
+
+#include <vlc_url.h>
+#include <sstream>
+#include <map>
+
+int Httpd::httpRequestCallback( httpd_callback_sys_t * cls,
+ httpd_client_t * client, httpd_message_t * answer,
+ const httpd_message_t * query )
+{
+ (void) client;
+ Httpd* server = (Httpd *) cls;
+
+ // Pre-fill data to be sent to the callback
+ std::unordered_map<std::string, std::string> args, headers;
+ std::string argument;
+ if ( query->psz_args != nullptr )
+ {
+ std::istringstream iss( std::string(
+ vlc_uri_decode( (char*) query->psz_args ) ) );
+ while ( std::getline( iss, argument, '&' ) ) {
+ size_t equal_div = argument.find('=');
+ if ( equal_div == std::string::npos )
+ continue;
+
+ std::string key = argument.substr( 0, equal_div );
+ std::string value = argument.substr( equal_div + 1 );
+ args.insert( std::make_pair( key, value ) );
+ }
+ }
+ for (unsigned int i = 0; i < query->i_headers; i++) {
+ headers.insert( std::make_pair(
+ query->p_headers[i].name, query->p_headers[i].value ) );
+ }
+ Httpd::Connection connection( query->psz_url, args, headers );
+
+ // Inform about a received connection in order to get the proper response
+ auto response_ptr = server->callback()->
+ receivedConnection( *server, &connection );
+ auto response = static_cast<Httpd::Response*>( response_ptr.get() );
+
+ // Fill the data to be requests to the lib
+ answer->i_proto = HTTPD_PROTO_HTTP;
+ answer->i_version= 1;
+ answer->i_type = HTTPD_MSG_ANSWER;
+ answer->i_status = response->getCode();
+
+ IResponse::Headers r_headers = response->getHeaders();
+ answer->i_headers = r_headers.size();
+ for ( auto header : r_headers )
+ httpd_MsgAdd( answer,
+ header.first.c_str(), "%s", header.second.c_str() );
+ answer->i_body = response->getBody().length();
+ char * message = strdup( response->getBody().c_str() );
+ answer->p_body = (unsigned char *) message;
+
+ httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
+
+ return VLC_SUCCESS;
+}
+
+Httpd::Response::Response( int code, const IResponse::Headers& headers,
+ const std::string& body ) :
+ i_code( code ), m_headers( headers ), p_body( body ) {}
+
+Httpd::CallbackResponse::CallbackResponse( int code,
+ const IResponse::Headers& headers, int size, int chunk_size,
+ IResponse::ICallback::Pointer ptr )
+{
+ // Not required for authorization purposes
+ (void) code; (void) headers; (void) size; (void) chunk_size; (void) ptr;
+}
+
+Httpd::Connection::Connection( const char* url,
+ const std::unordered_map<std::string, std::string>& args,
+ const std::unordered_map<std::string, std::string>& headers ) :
+ c_url( url ), m_args( args ), m_headers( headers ) {}
+
+const char* Httpd::Connection::getParameter(
+ const std::string& name) const
+{
+ auto element = m_args.find(name);
+ return element == m_args.end() ? nullptr : element->second.c_str();
+}
+
+const char* Httpd::Connection::header(const std::string& name) const
+{
+ auto element = m_headers.find(name);
+ return element == m_headers.end() ? nullptr : element->second.c_str();
+}
+
+std::string Httpd::Connection::url() const
+{
+ return c_url;
+}
+
+void Httpd::Connection::onCompleted(CompletedCallback f)
+{
+ ptr_callback = f;
+}
+
+void Httpd::Connection::suspend()
+{
+ // Not required for authorization purposes
+}
+
+void Httpd::Connection::resume()
+{
+ // Not required for authorization purposes
+}
+
+Httpd::Httpd( IHttpServer::ICallback::Pointer cb, IHttpServer::Type type,
+ stream_t * access ) :
+ p_callback( cb ), host( nullptr ), url_root( nullptr ),
+ url_login( nullptr )
+{
+ // Prevent the usage of this server for other effects than authorization
+ if ( type != IHttpServer::Type::Authorization )
+ {
+ throw std::runtime_error("Provider used for this purpose is not "
+ "support since this http server should only be used for "
+ "authorization purposes");
+ }
+
+ host = vlc_http_HostNew( VLC_OBJECT( access ) );
+
+ // Exception is handled by HttpdFactory right away
+ if ( host == nullptr )
+ throw std::runtime_error("Failed to create host");
+
+ // Spawns two URLs that might receive requests
+ url_root = httpd_UrlNew( host, "/auth", NULL, NULL );
+ url_login = httpd_UrlNew( host, "/auth/login", NULL, NULL );
+
+ if ( url_root != nullptr )
+ {
+ httpd_UrlCatch( url_root, HTTPD_MSG_HEAD, httpRequestCallback,
+ (httpd_callback_sys_t*) this );
+ httpd_UrlCatch( url_root, HTTPD_MSG_GET, httpRequestCallback,
+ (httpd_callback_sys_t*) this );
+ httpd_UrlCatch( url_root, HTTPD_MSG_POST, httpRequestCallback,
+ (httpd_callback_sys_t*) this );
+ }
+
+ if ( url_login != nullptr )
+ {
+ httpd_UrlCatch( url_login, HTTPD_MSG_HEAD, httpRequestCallback,
+ (httpd_callback_sys_t*) this );
+ httpd_UrlCatch( url_login, HTTPD_MSG_GET, httpRequestCallback,
+ (httpd_callback_sys_t*) this );
+ httpd_UrlCatch( url_login, HTTPD_MSG_POST, httpRequestCallback,
+ (httpd_callback_sys_t*) this );
+ }
+}
+
+Httpd::~Httpd()
+{
+ if ( host != nullptr )
+ {
+ if ( url_root != nullptr )
+ httpd_UrlDelete( url_root );
+ if ( url_login != nullptr )
+ httpd_UrlDelete( url_login );
+ httpd_HostDelete ( host );
+ }
+}
+
+Httpd::IResponse::Pointer Httpd::createResponse( int code,
+ const IResponse::Headers& headers, const std::string& body ) const
+{
+ return std::make_unique<Response>(code, headers, body);
+}
+
+Httpd::IResponse::Pointer Httpd::createResponse( int code,
+ const IResponse::Headers& headers, int size, int chunk_size,
+ IResponse::ICallback::Pointer ptr ) const
+{
+ return std::make_unique<CallbackResponse>( code, headers, size, chunk_size,
+ std::move( ptr ) );
+}
+
+HttpdFactory::HttpdFactory( stream_t* access ) : p_access( access ) {}
+
+IHttpServer::Pointer HttpdFactory::create(
+ IHttpServer::ICallback::Pointer cb, const std::string&,
+ IHttpServer::Type type )
+{
+ IHttpServer::Pointer ptr;
+ try
+ {
+ ptr = std::make_unique<Httpd>( cb, type, p_access );
+ }
+ catch ( const std::runtime_error& exception )
+ {
+ msg_Err( p_access, "Failed to create Http server: %s",
+ exception.what() );
+ ptr = nullptr;
+ }
+ return ptr;
+}
diff --git a/modules/access/cloudstorage/provider_httpd.h b/modules/access/cloudstorage/provider_httpd.h
new file mode 100644
index 0000000000..dde69b16a3
--- /dev/null
+++ b/modules/access/cloudstorage/provider_httpd.h
@@ -0,0 +1,109 @@
+/*****************************************************************************
+ * provider_httpd.h: Inherit class IHttpServer from libcloudstorage
+ *****************************************************************************
+ * Copyright (C) 2017 VideoLabs and VideoLAN
+ *
+ * Authors: Diogo Silva <dbtdsilva at gmail.com>
+ *
+ * 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 receivedaaaw 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 VLC_CLOUDSTORAGE_PROVIDER_HTTPD_H
+#define VLC_CLOUDSTORAGE_PROVIDER_HTTPD_H
+
+#include "access.h"
+
+#include <string>
+#include <unordered_map>
+#include <vlc_httpd.h>
+
+using cloudstorage::IHttpServer;
+using cloudstorage::IHttpServerFactory;
+
+class Httpd : public IHttpServer
+{
+public:
+ Httpd( IHttpServer::ICallback::Pointer cb, IHttpServer::Type type,
+ stream_t * access );
+ ~Httpd();
+
+ class Response : public IResponse {
+ public:
+ Response() = default;
+ Response( int code, const IResponse::Headers&,
+ const std::string& body );
+
+ int getCode() { return i_code; }
+ IResponse::Headers getHeaders() { return m_headers; }
+ const std::string& getBody() { return p_body; }
+ private:
+ int i_code;
+ IResponse::Headers m_headers;
+ const std::string p_body;
+ };
+
+ class CallbackResponse : public Response {
+ public:
+ CallbackResponse(int code, const IResponse::Headers&, int size,
+ int chunk_size, IResponse::ICallback::Pointer);
+ };
+
+ class Connection : public IConnection {
+ public:
+ Connection( const char* url,
+ const std::unordered_map<std::string, std::string>& args,
+ const std::unordered_map<std::string, std::string>& headers );
+ const char* getParameter( const std::string& name ) const override;
+ const char* header( const std::string& name ) const override;
+ std::string url() const override;
+ void onCompleted(CompletedCallback) override;
+ void suspend() override;
+ void resume() override;
+
+ private:
+ std::string c_url;
+ CompletedCallback ptr_callback;
+ const std::unordered_map<std::string, std::string> m_args;
+ const std::unordered_map<std::string, std::string> m_headers;
+ };
+
+ IResponse::Pointer createResponse( int code, const IResponse::Headers&,
+ const std::string& body ) const override;
+ IResponse::Pointer createResponse( int code, const IResponse::Headers&,
+ int size, int chunk_size,
+ IResponse::ICallback::Pointer ) const override;
+ ICallback::Pointer callback() const { return p_callback; }
+private:
+ static int httpRequestCallback( httpd_callback_sys_t * args,
+ httpd_client_t *, httpd_message_t * answer,
+ const httpd_message_t * query_t );
+
+ ICallback::Pointer p_callback;
+ httpd_host_t *host;
+ httpd_url_t *url_root, *url_login;
+};
+
+class HttpdFactory : public IHttpServerFactory
+{
+public:
+ HttpdFactory( stream_t* access );
+ IHttpServer::Pointer create( IHttpServer::ICallback::Pointer,
+ const std::string& session_id,
+ IHttpServer::Type ) override;
+private:
+ stream_t* p_access;
+};
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8bfa9577f0..dd1bbcaf74 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -181,6 +181,8 @@ modules/access/cloudstorage.cpp
modules/access/cloudstorage/access.cpp
modules/access/cloudstorage/access.h
modules/access/cloudstorage/provider_callback.h
+modules/access/cloudstorage/provider_httpd.cpp
+modules/access/cloudstorage/provider_httpd.h
modules/access/cloudstorage/services_discovery.cpp
modules/access/cloudstorage/services_discovery.h
modules/access/concat.c
--
2.14.1
More information about the vlc-devel
mailing list