<commit_before>/*************************************************************************
 *
 *  $RCSfile: Sequence.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: vg $ $Date: 2003-06-12 10:33:29 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#define _COM_SUN_STAR_UNO_SEQUENCE_HXX_

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef _OSL_INTERLCK_H_
#include <osl/interlck.h>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_H_
#include <com/sun/star/uno/Sequence.h>
#endif
#ifndef _TYPELIB_TYPEDESCRIPTION_H_
#include <typelib/typedescription.h>
#endif
#ifndef _UNO_DATA_H_
#include <uno/data.h>
#endif
#ifndef _COM_SUN_STAR_UNO_GENFUNC_HXX_
#include <com/sun/star/uno/genfunc.hxx>
#endif

namespace com
{
namespace sun
{
namespace star
{
namespace uno
{
//__________________________________________________________________________________________________
template< class E >
typelib_TypeDescriptionReference * Sequence< E >::s_pType = 0;

//__________________________________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence() SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_construct(
        &_pSequence, rType.getTypeLibType(),
        0, 0, (uno_AcquireFunc)cpp_acquire );
}
//__________________________________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence( const Sequence< E > & rSeq ) SAL_THROW( () )
{
    ::osl_incrementInterlockedCount( &rSeq._pSequence->nRefCount );
    _pSequence = rSeq._pSequence;
}
//__________________________________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence( uno_Sequence * pSequence, __sal_NoAcquire ) SAL_THROW( () )
    : _pSequence( pSequence )
{
}
//__________________________________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence( const E * pElements, sal_Int32 len ) SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_construct(
        &_pSequence, rType.getTypeLibType(),
        const_cast< E * >( pElements ), len, (uno_AcquireFunc)cpp_acquire );
}
//__________________________________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence( sal_Int32 len ) SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_construct(
        &_pSequence, rType.getTypeLibType(),
        0, len, (uno_AcquireFunc)cpp_acquire );
}
//__________________________________________________________________________________________________
template< class E >
inline Sequence< E >::~Sequence() SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_destructData(
        this, rType.getTypeLibType(), (uno_ReleaseFunc)cpp_release );
}
//__________________________________________________________________________________________________
template< class E >
inline Sequence< E > & Sequence< E >::operator = ( const Sequence< E > & rSeq ) SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_assign(
        &_pSequence, rSeq._pSequence, rType.getTypeLibType(), (uno_ReleaseFunc)cpp_release );
    return *this;
}
//__________________________________________________________________________________________________
template< class E >
inline sal_Bool Sequence< E >::operator == ( const Sequence< E > & rSeq ) const SAL_THROW( () )
{
    if (_pSequence == rSeq._pSequence)
        return sal_True;
    const Type & rType = ::getCppuType( this );
    return ::uno_type_equalData(
        const_cast< Sequence< E > * >( this ), rType.getTypeLibType(),
        const_cast< Sequence< E > * >( &rSeq ), rType.getTypeLibType(),
        (uno_QueryInterfaceFunc)cpp_queryInterface, (uno_ReleaseFunc)cpp_release );
}
//__________________________________________________________________________________________________
template< class E >
inline sal_Bool Sequence< E >::operator != ( const Sequence< E > & rSeq ) const SAL_THROW( () )
{
    return (! operator == ( rSeq ));
}
//__________________________________________________________________________________________________
template< class E >
inline E * Sequence< E >::getArray() SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_reference2One(
        &_pSequence, rType.getTypeLibType(),
        (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release );
    return reinterpret_cast< E * >( _pSequence->elements );
}
//__________________________________________________________________________________________________
template< class E >
inline E & Sequence< E >::operator [] ( sal_Int32 nIndex ) SAL_THROW( () )
{
    OSL_ENSURE( nIndex >= 0 && nIndex < getLength(), "### illegal index of sequence!" );
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_reference2One(
        &_pSequence, rType.getTypeLibType(),
        (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release );
    return reinterpret_cast< E * >( _pSequence->elements )[ nIndex ];
}
//__________________________________________________________________________________________________
template< class E >
inline const E & Sequence< E >::operator [] ( sal_Int32 nIndex ) const SAL_THROW( () )
{
    OSL_ENSURE( nIndex >= 0 && nIndex < getLength(), "### illegal index of sequence!" );
    return reinterpret_cast< const E * >( _pSequence->elements )[ nIndex ];
}
//__________________________________________________________________________________________________
template< class E >
inline void Sequence< E >::realloc( sal_Int32 nSize ) SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_realloc(
        &_pSequence, rType.getTypeLibType(), nSize,
        (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release );
}

//--------------------------------------------------------------------------------------------------
inline ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL toUnoSequence(
    const ::rtl::ByteSequence & rByteSequence ) SAL_THROW( () )
{
    return ::com::sun::star::uno::Sequence< sal_Int8 >(
        * reinterpret_cast< const ::com::sun::star::uno::Sequence< sal_Int8 > * >( &rByteSequence ) );
}

}
}
}
}

// generic sequence template
template< class E >
inline const ::com::sun::star::uno::Type &
SAL_CALL getCppuType( const ::com::sun::star::uno::Sequence< E > * ) SAL_THROW( () )
{
    if (! ::com::sun::star::uno::Sequence< E >::s_pType)
    {
        const ::com::sun::star::uno::Type & rElementType = ::getCppuType(
            (typename ::com::sun::star::uno::Sequence< E >::ElementType const *)0 );
        ::typelib_static_sequence_type_init(
            & ::com::sun::star::uno::Sequence< E >::s_pType,
            rElementType.getTypeLibType() );
    }
    return * reinterpret_cast< const ::com::sun::star::uno::Type * >(
        & ::com::sun::star::uno::Sequence< E >::s_pType );
}

// generic sequence template for given element type (e.g. C++ arrays)
template< class E >
inline const ::com::sun::star::uno::Type &
SAL_CALL getCppuSequenceType( const ::com::sun::star::uno::Type & rElementType ) SAL_THROW( () )
{
    if (! ::com::sun::star::uno::Sequence< E >::s_pType)
    {
        ::typelib_static_sequence_type_init(
            & ::com::sun::star::uno::Sequence< E >::s_pType,
            rElementType.getTypeLibType() );
    }
    return * reinterpret_cast< const ::com::sun::star::uno::Type * >(
        & ::com::sun::star::uno::Sequence< E >::s_pType );
}

#if ((defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) || (defined(__GNUC__) && defined(__APPLE__)))
static typelib_TypeDescriptionReference * s_pType_com_sun_star_uno_Sequence_Char = 0;
#endif

// char sequence
inline const ::com::sun::star::uno::Type &
SAL_CALL getCharSequenceCppuType() SAL_THROW( () )
{
#if !( (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) || (defined(__GNUC__) && defined(__APPLE__)) )
    static typelib_TypeDescriptionReference * s_pType_com_sun_star_uno_Sequence_Char = 0;
#endif
    if (! s_pType_com_sun_star_uno_Sequence_Char)
    {
        const ::com::sun::star::uno::Type & rElementType = ::getCharCppuType();
        ::typelib_static_sequence_type_init(
            & s_pType_com_sun_star_uno_Sequence_Char,
            rElementType.getTypeLibType() );
    }
    return * reinterpret_cast< const ::com::sun::star::uno::Type * >(
        & s_pType_com_sun_star_uno_Sequence_Char );
}

#endif
<commit_msg>INTEGRATION: CWS cliuno01 (1.14.44); FILE MERGED 2003/09/01 16:51:29 dbo 1.14.44.5: #107130# less code 2003/08/11 10:42:01 dbo 1.14.44.4: using bad_alloc def ctor 2003/08/08 12:43:48 dbo 1.14.44.3: RESYNC: (1.14-1.15); FILE MERGED 2003/07/24 15:19:00 dbo 1.14.44.2: - sequence reallocation fix - more code cleanup - test code 2003/07/23 16:39:19 dbo 1.14.44.1: - fixing cppu core sequence routines returning 0 handle upon memory allocation failure - C++ Sequence<> throws ::std::bad_alloc upon memory allocation failure<commit_after>/*************************************************************************
 *
 *  $RCSfile: Sequence.hxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: obo $ $Date: 2003-09-04 10:51:45 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#define _COM_SUN_STAR_UNO_SEQUENCE_HXX_

#ifndef _OSL_DIAGNOSE_H_
#include "osl/diagnose.h"
#endif
#ifndef _OSL_INTERLCK_H_
#include "osl/interlck.h"
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_H_
#include "com/sun/star/uno/Sequence.h"
#endif
#ifndef _TYPELIB_TYPEDESCRIPTION_H_
#include "typelib/typedescription.h"
#endif
#ifndef _UNO_DATA_H_
#include "uno/data.h"
#endif
#ifndef _COM_SUN_STAR_UNO_GENFUNC_HXX_
#include "com/sun/star/uno/genfunc.hxx"
#endif

namespace com
{
namespace sun
{
namespace star
{
namespace uno
{

//______________________________________________________________________________
template< class E >
typelib_TypeDescriptionReference * Sequence< E >::s_pType = 0;

//______________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence() SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_construct(
        &_pSequence, rType.getTypeLibType(),
        0, 0, (uno_AcquireFunc)cpp_acquire );
    // no bad_alloc, because empty sequence is statically allocated in cppu
}

//______________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence( const Sequence< E > & rSeq ) SAL_THROW( () )
{
    ::osl_incrementInterlockedCount( &rSeq._pSequence->nRefCount );
    _pSequence = rSeq._pSequence;
}

//______________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence(
    uno_Sequence * pSequence, __sal_NoAcquire ) SAL_THROW( () )
        : _pSequence( pSequence )
{
}

//______________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence( const E * pElements, sal_Int32 len )
{
    const Type & rType = ::getCppuType( this );
    sal_Bool success = ::uno_type_sequence_construct(
        &_pSequence, rType.getTypeLibType(),
        const_cast< E * >( pElements ), len, (uno_AcquireFunc)cpp_acquire );
#if ! defined EXCEPTIONS_OFF
    if (! success)
        throw ::std::bad_alloc();
#endif
}

//______________________________________________________________________________
template< class E >
inline Sequence< E >::Sequence( sal_Int32 len )
{
    const Type & rType = ::getCppuType( this );
    sal_Bool success = ::uno_type_sequence_construct(
        &_pSequence, rType.getTypeLibType(),
        0, len, (uno_AcquireFunc)cpp_acquire );
#if ! defined EXCEPTIONS_OFF
    if (! success)
        throw ::std::bad_alloc();
#endif
}

//______________________________________________________________________________
template< class E >
inline Sequence< E >::~Sequence() SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_destructData(
        this, rType.getTypeLibType(), (uno_ReleaseFunc)cpp_release );
}

//______________________________________________________________________________
template< class E >
inline Sequence< E > & Sequence< E >::operator = ( const Sequence< E > & rSeq ) SAL_THROW( () )
{
    const Type & rType = ::getCppuType( this );
    ::uno_type_sequence_assign(
        &_pSequence, rSeq._pSequence, rType.getTypeLibType(), (uno_ReleaseFunc)cpp_release );
    return *this;
}

//______________________________________________________________________________
template< class E >
inline sal_Bool Sequence< E >::operator == ( const Sequence< E > & rSeq ) const
    SAL_THROW( () )
{
    if (_pSequence == rSeq._pSequence)
        return sal_True;
    const Type & rType = ::getCppuType( this );
    return ::uno_type_equalData(
        const_cast< Sequence< E > * >( this ), rType.getTypeLibType(),
        const_cast< Sequence< E > * >( &rSeq ), rType.getTypeLibType(),
        (uno_QueryInterfaceFunc)cpp_queryInterface,
        (uno_ReleaseFunc)cpp_release );
}

//______________________________________________________________________________
template< class E >
inline sal_Bool Sequence< E >::operator != ( const Sequence< E > & rSeq ) const
    SAL_THROW( () )
{
    return (! operator == ( rSeq ));
}

//______________________________________________________________________________
template< class E >
inline E * Sequence< E >::getArray()
{
    const Type & rType = ::getCppuType( this );
    sal_Bool success = ::uno_type_sequence_reference2One(
        &_pSequence, rType.getTypeLibType(),
        (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release );
#if ! defined EXCEPTIONS_OFF
    if (! success)
        throw ::std::bad_alloc();
#endif
    return reinterpret_cast< E * >( _pSequence->elements );
}

//______________________________________________________________________________
template< class E >
inline E & Sequence< E >::operator [] ( sal_Int32 nIndex )
{
    OSL_ENSURE(
        nIndex >= 0 && nIndex < getLength(),
        "### illegal index of sequence!" );
    return getArray()[ nIndex ];
}

//______________________________________________________________________________
template< class E >
inline const E & Sequence< E >::operator [] ( sal_Int32 nIndex ) const
    SAL_THROW( () )
{
    OSL_ENSURE(
        nIndex >= 0 && nIndex < getLength(),
        "### illegal index of sequence!" );
    return reinterpret_cast< const E * >( _pSequence->elements )[ nIndex ];
}

//______________________________________________________________________________
template< class E >
inline void Sequence< E >::realloc( sal_Int32 nSize )
{
    const Type & rType = ::getCppuType( this );
    sal_Bool success = ::uno_type_sequence_realloc(
        &_pSequence, rType.getTypeLibType(), nSize,
        (uno_AcquireFunc)cpp_acquire, (uno_ReleaseFunc)cpp_release );
#if ! defined EXCEPTIONS_OFF
    if (! success)
        throw ::std::bad_alloc();
#endif
}

//------------------------------------------------------------------------------
inline ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL toUnoSequence(
    const ::rtl::ByteSequence & rByteSequence ) SAL_THROW( () )
{
    return ::com::sun::star::uno::Sequence< sal_Int8 >(
        * reinterpret_cast< const ::com::sun::star::uno::Sequence< sal_Int8 > * >( &rByteSequence ) );
}

}
}
}
}

// generic sequence template
template< class E >
inline const ::com::sun::star::uno::Type &
SAL_CALL getCppuType( const ::com::sun::star::uno::Sequence< E > * )
    SAL_THROW( () )
{
    if (! ::com::sun::star::uno::Sequence< E >::s_pType)
    {
        const ::com::sun::star::uno::Type & rElementType = ::getCppuType(
            (typename ::com::sun::star::uno::Sequence< E >::ElementType const *)0 );
        ::typelib_static_sequence_type_init(
            & ::com::sun::star::uno::Sequence< E >::s_pType,
            rElementType.getTypeLibType() );
    }
    return * reinterpret_cast< const ::com::sun::star::uno::Type * >(
        & ::com::sun::star::uno::Sequence< E >::s_pType );
}

// generic sequence template for given element type (e.g. C++ arrays)
template< class E >
inline const ::com::sun::star::uno::Type &
SAL_CALL getCppuSequenceType( const ::com::sun::star::uno::Type & rElementType )
    SAL_THROW( () )
{
    if (! ::com::sun::star::uno::Sequence< E >::s_pType)
    {
        ::typelib_static_sequence_type_init(
            & ::com::sun::star::uno::Sequence< E >::s_pType,
            rElementType.getTypeLibType() );
    }
    return * reinterpret_cast< const ::com::sun::star::uno::Type * >(
        & ::com::sun::star::uno::Sequence< E >::s_pType );
}

#if ((defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) || \
     (defined(__GNUC__) && defined(__APPLE__)))
static typelib_TypeDescriptionReference * s_pType_com_sun_star_uno_Sequence_Char
= 0;
#endif

// char sequence
inline const ::com::sun::star::uno::Type &
SAL_CALL getCharSequenceCppuType() SAL_THROW( () )
{
#if !( (defined(__SUNPRO_CC) && (__SUNPRO_CC == 0x500)) || \
       (defined(__GNUC__) && defined(__APPLE__)) )
    static typelib_TypeDescriptionReference *
        s_pType_com_sun_star_uno_Sequence_Char = 0;
#endif
    if (! s_pType_com_sun_star_uno_Sequence_Char)
    {
        const ::com::sun::star::uno::Type & rElementType = ::getCharCppuType();
        ::typelib_static_sequence_type_init(
            & s_pType_com_sun_star_uno_Sequence_Char,
            rElementType.getTypeLibType() );
    }
    return * reinterpret_cast< const ::com::sun::star::uno::Type * >(
        & s_pType_com_sun_star_uno_Sequence_Char );
}

#endif
<|endoftext|>


<commit_before>/************************************************************************
 *
 *  $RCSfile: xmlimp.hxx,v $
 *
 *  $Revision: 1.29 $
 *
 *  last change: $Author: hr $ $Date: 2004-11-09 12:34:22 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLIMP_HXX
#define _XMLIMP_HXX

#include <sot/storage.hxx>

#ifndef _XMLOFF_XMLICTXT_HXX
#include <xmloff/xmlictxt.hxx>
#endif

#ifndef _XMLITMAP_HXX
#include "xmlitmap.hxx"
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include <xmloff/xmlimp.hxx>
#endif

class SwDoc;
class SwPaM;
class SvXMLUnitConverter;
class SvXMLTokenMap;
class SvXMLImportItemMapper;
class SfxItemSet;
class SwNodeIndex;
class XMLTextImportHelper;
class SvXMLGraphicHelper;
class SvXMLEmbeddedObjectHelper;

// define, how many steps ( = paragraphs ) the progress bar should advance
// for styles, autostyles and settings + meta
#define PROGRESS_BAR_STEP 20

class SwXMLImport: public SvXMLImport
{
    SwNodeIndex             *pSttNdIdx;

    SvXMLUnitConverter      *pTwipUnitConv;
    SvXMLImportItemMapper   *pTableItemMapper;// paragraph item import
    SvXMLTokenMap           *pDocElemTokenMap;
    SvXMLTokenMap           *pTableElemTokenMap;
    SvXMLTokenMap           *pTableCellAttrTokenMap;
    SvXMLGraphicHelper      *pGraphicResolver;
    SvXMLEmbeddedObjectHelper   *pEmbeddedResolver;

    SvXMLItemMapEntriesRef  xTableItemMap;
    SvXMLItemMapEntriesRef  xTableColItemMap;
    SvXMLItemMapEntriesRef  xTableRowItemMap;
    SvXMLItemMapEntriesRef  xTableCellItemMap;
    SvStorageRef            xPackage;

    sal_uInt16              nStyleFamilyMask;// Mask of styles to load
    sal_Bool                bLoadDoc : 1;   // Load doc or styles only
    sal_Bool                bInsert : 1;    // Insert mode. If styles are
                                            // loaded only sal_False means that
                                            // existing styles will be
                                            // overwritten.
    sal_Bool                bBlock : 1;     // Load text block
    sal_Bool                bAutoStylesValid : 1;
    sal_Bool                bShowProgress : 1;
    sal_Bool                bOrganizerMode : 1;
    sal_Bool                bPreserveRedlineMode;

    void                    _InitItemImport();
    void                    _FinitItemImport();
    void                    UpdateTxtCollConditions( SwDoc *pDoc );

    void         setTextInsertMode(
                     const ::com::sun::star::uno::Reference<
                        ::com::sun::star::text::XTextRange > & rInsertPos );
    void         setStyleInsertMode( sal_uInt16 nFamilies,
                                     sal_Bool bOverwrite );
    void         setBlockMode();
    void         setOrganizerMode();

protected:

    // This method is called after the namespace map has been updated, but
    // before a context for the current element has been pushed.
    virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix,
                  const ::rtl::OUString& rLocalName,
                  const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    virtual XMLTextImportHelper* CreateTextImport();

    virtual XMLShapeImportHelper* CreateShapeImport();

public:

    // #110680#
    SwXMLImport(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
        sal_uInt16 nImportFlags = IMPORT_ALL);

#ifdef XML_CORE_API
    // #110680#
    SwXMLImport(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
        SwDoc& rDoc,
        const SwPaM& rPaM,
        sal_Bool bLoadDoc,
        sal_Bool bInsertMode,
        sal_uInt16 nStyleFamMask,
        const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & rModel,
        const ::com::sun::star::uno::Reference< ::com::sun::star::document::XGraphicObjectResolver > &,
        SvStorage *pPkg );
#endif

    ~SwXMLImport() throw();

    // ::com::sun::star::xml::sax::XDocumentHandler
    virtual void SAL_CALL startDocument(void)
        throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException );
    virtual void SAL_CALL endDocument(void)
        throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException );

    // XUnoTunnel
    static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw();
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);

    // XInitialization
    virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XServiceInfo (override parent method)
    ::rtl::OUString SAL_CALL getImplementationName()
        throw( ::com::sun::star::uno::RuntimeException );

    void                    InsertStyles( sal_Bool bAuto );
    void                    FinishStyles();

    // namespace office
    SvXMLImportContext *CreateMetaContext( const ::rtl::OUString& rLocalName );
    SvXMLImportContext *CreateScriptContext( const ::rtl::OUString& rLocalName );
    SvXMLImportContext *CreateStylesContext(
                const ::rtl::OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                sal_Bool bAuto );
    SvXMLImportContext *CreateMasterStylesContext(
                const ::rtl::OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
    SvXMLImportContext *CreateFontDeclsContext(
            const ::rtl::OUString& rLocalName,
            const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
    SvXMLImportContext *CreateBodyContentContext( const ::rtl::OUString& rLocalName );
    sal_uInt16 GetStyleFamilyMask() const { return nStyleFamilyMask; }
    sal_Bool IsInsertMode() const { return bInsert; }
    sal_Bool IsStylesOnlyMode() const { return !bLoadDoc; }
    sal_Bool IsBlockMode() const { return bBlock; }
    sal_Bool IsOrganizerMode() const { return bOrganizerMode; }

    inline const SvXMLUnitConverter& GetTwipUnitConverter() const;
    inline const SvXMLImportItemMapper& GetTableItemMapper() const;
    SvXMLImportContext *CreateTableItemImportContext( sal_uInt16 nPrefix,
                const ::rtl::OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                sal_uInt16 nSubFamily, SfxItemSet& rItemSet );

    const SvXMLTokenMap& GetDocElemTokenMap();
    const SvXMLTokenMap& GetTableElemTokenMap();
    const SvXMLTokenMap& GetTableCellAttrTokenMap();

    sal_Bool FindAutomaticStyle( sal_uInt16 nFamily,
                             const ::rtl::OUString& rName,
                             const SfxItemSet **ppItemSet=0,
                             ::rtl::OUString *pParent=0 ) const;

    virtual void SetStatisticAttributes(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttribs);
    virtual void SetViewSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aViewProps);
    virtual void SetConfigurationSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aConfigProps);

    SvStorage *GetPackage() { return &xPackage; }

    void SetProgressValue( sal_Int32 nValue );
};

inline const SvXMLUnitConverter& SwXMLImport::GetTwipUnitConverter() const
{
    return *pTwipUnitConv;
}

inline const SvXMLImportItemMapper& SwXMLImport::GetTableItemMapper() const
{
    return *pTableItemMapper;
}

inline void SwXMLImport::SetProgressValue( sal_Int32 nValue )
{
    if ( bShowProgress )
        GetProgressBarHelper()->SetValue(nValue);
}

#endif  //  _XMLIMP_HXX
<commit_msg>INTEGRATION: CWS eforms2 (1.27.24); FILE MERGED 2004/10/11 15:10:18 dvo 1.27.24.2: RESYNC: (1.27-1.28); FILE MERGED 2004/08/02 15:36:01 dvo 1.27.24.1: #i31958# initialize XForms<commit_after>/************************************************************************
 *
 *  $RCSfile: xmlimp.hxx,v $
 *
 *  $Revision: 1.30 $
 *
 *  last change: $Author: obo $ $Date: 2004-11-16 10:25:05 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLIMP_HXX
#define _XMLIMP_HXX

#include <sot/storage.hxx>

#ifndef _XMLOFF_XMLICTXT_HXX
#include <xmloff/xmlictxt.hxx>
#endif

#ifndef _XMLITMAP_HXX
#include "xmlitmap.hxx"
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include <xmloff/xmlimp.hxx>
#endif

class SwDoc;
class SwPaM;
class SvXMLUnitConverter;
class SvXMLTokenMap;
class SvXMLImportItemMapper;
class SfxItemSet;
class SwNodeIndex;
class XMLTextImportHelper;
class SvXMLGraphicHelper;
class SvXMLEmbeddedObjectHelper;

// define, how many steps ( = paragraphs ) the progress bar should advance
// for styles, autostyles and settings + meta
#define PROGRESS_BAR_STEP 20

class SwXMLImport: public SvXMLImport
{
    SwNodeIndex             *pSttNdIdx;

    SvXMLUnitConverter      *pTwipUnitConv;
    SvXMLImportItemMapper   *pTableItemMapper;// paragraph item import
    SvXMLTokenMap           *pDocElemTokenMap;
    SvXMLTokenMap           *pTableElemTokenMap;
    SvXMLTokenMap           *pTableCellAttrTokenMap;
    SvXMLGraphicHelper      *pGraphicResolver;
    SvXMLEmbeddedObjectHelper   *pEmbeddedResolver;

    SvXMLItemMapEntriesRef  xTableItemMap;
    SvXMLItemMapEntriesRef  xTableColItemMap;
    SvXMLItemMapEntriesRef  xTableRowItemMap;
    SvXMLItemMapEntriesRef  xTableCellItemMap;
    SvStorageRef            xPackage;

    sal_uInt16              nStyleFamilyMask;// Mask of styles to load
    sal_Bool                bLoadDoc : 1;   // Load doc or styles only
    sal_Bool                bInsert : 1;    // Insert mode. If styles are
                                            // loaded only sal_False means that
                                            // existing styles will be
                                            // overwritten.
    sal_Bool                bBlock : 1;     // Load text block
    sal_Bool                bAutoStylesValid : 1;
    sal_Bool                bShowProgress : 1;
    sal_Bool                bOrganizerMode : 1;
    sal_Bool                bPreserveRedlineMode;

    void                    _InitItemImport();
    void                    _FinitItemImport();
    void                    UpdateTxtCollConditions( SwDoc *pDoc );

    void         setTextInsertMode(
                     const ::com::sun::star::uno::Reference<
                        ::com::sun::star::text::XTextRange > & rInsertPos );
    void         setStyleInsertMode( sal_uInt16 nFamilies,
                                     sal_Bool bOverwrite );
    void         setBlockMode();
    void         setOrganizerMode();

protected:

    // This method is called after the namespace map has been updated, but
    // before a context for the current element has been pushed.
    virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix,
                  const ::rtl::OUString& rLocalName,
                  const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    virtual XMLTextImportHelper* CreateTextImport();

    virtual XMLShapeImportHelper* CreateShapeImport();

public:

    // #110680#
    SwXMLImport(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
        sal_uInt16 nImportFlags = IMPORT_ALL);

#ifdef XML_CORE_API
    // #110680#
    SwXMLImport(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
        SwDoc& rDoc,
        const SwPaM& rPaM,
        sal_Bool bLoadDoc,
        sal_Bool bInsertMode,
        sal_uInt16 nStyleFamMask,
        const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & rModel,
        const ::com::sun::star::uno::Reference< ::com::sun::star::document::XGraphicObjectResolver > &,
        SvStorage *pPkg );
#endif

    ~SwXMLImport() throw();

    // ::com::sun::star::xml::sax::XDocumentHandler
    virtual void SAL_CALL startDocument(void)
        throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException );
    virtual void SAL_CALL endDocument(void)
        throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException );

    // XUnoTunnel
    static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw();
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);

    // XInitialization
    virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XServiceInfo (override parent method)
    ::rtl::OUString SAL_CALL getImplementationName()
        throw( ::com::sun::star::uno::RuntimeException );

    void                    InsertStyles( sal_Bool bAuto );
    void                    FinishStyles();

    // namespace office
    SvXMLImportContext *CreateMetaContext( const ::rtl::OUString& rLocalName );
    SvXMLImportContext *CreateScriptContext( const ::rtl::OUString& rLocalName );
    SvXMLImportContext *CreateStylesContext(
                const ::rtl::OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                sal_Bool bAuto );
    SvXMLImportContext *CreateMasterStylesContext(
                const ::rtl::OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
    SvXMLImportContext *CreateFontDeclsContext(
            const ::rtl::OUString& rLocalName,
            const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
    SvXMLImportContext *CreateBodyContentContext( const ::rtl::OUString& rLocalName );
    sal_uInt16 GetStyleFamilyMask() const { return nStyleFamilyMask; }
    sal_Bool IsInsertMode() const { return bInsert; }
    sal_Bool IsStylesOnlyMode() const { return !bLoadDoc; }
    sal_Bool IsBlockMode() const { return bBlock; }
    sal_Bool IsOrganizerMode() const { return bOrganizerMode; }

    inline const SvXMLUnitConverter& GetTwipUnitConverter() const;
    inline const SvXMLImportItemMapper& GetTableItemMapper() const;
    SvXMLImportContext *CreateTableItemImportContext( sal_uInt16 nPrefix,
                const ::rtl::OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                sal_uInt16 nSubFamily, SfxItemSet& rItemSet );

    const SvXMLTokenMap& GetDocElemTokenMap();
    const SvXMLTokenMap& GetTableElemTokenMap();
    const SvXMLTokenMap& GetTableCellAttrTokenMap();

    sal_Bool FindAutomaticStyle( sal_uInt16 nFamily,
                             const ::rtl::OUString& rName,
                             const SfxItemSet **ppItemSet=0,
                             ::rtl::OUString *pParent=0 ) const;

    virtual void SetStatisticAttributes(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttribs);
    virtual void SetViewSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aViewProps);
    virtual void SetConfigurationSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aConfigProps);

    SvStorage *GetPackage() { return &xPackage; }

    void SetProgressValue( sal_Int32 nValue );

    // initialize XForms
    virtual void initXForms();
};

inline const SvXMLUnitConverter& SwXMLImport::GetTwipUnitConverter() const
{
    return *pTwipUnitConv;
}

inline const SvXMLImportItemMapper& SwXMLImport::GetTableItemMapper() const
{
    return *pTableItemMapper;
}

inline void SwXMLImport::SetProgressValue( sal_Int32 nValue )
{
    if ( bShowProgress )
        GetProgressBarHelper()->SetValue(nValue);
}

#endif  //  _XMLIMP_HXX
<|endoftext|>


<commit_before><commit_msg>mask VAS FIR bits 33,35,37<commit_after><|endoftext|>


<commit_before><commit_msg>Re-submit Axone updates<commit_after><|endoftext|>


<commit_before>#pragma once

#include <eosio/chain/webassembly/eos-vm-oc/ipc_protocol.hpp>

#include <boost/asio/local/datagram_protocol.hpp>

#include <vector>

#include <sys/syscall.h>
#include <linux/memfd.h>

namespace eosio { namespace chain { namespace eosvmoc {

class wrapped_fd {
   public:
      wrapped_fd() : _inuse(false) {}
      wrapped_fd(int fd) : _inuse(true), _fd(fd) {}
      wrapped_fd(const wrapped_fd&) = delete;
      wrapped_fd& operator=(const wrapped_fd&) = delete;
      wrapped_fd(wrapped_fd&& other) : _inuse(other._inuse), _fd(other._fd) {other._inuse = false;}
      wrapped_fd& operator=(wrapped_fd&& other) {
         _inuse = other._inuse;
         _fd = other._fd;
         other._inuse = false;
         return *this;
      }

      operator int() const {
         FC_ASSERT(_inuse, "trying to get the value of a not-in-use wrappedfd");
         return _fd;
      }

      int release() {
         _inuse = false;
         return _fd;
      }

      ~wrapped_fd() {
         if(_inuse)
            close(_fd);
      }

   private:
      bool _inuse = false;;
      int _fd;
};

std::tuple<bool, eosvmoc_message, std::vector<wrapped_fd>> read_message_with_fds(boost::asio::local::datagram_protocol::socket& s);
std::tuple<bool, eosvmoc_message, std::vector<wrapped_fd>> read_message_with_fds(int fd);
bool write_message_with_fds(boost::asio::local::datagram_protocol::socket& s, const eosvmoc_message& message, const std::vector<wrapped_fd>& fds = std::vector<wrapped_fd>());
bool write_message_with_fds(int fd_to_send_to, const eosvmoc_message& message, const std::vector<wrapped_fd>& fds = std::vector<wrapped_fd>());

template<typename T>
wrapped_fd memfd_for_bytearray(const T& bytes) {
   int fd = syscall(SYS_memfd_create, "eosvmoc_code", MFD_CLOEXEC);
   FC_ASSERT(fd >= 0, "Failed to create memfd");
   FC_ASSERT(ftruncate(fd, bytes.size()) == 0, "failed to grow memfd");
   if(bytes.size()) {
      uint8_t* b = (uint8_t*)mmap(nullptr, bytes.size(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
      FC_ASSERT(b != MAP_FAILED, "failed to mmap memfd");
      memcpy(b, bytes.data(), bytes.size());
      munmap(b, bytes.size());
   }
   return wrapped_fd(fd);
}

std::vector<uint8_t> vector_for_memfd(const wrapped_fd& memfd);
}}}<commit_msg>fix potential leak in OC's wrapped_fd move assignment op<commit_after>#pragma once

#include <eosio/chain/webassembly/eos-vm-oc/ipc_protocol.hpp>

#include <boost/asio/local/datagram_protocol.hpp>

#include <vector>

#include <sys/syscall.h>
#include <linux/memfd.h>

namespace eosio { namespace chain { namespace eosvmoc {

class wrapped_fd {
   public:
      wrapped_fd() : _inuse(false) {}
      wrapped_fd(int fd) : _inuse(true), _fd(fd) {}
      wrapped_fd(const wrapped_fd&) = delete;
      wrapped_fd& operator=(const wrapped_fd&) = delete;
      wrapped_fd(wrapped_fd&& other) : _inuse(other._inuse), _fd(other._fd) {other._inuse = false;}
      wrapped_fd& operator=(wrapped_fd&& other) {
         if(_inuse)
            close(_fd);
         _inuse = other._inuse;
         _fd = other._fd;
         other._inuse = false;
         return *this;
      }

      operator int() const {
         FC_ASSERT(_inuse, "trying to get the value of a not-in-use wrappedfd");
         return _fd;
      }

      int release() {
         _inuse = false;
         return _fd;
      }

      ~wrapped_fd() {
         if(_inuse)
            close(_fd);
      }

   private:
      bool _inuse = false;;
      int _fd;
};

std::tuple<bool, eosvmoc_message, std::vector<wrapped_fd>> read_message_with_fds(boost::asio::local::datagram_protocol::socket& s);
std::tuple<bool, eosvmoc_message, std::vector<wrapped_fd>> read_message_with_fds(int fd);
bool write_message_with_fds(boost::asio::local::datagram_protocol::socket& s, const eosvmoc_message& message, const std::vector<wrapped_fd>& fds = std::vector<wrapped_fd>());
bool write_message_with_fds(int fd_to_send_to, const eosvmoc_message& message, const std::vector<wrapped_fd>& fds = std::vector<wrapped_fd>());

template<typename T>
wrapped_fd memfd_for_bytearray(const T& bytes) {
   int fd = syscall(SYS_memfd_create, "eosvmoc_code", MFD_CLOEXEC);
   FC_ASSERT(fd >= 0, "Failed to create memfd");
   FC_ASSERT(ftruncate(fd, bytes.size()) == 0, "failed to grow memfd");
   if(bytes.size()) {
      uint8_t* b = (uint8_t*)mmap(nullptr, bytes.size(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
      FC_ASSERT(b != MAP_FAILED, "failed to mmap memfd");
      memcpy(b, bytes.data(), bytes.size());
      munmap(b, bytes.size());
   }
   return wrapped_fd(fd);
}

std::vector<uint8_t> vector_for_memfd(const wrapped_fd& memfd);
}}}<|endoftext|>


<commit_before>/**
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */
#include "ProxyLogger.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

#include <folly/DynamicConverter.h>
#include <folly/io/async/EventBase.h>
#include <folly/json.h>

#include "mcrouter/_router.h"
#include "mcrouter/async.h"
#include "mcrouter/lib/fbi/asox_timer.h"
#include "mcrouter/lib/fbi/cpp/util.h"
#include "mcrouter/lib/fbi/debug.h"
#include "mcrouter/proxy.h"
#include "mcrouter/stats.h"

namespace facebook { namespace memcache { namespace mcrouter {

namespace {

const char* kStatsSfx = "stats";
const char* kStatsStartupOptionsSfx = "startup_options";
const char* kConfigSourcesInfoFileName = "config_sources_info";

void log_stats(const asox_timer_t timer, void* arg) {
  auto logger = reinterpret_cast<ProxyLogger*>(arg);
  logger->log();
}

bool ensure_dir_exists_and_writeable(const std::string& path) {
  boost::system::error_code ec;
  boost::filesystem::create_directories(path, ec);
  if (ec) {
    return false;
  }

  struct stat st;
  if (::stat(path.c_str(), &st) != 0) {
    return false;
  }

  if ((st.st_mode & 0777) == 0777) {
    return true;
  }

  if (::chmod(path.c_str(), 0777) != 0) {
    return false;
  }

  return true;
}

/** returns "<source_library>.<source_service>.<source_flavor>" */
inline std::string get_stats_key(const proxy_t* proxy) {
  return folly::format(
    "libmcrouter.{}.{}",
    proxy->opts.service_name,
    proxy->opts.router_name).str();
}

std::string proxy_stats_file_path(proxy_t* proxy, const std::string& suffix) {
  boost::filesystem::path path(proxy->opts.stats_root);
  path /= get_stats_key(proxy) + "." + suffix;
  return path.string();
}

/**
 * Writes string to a file.
 */
void proxy_write_file(proxy_t* proxy,
                      const std::string& suffix,
                      const std::string& str) {
  try {
    // In case the dir was deleted some time after mcrouter started
    if (!ensure_dir_exists_and_writeable(proxy->opts.stats_root)) {
      return;
    }

    auto path = proxy_stats_file_path(proxy, suffix);

    async_write_file(proxy->stats_log_writer.get(), path, str);
  } catch (...) {
    // Do nothing
  }
}

/**
 * Determines the correct location and file name and writes the stats object
 * to disk in json format. The suffix is the file extension. If the stats root
 * directory is ever removed or is unwriteable, we just give up.
 */
void proxy_write_stats_file(proxy_t* proxy,
                            const std::string& suffix,
                            const folly::dynamic& stats) {
  auto statsString = folly::toPrettyJson(stats).toStdString() + "\n";
  proxy_write_file(proxy, suffix, statsString);
}

void write_stats_to_disk(proxy_t* proxy, const std::vector<stat_t>& stats) {
  try {
    std::string prefix = get_stats_key(proxy) + ".";
    folly::dynamic jstats = folly::dynamic::object;

    for (size_t i = 0; i < stats.size(); ++i) {
      if (stats[i].group & ods_stats) {
        auto key = prefix + stats[i].name.str();

        switch (stats[i].type) {
          case stat_uint64:
            jstats[key] = stats[i].data.uint64;
            break;

          case stat_int64:
            jstats[key] = stats[i].data.int64;
            break;

          case stat_double:
            jstats[key] = stats[i].data.dbl;
            break;

          default:
            continue;
        }
      }
    }

    proxy_write_stats_file(proxy, kStatsSfx, jstats);
  } catch (...) {
    // Do nothing
  }
}

void write_config_sources_info_to_disk(const proxy_t* proxy) {
  auto config_info_json = proxy->router->configApi->getConfigSourcesInfo();

  try {
    boost::filesystem::path path(proxy->opts.stats_root);
    path /= get_stats_key(proxy) + "." + kConfigSourcesInfoFileName;
    async_write_file(proxy->stats_log_writer.get(), path.string(),
                     folly::toPrettyJson(config_info_json).toStdString());
  } catch (...) {
    LOG(ERROR) << "Error occured while writing configuration info to disk";
  }
}

}  // anonymous namespace

ProxyLogger::ProxyLogger(proxy_t* proxy,
  std::unique_ptr<AdditionalLoggerIf> additionalLogger)
    : proxy_(proxy),
      additionalLogger_(std::move(additionalLogger)) {

  if (!ensure_dir_exists_and_writeable(proxy_->opts.stats_root)) {
    LOG(ERROR) << "Can't create or chmod " << proxy_->opts.stats_root <<
                  ", disabling stats logging";
  } else {
    auto json_options = folly::toDynamic(proxy_->router->getStartupOpts());
    json_options["pid"] = folly::to<string>(getpid());
    proxy_write_stats_file(proxy_, kStatsStartupOptionsSfx, json_options);
    auto path = proxy_stats_file_path(proxy_, kStatsStartupOptionsSfx);
    touchStatsFilepaths_.push_back(std::move(path));

    timeval_t delay = to<timeval_t>(proxy_->opts.stats_logging_interval);
    statsLoggingTimer_ = asox_add_timer(proxy_->eventBase->getLibeventBase(),
                                        delay, log_stats, this);
  }
}

ProxyLogger::~ProxyLogger() {
  if (statsLoggingTimer_ != nullptr) {
    asox_remove_timer(statsLoggingTimer_);
  }
}

void ProxyLogger::log() {
  std::vector<stat_t> stats(num_stats);
  try {
    proxy_->router->startupLock.wait();
    std::lock_guard<ShutdownLock> lg(proxy_->router->shutdownLock());
    std::lock_guard<std::mutex> guard(proxy_->stats_lock);

    prepare_stats(proxy_, stats.data());
  } catch (const shutdown_started_exception& e) {
    return;
  }

  for (int i = 0; i < num_stats; ++i) {
    if (stats[i].group & rate_stats) {
      stats[i].type = stat_double;
      stats[i].data.dbl = stats_rate_value(proxy_, i);
    }
  }

  write_stats_to_disk(proxy_, stats);
  write_config_sources_info_to_disk(proxy_);

  for (const auto& filepath : touchStatsFilepaths_) {
    touchFile(filepath);
  }

  if (additionalLogger_) {
    additionalLogger_->log(stats);
  }
}

}}}  // facebook::memcache::mcrouter
<commit_msg>Fix OSS build<commit_after>/**
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */
#include "ProxyLogger.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

#include <folly/DynamicConverter.h>
#include <folly/io/async/EventBase.h>
#include <folly/json.h>

#include "mcrouter/_router.h"
#include "mcrouter/async.h"
#include "mcrouter/lib/fbi/asox_timer.h"
#include "mcrouter/lib/fbi/cpp/util.h"
#include "mcrouter/lib/fbi/debug.h"
#include "mcrouter/proxy.h"
#include "mcrouter/stats.h"

namespace facebook { namespace memcache { namespace mcrouter {

namespace {

const char* kStatsSfx = "stats";
const char* kStatsStartupOptionsSfx = "startup_options";
const char* kConfigSourcesInfoFileName = "config_sources_info";

void log_stats(const asox_timer_t timer, void* arg) {
  auto logger = reinterpret_cast<ProxyLogger*>(arg);
  logger->log();
}

bool ensure_dir_exists_and_writeable(const std::string& path) {
  boost::system::error_code ec;
  boost::filesystem::create_directories(path, ec);
  if (ec) {
    return false;
  }

  struct stat st;
  if (::stat(path.c_str(), &st) != 0) {
    return false;
  }

  if ((st.st_mode & 0777) == 0777) {
    return true;
  }

  if (::chmod(path.c_str(), 0777) != 0) {
    return false;
  }

  return true;
}

/** returns "<source_library>.<source_service>.<source_flavor>" */
inline std::string get_stats_key(const proxy_t* proxy) {
  return folly::format(
    "libmcrouter.{}.{}",
    proxy->opts.service_name,
    proxy->opts.router_name).str();
}

std::string proxy_stats_file_path(proxy_t* proxy, const std::string& suffix) {
  boost::filesystem::path path(proxy->opts.stats_root);
  path /= get_stats_key(proxy) + "." + suffix;
  return path.string();
}

/**
 * Writes string to a file.
 */
void proxy_write_file(proxy_t* proxy,
                      const std::string& suffix,
                      const std::string& str) {
  try {
    // In case the dir was deleted some time after mcrouter started
    if (!ensure_dir_exists_and_writeable(proxy->opts.stats_root)) {
      return;
    }

    auto path = proxy_stats_file_path(proxy, suffix);

    async_write_file(proxy->stats_log_writer.get(), path, str);
  } catch (...) {
    // Do nothing
  }
}

/**
 * Determines the correct location and file name and writes the stats object
 * to disk in json format. The suffix is the file extension. If the stats root
 * directory is ever removed or is unwriteable, we just give up.
 */
void proxy_write_stats_file(proxy_t* proxy,
                            const std::string& suffix,
                            const folly::dynamic& stats) {
  auto statsString = folly::toPrettyJson(stats).toStdString() + "\n";
  proxy_write_file(proxy, suffix, statsString);
}

void write_stats_to_disk(proxy_t* proxy, const std::vector<stat_t>& stats) {
  try {
    std::string prefix = get_stats_key(proxy) + ".";
    folly::dynamic jstats = folly::dynamic::object;

    for (size_t i = 0; i < stats.size(); ++i) {
      if (stats[i].group & ods_stats) {
        auto key = prefix + stats[i].name.str();

        switch (stats[i].type) {
          case stat_uint64:
            jstats[key] = stats[i].data.uint64;
            break;

          case stat_int64:
            jstats[key] = stats[i].data.int64;
            break;

          case stat_double:
            jstats[key] = stats[i].data.dbl;
            break;

          default:
            continue;
        }
      }
    }

    proxy_write_stats_file(proxy, kStatsSfx, jstats);
  } catch (...) {
    // Do nothing
  }
}

void write_config_sources_info_to_disk(const proxy_t* proxy) {
  auto config_info_json = proxy->router->configApi->getConfigSourcesInfo();

  try {
    boost::filesystem::path path(proxy->opts.stats_root);
    path /= get_stats_key(proxy) + "." + kConfigSourcesInfoFileName;
    async_write_file(proxy->stats_log_writer.get(), path.string(),
                     folly::toPrettyJson(config_info_json).toStdString());
  } catch (...) {
    LOG(ERROR) << "Error occured while writing configuration info to disk";
  }
}

}  // anonymous namespace

ProxyLogger::ProxyLogger(proxy_t* proxy,
  std::unique_ptr<AdditionalLoggerIf> additionalLogger)
    : proxy_(proxy),
      additionalLogger_(std::move(additionalLogger)) {

  if (!ensure_dir_exists_and_writeable(proxy_->opts.stats_root)) {
    LOG(ERROR) << "Can't create or chmod " << proxy_->opts.stats_root <<
                  ", disabling stats logging";
  } else {
    auto json_options = folly::toDynamic(proxy_->router->getStartupOpts());
    json_options["pid"] = folly::to<std::string>(getpid());
    proxy_write_stats_file(proxy_, kStatsStartupOptionsSfx, json_options);
    auto path = proxy_stats_file_path(proxy_, kStatsStartupOptionsSfx);
    touchStatsFilepaths_.push_back(std::move(path));

    timeval_t delay = to<timeval_t>(proxy_->opts.stats_logging_interval);
    statsLoggingTimer_ = asox_add_timer(proxy_->eventBase->getLibeventBase(),
                                        delay, log_stats, this);
  }
}

ProxyLogger::~ProxyLogger() {
  if (statsLoggingTimer_ != nullptr) {
    asox_remove_timer(statsLoggingTimer_);
  }
}

void ProxyLogger::log() {
  std::vector<stat_t> stats(num_stats);
  try {
    proxy_->router->startupLock.wait();
    std::lock_guard<ShutdownLock> lg(proxy_->router->shutdownLock());
    std::lock_guard<std::mutex> guard(proxy_->stats_lock);

    prepare_stats(proxy_, stats.data());
  } catch (const shutdown_started_exception& e) {
    return;
  }

  for (int i = 0; i < num_stats; ++i) {
    if (stats[i].group & rate_stats) {
      stats[i].type = stat_double;
      stats[i].data.dbl = stats_rate_value(proxy_, i);
    }
  }

  write_stats_to_disk(proxy_, stats);
  write_config_sources_info_to_disk(proxy_);

  for (const auto& filepath : touchStatsFilepaths_) {
    touchFile(filepath);
  }

  if (additionalLogger_) {
    additionalLogger_->log(stats);
  }
}

}}}  // facebook::memcache::mcrouter
<|endoftext|>


<commit_before>// Copyright (c) 2015-2017 William W. Fisher (at gmail dot com)
// This file is distributed under the MIT License.

#include "ofp/sys/engine.h"
#include "ofp/log.h"
#include "ofp/sys/tcp_connection.h"
#include "ofp/sys/tcp_server.h"
#include "ofp/sys/udp_server.h"

using namespace ofp;
using namespace ofp::sys;

Engine::Engine(Driver *driver)
    : driver_{driver}, signals_{io_}, stopTimer_{io_}, idleTimer_{io_} {
  log_debug("Engine ready");
}

Engine::~Engine() {
  // Shutdown all existing connections and servers.
  (void)close(0);
  log_debug("Engine shutting down");
}

UInt64 Engine::listen(ChannelOptions options, UInt64 securityId,
                      const IPv6Endpoint &localEndpoint,
                      ProtocolVersions versions,
                      ChannelListener::Factory listenerFactory,
                      std::error_code &error) {
  // Verify the channel options.
  if (!AreChannelOptionsValid(options)) {
    error = std::make_error_code(std::errc::invalid_argument);
    return 0;
  }

  auto svrPtr = TCP_Server::create(this, options, securityId, localEndpoint,
                                   versions, listenerFactory, error);
  if (error)
    return 0;

  // If there's no error, the TCP_Server has registered itself with the engine.
  UInt64 connId = svrPtr->connectionId();
  assert(connId > 0);

  return connId;
}

UInt64 Engine::connect(
    ChannelOptions options, UInt64 securityId,
    const IPv6Endpoint &remoteEndpoint, ProtocolVersions versions,
    ChannelListener::Factory listenerFactory,
    std::function<void(Channel *, std::error_code)> resultHandler) {
  // Verify the channel options.
  if (!AreChannelOptionsValid(options)) {
    resultHandler(nullptr, std::make_error_code(std::errc::invalid_argument));
    return 0;
  }

  UInt64 connId = 0;

  // Check for CONNECT_UDP option.
  if ((options & ChannelOptions::CONNECT_UDP) != 0) {
    std::error_code error;
    connId = connectUDP(securityId, remoteEndpoint, listenerFactory, error);
    resultHandler(nullptr, error);
    return connId;
  }

  if (securityId != 0) {
    connId = TCP_AsyncConnect<EncryptedSocket>(this, options, securityId,
                                               versions, listenerFactory,
                                               remoteEndpoint, resultHandler);

  } else {
    connId = TCP_AsyncConnect<PlaintextSocket>(this, options, securityId,
                                               versions, listenerFactory,
                                               remoteEndpoint, resultHandler);
  }

  return connId;
}

UInt64 Engine::connectUDP(UInt64 securityId, const IPv6Endpoint &remoteEndpoint,
                          ChannelListener::Factory listenerFactory,
                          std::error_code &error) {
  UInt64 connId = 0;

  if (!udpConnect_) {
    udpConnect_ = UDP_Server::create(this, error);
    if (error) {
      udpConnect_.reset();
    }
  }

  if (udpConnect_) {
    connId = udpConnect_->connect(remoteEndpoint, securityId, listenerFactory,
                                  error);
  }

  return connId;
}

size_t Engine::close(UInt64 connId) {
  if (connId != 0) {
    // Close a specific server or connection.
    TCP_Server *server = findTCPServer(
        [connId](TCP_Server *svr) { return svr->connectionId() == connId; });

    if (server) {
      server->shutdown();
      return 1;
    }

    Connection *conn = findConnId(connId);
    if (conn) {
      conn->shutdown();
      if (conn->flags() & Connection::kManualDelete) {
        delete conn;
      }
      return 1;
    }

    return 0;
  }

  // Close all servers and connections.
  size_t result = serverList_.size() + connList_.size() + (udpConnect_ ? 1 : 0);
  if (result == 0)
    return result;

  log_info("Close all servers and connections");

  std::vector<TCP_Server *> servers;
  servers.swap(serverList_);
  for (auto svr : servers) {
    svr->shutdown();
  }

  std::vector<Connection *> conns;
  conns.swap(connList_);
  for (auto conn : conns) {
    conn->shutdown();
    if (conn->flags() & Connection::kManualDelete) {
      delete conn;
    }
  }

  if (udpConnect_) {
    udpConnect_->shutdown();
    udpConnect_.reset();
  }

  return result;
}

#if LIBOFP_ENABLE_OPENSSL

UInt64 Engine::addIdentity(const std::string &certData,
                           const std::string &keyPassphrase,
                           const std::string &verifier,
                           std::error_code &error) {
  auto idPtr =
      MakeUniquePtr<Identity>(certData, keyPassphrase, verifier, error);
  if (error)
    return 0;

  UInt64 secId = assignSecurityId();
  assert(secId > 0);
  idPtr->setSecurityId(secId);

  log_info("Add TLS identity:", idPtr->subjectName(),
           std::make_pair("tlsid", secId));

  identities_.push_back(std::move(idPtr));

  return secId;
}

Identity *Engine::findIdentity(UInt64 securityId) {
  if (securityId == 0) {
    return nullptr;
  }

  auto iter = std::find_if(identities_.begin(), identities_.end(),
                           [securityId](std::unique_ptr<Identity> &identity) {
                             return identity->securityId() == securityId;
                           });

  return iter != identities_.end() ? iter->get() : nullptr;
}

UInt64 Engine::assignSecurityId() {
  if (++lastSecurityId_ == 0) {
    static_assert(sizeof(lastSecurityId_) == 8, "Expected 64-bit integer");
    log::fatal("Engine::assignSecurityId: Ran out of 64-bit securityIds");
  }
  return lastSecurityId_;
}

#endif  // LIBOFP_ENABLE_OPENSSL

void Engine::run() {
  if (!isRunning_) {
    isRunning_ = true;

    // Set isRunning_ to true when we are in io.run(). This guards against
    // re-entry and provides a flag to test when shutting down.

    asyncIdle();

    io_.run();

    idleTimer_.cancel();

    isRunning_ = false;
  }
}

void Engine::stop(Milliseconds timeout) {
  if (timeout == 0_ms) {
    io_.stop();
  } else {
    asio::error_code error;
    stopTimer_.expires_after(timeout, error);
    if (error) {
      io_.stop();
      return;
    }

    stopTimer_.async_wait([this](const asio::error_code &err) {
      if (err != asio::error::operation_aborted) {
        io_.stop();
      }
    });
  }
}

bool Engine::registerDatapath(Connection *channel) {
  DatapathID dpid = channel->datapathId();
  UInt8 auxID = channel->auxiliaryId();

  if (auxID == 0) {
    assert(!IsChannelTransportUDP(channel->transport()));

    // Insert main connection's datapathID into the dpidMap, if not present
    // already.
    auto pair = dpidMap_.insert({dpid, channel});
    if (!pair.second) {
      // DatapathID already exists in map. If the existing channel is
      // different, close it and replace it with the new one.
      auto item = pair.first;
      if (item->second != channel) {
        log_error("Datapath conflict between main connections detected:", dpid,
                  std::make_pair("prev_conn_id", item->second->connectionId()),
                  std::make_pair("conn_id", channel->connectionId()));
        Connection *old = item->second;
        item->second = channel;
        old->shutdown(true);  // force immediate reset

      } else {
        log_warning("Datapath is already registered:", dpid,
                    std::make_pair("conn_id", channel->connectionId()));
      }
    }

  } else {
    assert(auxID != 0);

    // Look up main connection and assign auxiliary connection to it. If we
    // don't find a main connection, close the auxiliary channel.
    auto item = dpidMap_.find(dpid);
    if (item != dpidMap_.end()) {
      Connection *parent = item->second;
      if (parent->flags() & Connection::kPermitsAuxiliary) {
        channel->setMainConnection(parent, auxID);
      } else {
        log_warning(
            "registerDatapath: Auxiliary connection not permitted for datapath",
            dpid, "aux", static_cast<int>(auxID),
            std::make_pair("conn_id", channel->connectionId()));
        return false;
      }

    } else {
      log_warning("registerDatapath: Main connection not found for datapath",
                  dpid, "aux", static_cast<int>(auxID),
                  std::make_pair("conn_id", channel->connectionId()));
      return false;
    }
  }

  return true;
}

void Engine::releaseDatapath(Connection *channel) {
  DatapathID dpid = channel->datapathId();
  UInt8 auxID = channel->auxiliaryId();

  // We only need to release the datapath for main connections.
  if (auxID == 0) {
    // When releasing the datapathID for a main connection, we need to
    // verify that the datapathID _is_ registered to this connection.
    auto item = dpidMap_.find(dpid);
    if (item != dpidMap_.end()) {
      if (item->second == channel)
        dpidMap_.erase(item);
    }
  }
}

UInt64 Engine::registerServer(TCP_Server *server) {
  assert(!serverListLock_);
  serverList_.push_back(server);
  return assignConnectionId();
}

void Engine::releaseServer(TCP_Server *server) {
  assert(!serverListLock_);
  auto iter = std::find(serverList_.begin(), serverList_.end(), server);
  if (iter != serverList_.end()) {
    assert(*iter == server);
    serverList_.erase(iter);
  }
}

UInt64 Engine::registerConnection(Connection *connection) {
  assert(!connListLock_);
  connList_.push_back(connection);
  return assignConnectionId();
}

void Engine::releaseConnection(Connection *connection) {
  assert(!connListLock_);
  auto iter = findConnIter(connection->connectionId());
  if (iter != connList_.end()) {
    assert(*iter == connection);
    connList_.erase(iter);
  }
}

void Engine::installSignalHandlers(std::function<void()> callback) {
  log_debug("Install signal handlers");

  std::error_code ignore;
  signals_.cancel(ignore);
  signals_.clear(ignore);
  signals_.add(SIGINT);
  signals_.add(SIGTERM);

  OFP_BEGIN_IGNORE_PADDING

  signals_.async_wait(
      [this, callback](const asio::error_code &error, int signum) {
        if (!error) {
          const char *signame = (signum == SIGTERM)
                                    ? "SIGTERM"
                                    : (signum == SIGINT) ? "SIGINT" : "???";
          log_info("Signal received:", signame);

          signals_.cancel();
          idleTimer_.cancel();
          (void)this->close(0);

          if (callback)
            callback();

        } else {
          log_error("Signal error", signum, error);
        }
      });

  OFP_END_IGNORE_PADDING
}

UInt64 Engine::assignConnectionId() {
  if (++lastConnId_ == 0) {
    static_assert(sizeof(lastConnId_) == 8, "Expected 64-bit integer");
    log::fatal("Engine::assignConnectionId: Ran out of 64-bit connectionIds");
  }
  return lastConnId_;
}

Connection *Engine::findDatapath(UInt64 connId, const DatapathID &dpid) const {
  // Use the connectionId, it it's non-zero.
  if (connId != 0) {
    return findConnId(connId);
  }

  // If datapath ID is not all zeros, use it to look up the connection.
  if (!dpid.empty()) {
    auto item = dpidMap_.find(dpid);
    if (item != dpidMap_.end()) {
      return item->second;
    }
    return nullptr;
  }

  assert(dpid.empty() && connId == 0);

  return nullptr;
}

Connection *Engine::findConnId(UInt64 connId) const {
  auto iter = findConnIter(connId);
  if (iter != connList_.end()) {
    return *iter;
  }
  return nullptr;
}

std::vector<Connection *>::const_iterator Engine::findConnIter(
    UInt64 connId) const {
  assert(connId != 0);

  // Use binary search to locate connection with connID.
  auto iter = std::lower_bound(
      connList_.begin(), connList_.end(), connId,
      [](Connection *conn, UInt64 cid) { return conn->connectionId() < cid; });

  if (iter != connList_.end()) {
    Connection *conn = *iter;
    if (conn->connectionId() == connId)
      return iter;
  }

  return connList_.end();
}

void Engine::asyncIdle() {
  asio::error_code error;

  idleTimer_.expires_after(1000_ms, error);
  idleTimer_.async_wait([this](const asio::error_code &err) {
    if (!err) {
      TimePoint now = TimeClock::now();
      forEachConnection([this, &now](Connection *conn) {
        if (conn->flags() & Connection::kConnectionUp) {
          conn->tickle(now);
        }
      });
      asyncIdle();
    }
  });
}

void Engine::setAlertCallback(AlertCallback callback, void *context) {
  alertCallback_ = callback;
  alertContext_ = context;
}

void Engine::alert(Channel *conn, const std::string &alert,
                   const ByteRange &data) {
  if (alertCallback_) {
    alertCallback_(conn, alert, data, alertContext_);
  }
}
<commit_msg>GCC 4.8 C++ doesn't support c++11 fully.<commit_after>// Copyright (c) 2015-2017 William W. Fisher (at gmail dot com)
// This file is distributed under the MIT License.

#include "ofp/sys/engine.h"
#include "ofp/log.h"
#include "ofp/sys/tcp_connection.h"
#include "ofp/sys/tcp_server.h"
#include "ofp/sys/udp_server.h"

using namespace ofp;
using namespace ofp::sys;

Engine::Engine(Driver *driver)
    : driver_{driver}, signals_{io_}, stopTimer_{io_}, idleTimer_{io_} {
  log_debug("Engine ready");
}

Engine::~Engine() {
  // Shutdown all existing connections and servers.
  (void)close(0);
  log_debug("Engine shutting down");
}

UInt64 Engine::listen(ChannelOptions options, UInt64 securityId,
                      const IPv6Endpoint &localEndpoint,
                      ProtocolVersions versions,
                      ChannelListener::Factory listenerFactory,
                      std::error_code &error) {
  // Verify the channel options.
  if (!AreChannelOptionsValid(options)) {
    error = std::make_error_code(std::errc::invalid_argument);
    return 0;
  }

  auto svrPtr = TCP_Server::create(this, options, securityId, localEndpoint,
                                   versions, listenerFactory, error);
  if (error)
    return 0;

  // If there's no error, the TCP_Server has registered itself with the engine.
  UInt64 connId = svrPtr->connectionId();
  assert(connId > 0);

  return connId;
}

UInt64 Engine::connect(
    ChannelOptions options, UInt64 securityId,
    const IPv6Endpoint &remoteEndpoint, ProtocolVersions versions,
    ChannelListener::Factory listenerFactory,
    std::function<void(Channel *, std::error_code)> resultHandler) {
  // Verify the channel options.
  if (!AreChannelOptionsValid(options)) {
    resultHandler(nullptr, std::make_error_code(std::errc::invalid_argument));
    return 0;
  }

  UInt64 connId = 0;

  // Check for CONNECT_UDP option.
  if ((options & ChannelOptions::CONNECT_UDP) != 0) {
    std::error_code error;
    connId = connectUDP(securityId, remoteEndpoint, listenerFactory, error);
    resultHandler(nullptr, error);
    return connId;
  }

  if (securityId != 0) {
    connId = TCP_AsyncConnect<EncryptedSocket>(this, options, securityId,
                                               versions, listenerFactory,
                                               remoteEndpoint, resultHandler);

  } else {
    connId = TCP_AsyncConnect<PlaintextSocket>(this, options, securityId,
                                               versions, listenerFactory,
                                               remoteEndpoint, resultHandler);
  }

  return connId;
}

UInt64 Engine::connectUDP(UInt64 securityId, const IPv6Endpoint &remoteEndpoint,
                          ChannelListener::Factory listenerFactory,
                          std::error_code &error) {
  UInt64 connId = 0;

  if (!udpConnect_) {
    udpConnect_ = UDP_Server::create(this, error);
    if (error) {
      udpConnect_.reset();
    }
  }

  if (udpConnect_) {
    connId = udpConnect_->connect(remoteEndpoint, securityId, listenerFactory,
                                  error);
  }

  return connId;
}

size_t Engine::close(UInt64 connId) {
  if (connId != 0) {
    // Close a specific server or connection.
    TCP_Server *server = findTCPServer(
        [connId](TCP_Server *svr) { return svr->connectionId() == connId; });

    if (server) {
      server->shutdown();
      return 1;
    }

    Connection *conn = findConnId(connId);
    if (conn) {
      conn->shutdown();
      if (conn->flags() & Connection::kManualDelete) {
        delete conn;
      }
      return 1;
    }

    return 0;
  }

  // Close all servers and connections.
  size_t result = serverList_.size() + connList_.size() + (udpConnect_ ? 1 : 0);
  if (result == 0)
    return result;

  log_info("Close all servers and connections");

  std::vector<TCP_Server *> servers;
  servers.swap(serverList_);
  for (auto svr : servers) {
    svr->shutdown();
  }

  std::vector<Connection *> conns;
  conns.swap(connList_);
  for (auto conn : conns) {
    conn->shutdown();
    if (conn->flags() & Connection::kManualDelete) {
      delete conn;
    }
  }

  if (udpConnect_) {
    udpConnect_->shutdown();
    udpConnect_.reset();
  }

  return result;
}

#if LIBOFP_ENABLE_OPENSSL

UInt64 Engine::addIdentity(const std::string &certData,
                           const std::string &keyPassphrase,
                           const std::string &verifier,
                           std::error_code &error) {
  auto idPtr =
      MakeUniquePtr<Identity>(certData, keyPassphrase, verifier, error);
  if (error)
    return 0;

  UInt64 secId = assignSecurityId();
  assert(secId > 0);
  idPtr->setSecurityId(secId);

  log_info("Add TLS identity:", idPtr->subjectName(),
           std::make_pair("tlsid", secId));

  identities_.push_back(std::move(idPtr));

  return secId;
}

Identity *Engine::findIdentity(UInt64 securityId) {
  if (securityId == 0) {
    return nullptr;
  }

  auto iter = std::find_if(identities_.begin(), identities_.end(),
                           [securityId](std::unique_ptr<Identity> &identity) {
                             return identity->securityId() == securityId;
                           });

  return iter != identities_.end() ? iter->get() : nullptr;
}

UInt64 Engine::assignSecurityId() {
  if (++lastSecurityId_ == 0) {
    static_assert(sizeof(lastSecurityId_) == 8, "Expected 64-bit integer");
    log::fatal("Engine::assignSecurityId: Ran out of 64-bit securityIds");
  }
  return lastSecurityId_;
}

#endif  // LIBOFP_ENABLE_OPENSSL

void Engine::run() {
  if (!isRunning_) {
    isRunning_ = true;

    // Set isRunning_ to true when we are in io.run(). This guards against
    // re-entry and provides a flag to test when shutting down.

    asyncIdle();

    io_.run();

    idleTimer_.cancel();

    isRunning_ = false;
  }
}

void Engine::stop(Milliseconds timeout) {
  if (timeout == 0_ms) {
    io_.stop();
  } else {
    asio::error_code error;
    stopTimer_.expires_after(timeout, error);
    if (error) {
      io_.stop();
      return;
    }

    stopTimer_.async_wait([this](const asio::error_code &err) {
      if (err != asio::error::operation_aborted) {
        io_.stop();
      }
    });
  }
}

bool Engine::registerDatapath(Connection *channel) {
  DatapathID dpid = channel->datapathId();
  UInt8 auxID = channel->auxiliaryId();

  if (auxID == 0) {
    assert(!IsChannelTransportUDP(channel->transport()));

    // Insert main connection's datapathID into the dpidMap, if not present
    // already.
    auto pair = dpidMap_.insert({dpid, channel});
    if (!pair.second) {
      // DatapathID already exists in map. If the existing channel is
      // different, close it and replace it with the new one.
      auto item = pair.first;
      if (item->second != channel) {
        log_error("Datapath conflict between main connections detected:", dpid,
                  std::make_pair("prev_conn_id", item->second->connectionId()),
                  std::make_pair("conn_id", channel->connectionId()));
        Connection *old = item->second;
        item->second = channel;
        old->shutdown(true);  // force immediate reset

      } else {
        log_warning("Datapath is already registered:", dpid,
                    std::make_pair("conn_id", channel->connectionId()));
      }
    }

  } else {
    assert(auxID != 0);

    // Look up main connection and assign auxiliary connection to it. If we
    // don't find a main connection, close the auxiliary channel.
    auto item = dpidMap_.find(dpid);
    if (item != dpidMap_.end()) {
      Connection *parent = item->second;
      if (parent->flags() & Connection::kPermitsAuxiliary) {
        channel->setMainConnection(parent, auxID);
      } else {
        log_warning(
            "registerDatapath: Auxiliary connection not permitted for datapath",
            dpid, "aux", static_cast<int>(auxID),
            std::make_pair("conn_id", channel->connectionId()));
        return false;
      }

    } else {
      log_warning("registerDatapath: Main connection not found for datapath",
                  dpid, "aux", static_cast<int>(auxID),
                  std::make_pair("conn_id", channel->connectionId()));
      return false;
    }
  }

  return true;
}

void Engine::releaseDatapath(Connection *channel) {
  DatapathID dpid = channel->datapathId();
  UInt8 auxID = channel->auxiliaryId();

  // We only need to release the datapath for main connections.
  if (auxID == 0) {
    // When releasing the datapathID for a main connection, we need to
    // verify that the datapathID _is_ registered to this connection.
    auto item = dpidMap_.find(dpid);
    if (item != dpidMap_.end()) {
      if (item->second == channel)
        dpidMap_.erase(item);
    }
  }
}

UInt64 Engine::registerServer(TCP_Server *server) {
  assert(!serverListLock_);
  serverList_.push_back(server);
  return assignConnectionId();
}

void Engine::releaseServer(TCP_Server *server) {
  assert(!serverListLock_);
  auto iter = std::find(serverList_.begin(), serverList_.end(), server);
  if (iter != serverList_.end()) {
    assert(*iter == server);
    serverList_.erase(iter);
  }
}

UInt64 Engine::registerConnection(Connection *connection) {
  assert(!connListLock_);
  connList_.push_back(connection);
  return assignConnectionId();
}

void Engine::releaseConnection(Connection *connection) {
  assert(!connListLock_);
  auto iter = findConnIter(connection->connectionId());
  if (iter != connList_.end()) {
    assert(*iter == connection);
#if __GNUC__ == 4 && __GNUC_MINOR__ == 8
    // Convert const_iterator to iterator.
    auto it = connList_.begin() + (iter - connList_.begin());
    connList_.erase(it);
#else
    connList_.erase(iter);
#endif
  }
}

void Engine::installSignalHandlers(std::function<void()> callback) {
  log_debug("Install signal handlers");

  std::error_code ignore;
  signals_.cancel(ignore);
  signals_.clear(ignore);
  signals_.add(SIGINT);
  signals_.add(SIGTERM);

  OFP_BEGIN_IGNORE_PADDING

  signals_.async_wait(
      [this, callback](const asio::error_code &error, int signum) {
        if (!error) {
          const char *signame = (signum == SIGTERM)
                                    ? "SIGTERM"
                                    : (signum == SIGINT) ? "SIGINT" : "???";
          log_info("Signal received:", signame);

          signals_.cancel();
          idleTimer_.cancel();
          (void)this->close(0);

          if (callback)
            callback();

        } else {
          log_error("Signal error", signum, error);
        }
      });

  OFP_END_IGNORE_PADDING
}

UInt64 Engine::assignConnectionId() {
  if (++lastConnId_ == 0) {
    static_assert(sizeof(lastConnId_) == 8, "Expected 64-bit integer");
    log::fatal("Engine::assignConnectionId: Ran out of 64-bit connectionIds");
  }
  return lastConnId_;
}

Connection *Engine::findDatapath(UInt64 connId, const DatapathID &dpid) const {
  // Use the connectionId, it it's non-zero.
  if (connId != 0) {
    return findConnId(connId);
  }

  // If datapath ID is not all zeros, use it to look up the connection.
  if (!dpid.empty()) {
    auto item = dpidMap_.find(dpid);
    if (item != dpidMap_.end()) {
      return item->second;
    }
    return nullptr;
  }

  assert(dpid.empty() && connId == 0);

  return nullptr;
}

Connection *Engine::findConnId(UInt64 connId) const {
  auto iter = findConnIter(connId);
  if (iter != connList_.end()) {
    return *iter;
  }
  return nullptr;
}

std::vector<Connection *>::const_iterator Engine::findConnIter(
    UInt64 connId) const {
  assert(connId != 0);

  // Use binary search to locate connection with connID.
  auto iter = std::lower_bound(
      connList_.begin(), connList_.end(), connId,
      [](Connection *conn, UInt64 cid) { return conn->connectionId() < cid; });

  if (iter != connList_.end()) {
    Connection *conn = *iter;
    if (conn->connectionId() == connId)
      return iter;
  }

  return connList_.end();
}

void Engine::asyncIdle() {
  asio::error_code error;

  idleTimer_.expires_after(1000_ms, error);
  idleTimer_.async_wait([this](const asio::error_code &err) {
    if (!err) {
      TimePoint now = TimeClock::now();
      forEachConnection([this, &now](Connection *conn) {
        if (conn->flags() & Connection::kConnectionUp) {
          conn->tickle(now);
        }
      });
      asyncIdle();
    }
  });
}

void Engine::setAlertCallback(AlertCallback callback, void *context) {
  alertCallback_ = callback;
  alertContext_ = context;
}

void Engine::alert(Channel *conn, const std::string &alert,
                   const ByteRange &data) {
  if (alertCallback_) {
    alertCallback_(conn, alert, data, alertContext_);
  }
}
<|endoftext|>