Kaydet (Commit) 09954fc8 authored tarafından Thorsten Behrens's avatar Thorsten Behrens

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.
üst d3193875
......@@ -31,6 +31,7 @@
#include <cppuhelper/implbase4.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <com/sun/star/beans/Property.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/configuration/theDefaultProvider.hpp>
......@@ -47,7 +48,7 @@
#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
#include <com/sun/star/ucb/XContentProvider.hpp>
#include "com/sun/star/ucb/XInteractionSupplyAuthentication.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/sdbc/XRow.hpp>
#include <com/sun/star/task/PasswordContainerInteractionHandler.hpp>
......@@ -481,10 +482,18 @@ UpdateInformationProvider::load(const rtl::OUString& rURL)
uno::Reference< ucb::XCommandProcessor > xCommandProcessor(m_xContentProvider->queryContent(xId), uno::UNO_QUERY_THROW);
rtl::Reference< ActiveDataSink > aSink(new ActiveDataSink());
ucb::OpenCommandArgument2 aOpenArgument;
// Disable KeepAlive in webdav - don't want millions of office
// instances phone home & clog up servers
uno::Sequence< beans::PropertyValue > aProps( 1 );
aProps[ 0 ] = beans::PropertyValue(
UNISTRING("KeepAlive"), -1,
uno::makeAny(sal_False), beans::PropertyState_DIRECT_VALUE);
ucb::OpenCommandArgument3 aOpenArgument;
aOpenArgument.Mode = ucb::OpenMode::DOCUMENT;
aOpenArgument.Priority = 32768;
aOpenArgument.Sink = *aSink;
aOpenArgument.OpeningFlags = aProps;
ucb::Command aCommand;
aCommand.Name = UNISTRING("open");
......
......@@ -3811,6 +3811,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,offapi,offapi/com/sun/star/ucb,\
NumberedSortingInfo \
OpenCommandArgument \
OpenCommandArgument2 \
OpenCommandArgument3 \
OpenMode \
OutgoingMessageState \
PostCommandArgument \
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Version: MPL 1.1 / GPLv3+ / LGPLv3+
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License or as specified alternatively below. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Major Contributor(s):
* Copyright (C) 2012 Thorsten Behrens <tbehrens@suse.com> (initial developer)
*
* All Rights Reserved.
*
* For minor contributions see the git repository.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 3 or later (the "GPLv3+"), or
* the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
* in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
* instead of those above.
*/
#ifndef __com_sun_star_ucb_OpenCommandArgument3_idl__
#define __com_sun_star_ucb_OpenCommandArgument3_idl__
#include <com/sun/star/ucb/OpenCommandArgument2.idl>
#include <com/sun/star/beans/PropertyValue.idl>
module com { module sun { module star { module ucb {
/** Extended argument for commands like "open"
<p>We're extending OpenCommandArgument even more, to provide some opening flags on to webdav.
@see XCommandProcessor
*/
published struct OpenCommandArgument3 : OpenCommandArgument2
{
//-------------------------------------------------------------------------
/** Flags to use for opening.
<p>WebDav e.g. uses "KeepAlive" to enable/disable the respective http feature.
*/
sequence< com::sun::star::beans::PropertyValue > OpeningFlags;
};
}; }; }; };
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -151,6 +151,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_xSMgr( rOther.m_xSMgr ),
......@@ -164,6 +165,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_xSMgr = rOther.m_xSMgr;
......@@ -1042,6 +1044,14 @@ void DAVResourceAccess::UNLOCK(
while ( bRetry );
}
//=========================================================================
void DAVResourceAccess::setFlags( const uno::Sequence< beans::PropertyValue >& rFlags )
throw ( DAVException )
{
osl::Guard< osl::Mutex > aGuard( m_aMutex );
m_aFlags = rFlags;
}
//=========================================================================
void DAVResourceAccess::setURL( const rtl::OUString & rNewURL )
throw( DAVException )
......@@ -1070,13 +1080,13 @@ void DAVResourceAccess::initialize()
if ( !aURI.GetHost().getLength() )
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_xSMgr );
= m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, m_xSMgr );
if ( !m_xSession.is() )
return;
......
......@@ -35,6 +35,7 @@
#include <osl/mutex.hxx>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/ucb/Lock.hpp>
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
#include "DAVAuthListener.hxx"
......@@ -54,6 +55,7 @@ class DAVResourceAccess
osl::Mutex m_aMutex;
rtl::OUString m_aURL;
rtl::OUString m_aPath;
::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aFlags;
rtl::Reference< DAVSession > m_xSession;
rtl::Reference< DAVSessionFactory > m_xSessionFactory;
com::sun::star::uno::Reference<
......@@ -71,6 +73,9 @@ public:
DAVResourceAccess & operator=( const DAVResourceAccess & rOther );
void setFlags( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rFlags )
throw ( DAVException );
void setURL( const rtl::OUString & rNewURL )
throw ( DAVException );
......
......@@ -40,6 +40,10 @@
#include "DAVTypes.hxx"
#include "DAVRequestEnvironment.hxx"
namespace com { namespace sun { namespace star { namespace beans {
struct PropertyValue;
} } } }
namespace com { namespace sun { namespace star { namespace ucb {
struct Lock;
} } } }
......@@ -66,7 +70,8 @@ public:
}
}
virtual sal_Bool CanUse( const ::rtl::OUString & inPath ) = 0;
virtual sal_Bool CanUse( const ::rtl::OUString & inPath,
const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rFlags ) = 0;
virtual sal_Bool UsesProxy() = 0;
......
......@@ -40,6 +40,7 @@ DAVSessionFactory::~DAVSessionFactory()
rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession(
const ::rtl::OUString & inUri,
const uno::Sequence< beans::PropertyValue >& rFlags,
const uno::Reference< lang::XMultiServiceFactory > & rxSMgr )
throw( DAVException )
{
......@@ -55,7 +56,7 @@ rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession(
while ( aIt != aEnd )
{
if ( (*aIt).second->CanUse( inUri ) )
if ( (*aIt).second->CanUse( inUri, rFlags ) )
break;
++aIt;
......@@ -66,7 +67,7 @@ rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession(
NeonUri aURI( inUri );
std::auto_ptr< DAVSession > xElement(
new NeonSession( this, inUri, *m_xProxyDecider.get() ) );
new NeonSession( this, inUri, rFlags, *m_xProxyDecider.get() ) );
aIt = m_aMap.insert( Map::value_type( inUri, xElement.get() ) ).first;
aIt->second->m_aContainerIt = aIt;
......@@ -89,7 +90,7 @@ rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession(
// call a little:
NeonUri aURI( inUri );
aIt->second = new NeonSession( this, inUri, *m_xProxyDecider.get() );
aIt->second = new NeonSession( this, inUri, rFlags, *m_xProxyDecider.get() );
aIt->second->m_aContainerIt = aIt;
return aIt->second;
}
......
......@@ -42,6 +42,10 @@
using namespace com::sun::star;
namespace com { namespace sun { namespace star { namespace beans {
struct PropertyValue;
} } } }
namespace com { namespace sun { namespace star { namespace lang {
class XMultiServiceFactory;
} } } }
......@@ -58,6 +62,7 @@ public:
rtl::Reference< DAVSession >
createDAVSession( const ::rtl::OUString & inUri,
const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rFlags,
const ::com::sun::star::uno::Reference<
::com::sun::star::lang::XMultiServiceFactory >&
rxSMgr )
......
......@@ -50,6 +50,7 @@ extern "C" {
#include "libxml/parser.h"
#include "rtl/ustrbuf.hxx"
#include "comphelper/sequence.hxx"
#include <comphelper/stl_types.hxx>
#include "ucbhelper/simplecertificatevalidationrequest.hxx"
#include "DAVAuthListener.hxx"
......@@ -69,8 +70,11 @@ extern "C" {
#include <com/sun/star/security/CertificateContainer.hpp>
#include <com/sun/star/security/XCertificateContainer.hpp>
#include <com/sun/star/ucb/Lock.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
#include <boost/bind.hpp>
using namespace com::sun::star;
using namespace webdav_ucp;
......@@ -150,6 +154,26 @@ static sal_uInt16 makeStatusCode( const rtl::OUString & rStatusText )
return sal_uInt16( rStatusText.copy( 0, nPos ).toInt32() );
}
// -------------------------------------------------------------------
static bool noKeepAlive( const uno::Sequence< beans::PropertyValue >& rFlags )
{
if ( !rFlags.hasElements() )
return false;
// find "KeepAlive" property
const beans::PropertyValue* pAry(rFlags.getConstArray());
const sal_Int32 nLen(rFlags.getLength());
const beans::PropertyValue* pValue(
std::find_if(pAry,pAry+nLen,
boost::bind(comphelper::TPropertyValueEqualFunctor(),
_1,
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("KeepAlive")))));
if ( pValue != pAry+nLen && !pValue->Value.get<sal_Bool>() )
return true;
return false;
}
// -------------------------------------------------------------------
struct NeonRequestContext
{
......@@ -619,9 +643,11 @@ NeonLockStore NeonSession::m_aNeonLockStore;
NeonSession::NeonSession(
const rtl::Reference< DAVSessionFactory > & rSessionFactory,
const rtl::OUString& inUri,
const uno::Sequence< beans::PropertyValue >& rFlags,
const ucbhelper::InternetProxyDecider & rProxyDecider )
throw ( DAVException )
: DAVSession( rSessionFactory ),
m_aFlags( rFlags ),
m_pHttpSession( 0 ),
m_pRequestData( new RequestDataMap ),
m_rProxyDecider( rProxyDecider )
......@@ -808,6 +834,10 @@ void NeonSession::Init()
m_nProxyPort );
}
// avoid KeepAlive?
if ( noKeepAlive(m_aFlags) )
ne_set_session_flag( m_pHttpSession, NE_SESSFLAG_PERSIST, 0 );
// Register for redirects.
ne_redirect_register( m_pHttpSession );
......@@ -824,14 +854,16 @@ void NeonSession::Init()
// -------------------------------------------------------------------
// virtual
sal_Bool NeonSession::CanUse( const rtl::OUString & inUri )
sal_Bool NeonSession::CanUse( const rtl::OUString & inUri,
const uno::Sequence< beans::PropertyValue >& rFlags )
{
try
{
NeonUri theUri( inUri );
if ( ( theUri.GetPort() == m_nPort ) &&
( theUri.GetHost() == m_aHostName ) &&
( theUri.GetScheme() == m_aScheme ) )
( theUri.GetScheme() == m_aScheme ) &&
( rFlags == m_aFlags ) )
return sal_True;
}
catch ( DAVException const & )
......
......@@ -55,6 +55,7 @@ private:
rtl::OUString m_aProxyName;
sal_Int32 m_nPort;
sal_Int32 m_nProxyPort;
::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aFlags;
HttpSession * m_pHttpSession;
void * m_pRequestData;
const ucbhelper::InternetProxyDecider & m_rProxyDecider;
......@@ -75,11 +76,13 @@ protected:
public:
NeonSession( const rtl::Reference< DAVSessionFactory > & rSessionFactory,
const rtl::OUString& inUri,
const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rFlags,
const ucbhelper::InternetProxyDecider & rProxyDecider )
throw ( DAVException );
// DAVSession methods
virtual sal_Bool CanUse( const ::rtl::OUString & inUri );
virtual sal_Bool CanUse( const ::rtl::OUString & inPath,
const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rFlags );
virtual sal_Bool UsesProxy();
......
......@@ -68,7 +68,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/TransferInfo.hpp>
......@@ -493,8 +493,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(
......@@ -505,6 +506,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 );
}
......@@ -1901,7 +1911,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 )
throw( uno::Exception )
{
......@@ -1985,6 +1995,7 @@ uno::Any Content::open(
new DAVResourceAccess( *m_xResAccess.get() ) );
}
xResAccess->setFlags( rArg.OpeningFlags );
DAVResource aResource;
std::vector< rtl::OUString > aHeaders;
......@@ -2031,6 +2042,8 @@ uno::Any Content::open(
new DAVResourceAccess( *m_xResAccess.get() ) );
}
xResAccess->setFlags( rArg.OpeningFlags );
// fill inputsream sync; return if all data present
DAVResource aResource;
std::vector< rtl::OUString > aHeaders;
......
......@@ -52,7 +52,7 @@ namespace com { namespace sun { namespace star { namespace sdbc {
} } } }
namespace com { namespace sun { namespace star { namespace ucb {
struct OpenCommandArgument2;
struct OpenCommandArgument3;
struct PostCommandArgument2;
struct TransferInfo;
} } } }
......@@ -148,7 +148,7 @@ private:
// Command "open"
com::sun::star::uno::Any open(
const com::sun::star::ucb::OpenCommandArgument2 & rArg,
const com::sun::star::ucb::OpenCommandArgument3 & rArg,
const com::sun::star::uno::Reference<
com::sun::star::ucb::XCommandEnvironment > & xEnv )
throw( ::com::sun::star::uno::Exception );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment