ucb/source/ucp/webdav-curl/CurlSession.cxx | 17 +++++++++++++++-- ucb/source/ucp/webdav-curl/CurlSession.hxx | 6 +++++- ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx | 11 +++++++++-- ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx | 5 +++++ ucb/source/ucp/webdav-curl/DAVSession.hxx | 7 ++++++- ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx | 7 ++++--- ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx | 12 +++++++++--- ucb/source/ucp/webdav-curl/webdavcontent.cxx | 21 +++++++++++++++++---- ucb/source/ucp/webdav-curl/webdavcontent.hxx | 4 ++-- 9 files changed, 72 insertions(+), 18 deletions(-)
New commits: commit d80ad1370b65987505fd5aedd3ac17ff8b1ee0ed Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Wed Oct 6 15:40:57 2021 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Mon Nov 1 18:20:33 2021 +0100 ucb: webdav-curl: add OpenCommandArg3 "KeepAlive" support This is based on the following commits, which conflict everywhere, except the code in CurlSession.* is new. commit 09954fc863c8ee900f157cab4458e1dcf51493d3 Author: Thorsten Behrens <tbehr...@suse.com> AuthorDate: Tue Jan 17 04:59:56 2012 +0100 Fix UpdateCheck clog up server by keeping connection alive The update check protocol uses the webdav ucp, which uses neon, which in turn defaults to keeping the connection alive. this is nice for webdav, but disastrous for millions of clients phoning home to the same server. Using neon directly in updatefeed.cxx is not an option, due to the thread safety problems around that (see e.g. rhbz#544619) - so we had to extend it to accept connection options, and reuse the existing webdav provider. commit 29bd62fdc2792e215999e9dd0ec9a4bf1102201d Author: Thorsten Behrens <tbehr...@suse.com> AuthorDate: Tue Jan 17 11:41:14 2012 +0100 Switch flag sequence of OpenCommandArg3 to NamedValue. Based on feedback for 09954fc863c8ee900f157cab4458e1dcf51493d3, using the less-bulky NamedValue type instead of PropertyValue. Change-Id: I48e07dd4c3f189eb4445ed95a67011131d7b49f9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123174 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx index 2374ccbc26f2..6605ffc4f9ac 100644 --- a/ucb/source/ucp/webdav-curl/CurlSession.cxx +++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx @@ -18,6 +18,7 @@ #include <officecfg/Inet.hxx> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/io/Pipe.hpp> #include <com/sun/star/io/SequenceInputStream.hpp> #include <com/sun/star/io/SequenceOutputStream.hpp> @@ -433,9 +434,11 @@ static auto ExtractRealm(ResponseHeaders const& rHeaders, char const* const pAut CurlSession::CurlSession(uno::Reference<uno::XComponentContext> const& xContext, ::rtl::Reference<DAVSessionFactory> const& rpFactory, OUString const& rURI, + uno::Sequence<beans::NamedValue> const& rFlags, ::ucbhelper::InternetProxyDecider const& rProxyDecider) : DAVSession(rpFactory) , m_xContext(xContext) + , m_Flags(rFlags) , m_URI(rURI) , m_Proxy(rProxyDecider.getProxy(m_URI.GetScheme(), m_URI.GetHost(), m_URI.GetPort())) { @@ -533,18 +536,28 @@ CurlSession::CurlSession(uno::Reference<uno::XComponentContext> const& xContext, rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_PROXYAUTH, CURLAUTH_ANY); assert(rc == CURLE_OK); // ANY is always available } + auto const it(::std::find_if(m_Flags.begin(), m_Flags.end(), + [](auto const& rFlag) { return rFlag.Name == "KeepAlive"; })); + if (it != m_Flags.end() && it->Value.get<bool>()) + { + // neon would close the connection from ne_end_request(), this seems + // to be the equivalent and not CURLOPT_TCP_KEEPALIVE + rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_FORBID_REUSE, 1L); + assert(rc == CURLE_OK); + } } CurlSession::~CurlSession() {} -auto CurlSession::CanUse(OUString const& rURI) -> bool +auto CurlSession::CanUse(OUString const& rURI, uno::Sequence<beans::NamedValue> const& rFlags) + -> bool { try { CurlUri const uri(rURI); return m_URI.GetScheme() == uri.GetScheme() && m_URI.GetHost() == uri.GetHost() - && m_URI.GetPort() == uri.GetPort(); + && m_URI.GetPort() == uri.GetPort() && m_Flags == rFlags; } catch (DAVException const&) { diff --git a/ucb/source/ucp/webdav-curl/CurlSession.hxx b/ucb/source/ucp/webdav-curl/CurlSession.hxx index 4c33c795d940..e7e566c0fe99 100644 --- a/ucb/source/ucp/webdav-curl/CurlSession.hxx +++ b/ucb/source/ucp/webdav-curl/CurlSession.hxx @@ -25,6 +25,8 @@ private: /// mutex required to access all other non-const members ::std::mutex m_Mutex; css::uno::Reference<css::uno::XComponentContext> const m_xContext; + /// flags may be passed to constructor, e.g. "KeepAlive" + css::uno::Sequence<css::beans::NamedValue> const m_Flags; CurlUri const m_URI; /// buffer for libcurl detailed error messages char m_ErrorBuffer[CURL_ERROR_SIZE]; @@ -43,10 +45,12 @@ private: public: explicit CurlSession(css::uno::Reference<css::uno::XComponentContext> const& xContext, ::rtl::Reference<DAVSessionFactory> const& rpFactory, OUString const& rURI, + css::uno::Sequence<css::beans::NamedValue> const& rFlags, ::ucbhelper::InternetProxyDecider const& rProxyDecider); virtual ~CurlSession() override; - virtual auto CanUse(OUString const& rURI) -> bool override; + virtual auto CanUse(OUString const& rURI, + css::uno::Sequence<css::beans::NamedValue> const& rFlags) -> bool override; virtual auto UsesProxy() -> bool override; diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx index 3ac379c9da70..34c3429f3bf3 100644 --- a/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx +++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx @@ -136,6 +136,7 @@ DAVResourceAccess::DAVResourceAccess( DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther ) : m_aURL( rOther.m_aURL ), m_aPath( rOther.m_aPath ), + m_aFlags( rOther.m_aFlags ), m_xSession( rOther.m_xSession ), m_xSessionFactory( rOther.m_xSessionFactory ), m_xContext( rOther.m_xContext ), @@ -149,6 +150,7 @@ DAVResourceAccess & DAVResourceAccess::operator=( { m_aURL = rOther.m_aURL; m_aPath = rOther.m_aPath; + m_aFlags = rOther.m_aFlags; m_xSession = rOther.m_xSession; m_xSessionFactory = rOther.m_xSessionFactory; m_xContext = rOther.m_xContext; @@ -960,6 +962,11 @@ void DAVResourceAccess::UNLOCK( while ( bRetry ); } +void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& rFlags ) +{ + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_aFlags = rFlags; +} void DAVResourceAccess::setURL( const OUString & rNewURL ) { @@ -986,13 +993,13 @@ void DAVResourceAccess::initialize() if ( aURI.GetHost().isEmpty() ) throw DAVException( DAVException::DAV_INVALID_ARG ); - if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL ) ) + if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL, m_aFlags ) ) { m_xSession.clear(); // create new webdav session m_xSession - = m_xSessionFactory->createDAVSession( m_aURL, m_xContext ); + = m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, m_xContext ); if ( !m_xSession.is() ) return; diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx index 639e22e29611..1fce8d1377dd 100644 --- a/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx +++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx @@ -26,6 +26,7 @@ #include <osl/mutex.hxx> #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/ucb/Lock.hpp> #include <com/sun/star/ucb/XCommandEnvironment.hpp> #include <com/sun/star/ucb/WebDAVHTTPMethod.hpp> @@ -46,6 +47,7 @@ class DAVResourceAccess osl::Mutex m_aMutex; OUString m_aURL; OUString m_aPath; + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > m_aFlags; rtl::Reference< DAVSession > m_xSession; rtl::Reference< DAVSessionFactory > m_xSessionFactory; css::uno::Reference< css::uno::XComponentContext > m_xContext; @@ -60,6 +62,9 @@ public: DAVResourceAccess & operator=( const DAVResourceAccess & rOther ); + /// @throws DAVException + void setFlags( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rFlags ); + /// @throws DAVException void setURL( const OUString & rNewURL ); diff --git a/ucb/source/ucp/webdav-curl/DAVSession.hxx b/ucb/source/ucp/webdav-curl/DAVSession.hxx index d5e8e4ad0a57..88a41ab3153f 100644 --- a/ucb/source/ucp/webdav-curl/DAVSession.hxx +++ b/ucb/source/ucp/webdav-curl/DAVSession.hxx @@ -29,6 +29,10 @@ #include "DAVTypes.hxx" #include "DAVRequestEnvironment.hxx" +namespace com { namespace sun { namespace star { namespace beans { + struct NamedValue; +} } } } + namespace com::sun::star::ucb { struct Lock; } @@ -55,7 +59,8 @@ public: } } - virtual bool CanUse( const OUString & rURI ) = 0; + virtual bool CanUse( const OUString & rURI, + const ::com::sun::star::uno::Sequence<::com::sun::star::beans::NamedValue>& rFlags ) = 0; virtual bool UsesProxy() = 0; diff --git a/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx b/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx index 25113e2eb2a7..bbb7a48bcf0a 100644 --- a/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx +++ b/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx @@ -31,6 +31,7 @@ DAVSessionFactory::~DAVSessionFactory() rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession( const OUString & inUri, + const uno::Sequence< beans::NamedValue >& rFlags, const uno::Reference< uno::XComponentContext > & rxContext ) { osl::MutexGuard aGuard( m_aMutex ); @@ -39,14 +40,14 @@ rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession( m_xProxyDecider.reset( new ucbhelper::InternetProxyDecider( rxContext ) ); Map::iterator aIt = std::find_if(m_aMap.begin(), m_aMap.end(), - [&inUri](const Map::value_type& rEntry) { return rEntry.second->CanUse( inUri ); }); + [&inUri, &rFlags](const Map::value_type& rEntry) { return rEntry.second->CanUse( inUri, rFlags ); }); if ( aIt == m_aMap.end() ) { CurlUri const aURI( inUri ); std::unique_ptr< DAVSession > xElement( - new CurlSession(rxContext, this, inUri, *m_xProxyDecider) ); + new CurlSession(rxContext, this, inUri, rFlags, *m_xProxyDecider) ); aIt = m_aMap.emplace( inUri, xElement.get() ).first; aIt->second->m_aContainerIt = aIt; @@ -69,7 +70,7 @@ rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession( // call a little: CurlUri const aURI( inUri ); - aIt->second = new CurlSession(rxContext, this, inUri, *m_xProxyDecider); + aIt->second = new CurlSession(rxContext, this, inUri, rFlags, *m_xProxyDecider); aIt->second->m_aContainerIt = aIt; return aIt->second; } diff --git a/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx b/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx index 4b932ea6d2f4..b0d426f43bf3 100644 --- a/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx +++ b/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx @@ -32,6 +32,11 @@ using namespace com::sun::star; +namespace com::sun::star::beans +{ +struct NamedValue; +} + namespace com::sun::star::lang { class XMultiServiceFactory; @@ -47,9 +52,10 @@ public: virtual ~DAVSessionFactory() override; /// @throws DAVException - rtl::Reference<DAVSession> - createDAVSession(const OUString& inUri, - const css::uno::Reference<css::uno::XComponentContext>& rxContext); + rtl::Reference<DAVSession> createDAVSession( + const OUString& inUri, + const ::com::sun::star::uno::Sequence<::com::sun::star::beans::NamedValue>& rFlags, + const css::uno::Reference<css::uno::XComponentContext>& rxContext); private: typedef std::map<OUString, DAVSession*> Map; diff --git a/ucb/source/ucp/webdav-curl/webdavcontent.cxx b/ucb/source/ucp/webdav-curl/webdavcontent.cxx index 058a22646c1f..f001c442ab4c 100644 --- a/ucb/source/ucp/webdav-curl/webdavcontent.cxx +++ b/ucb/source/ucp/webdav-curl/webdavcontent.cxx @@ -60,7 +60,7 @@ #include <com/sun/star/ucb/MissingPropertiesException.hpp> #include <com/sun/star/ucb/NameClash.hpp> #include <com/sun/star/ucb/NameClashException.hpp> -#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#include <com/sun/star/ucb/OpenCommandArgument3.hpp> #include <com/sun/star/ucb/OpenMode.hpp> #include <com/sun/star/ucb/PostCommandArgument2.hpp> #include <com/sun/star/ucb/PropertyCommandArgument.hpp> @@ -514,8 +514,9 @@ uno::Any SAL_CALL Content::execute( // open - ucb::OpenCommandArgument2 aOpenCommand; - if ( !( aCommand.Argument >>= aOpenCommand ) ) + ucb::OpenCommandArgument3 aOpenCommand; + ucb::OpenCommandArgument2 aTmp; + if ( !( aCommand.Argument >>= aTmp ) ) { ucbhelper::cancelCommandExecution( uno::makeAny( lang::IllegalArgumentException( @@ -525,6 +526,15 @@ uno::Any SAL_CALL Content::execute( Environment ); // Unreachable } + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + // compat mode, extract Arg2 info into newer structure + aOpenCommand.Mode = aTmp.Mode; + aOpenCommand.Priority = aTmp.Priority; + aOpenCommand.Sink = aTmp.Sink; + aOpenCommand.Properties = aTmp.Properties; + aOpenCommand.SortingInfo = aTmp.SortingInfo; + } aRet = open( aOpenCommand, Environment ); @@ -1964,7 +1974,7 @@ uno::Sequence< uno::Any > Content::setPropertyValues( uno::Any Content::open( - const ucb::OpenCommandArgument2 & rArg, + const ucb::OpenCommandArgument3 & rArg, const uno::Reference< ucb::XCommandEnvironment > & xEnv ) { uno::Any aRet; @@ -2030,6 +2040,7 @@ uno::Any Content::open( new DAVResourceAccess( *m_xResAccess ) ); } + xResAccess->setFlags( rArg.OpeningFlags ); DAVResource aResource; std::vector< OUString > aHeaders; @@ -2072,6 +2083,8 @@ uno::Any Content::open( new DAVResourceAccess( *m_xResAccess ) ); } + xResAccess->setFlags( rArg.OpeningFlags ); + // fill inputstream sync; return if all data present DAVResource aResource; std::vector< OUString > aHeaders; diff --git a/ucb/source/ucp/webdav-curl/webdavcontent.hxx b/ucb/source/ucp/webdav-curl/webdavcontent.hxx index 5aabca16522f..dc1a93cbac97 100644 --- a/ucb/source/ucp/webdav-curl/webdavcontent.hxx +++ b/ucb/source/ucp/webdav-curl/webdavcontent.hxx @@ -43,7 +43,7 @@ namespace com::sun::star::sdbc { } namespace com::sun::star::ucb { - struct OpenCommandArgument2; + struct OpenCommandArgument3; struct PropertyCommandArgument; struct PostCommandArgument2; struct TransferInfo; @@ -125,7 +125,7 @@ private: // Command "open" /// @throws css::uno::Exception css::uno::Any open( - const css::ucb::OpenCommandArgument2 & rArg, + const css::ucb::OpenCommandArgument3 & rArg, const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );