<commit_before>/*************************************************************************
 *
 *  $RCSfile: CommonTools.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: oj $ $Date: 2002-07-05 06:58:31 $
 *
 *  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 _CONNECTIVITY_COMMONTOOLS_HXX_
#define _CONNECTIVITY_COMMONTOOLS_HXX_

#ifndef _RTL_USTRING_
#include <rtl/ustring>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif
#ifndef _VECTOR_
#include <vector>
#endif
#ifndef _CPPUHELPER_WEAKREF_HXX_
#include <cppuhelper/weakref.hxx>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#endif
#ifndef _OSL_INTERLOCK_H_
#include <osl/interlck.h>
#endif

#ifdef _MSC_VER
#ifndef SAL_NO_VTABLE
#define SAL_NO_VTABLE __declspec(novtable)
#endif
#else
#define SAL_NO_VTABLE
#endif

namespace com { namespace sun { namespace star { namespace util {
    struct Date;
    struct DateTime;
    struct Time;
}
}}}

namespace connectivity
{
    //------------------------------------------------------------------------------
    sal_Bool match(const sal_Unicode* pWild, const sal_Unicode* pStr, const sal_Unicode cEscape);
    //------------------------------------------------------------------------------
    rtl::OUString toString(const ::com::sun::star::uno::Any& rValue);
    rtl::OUString toDateString(const ::com::sun::star::util::Date& rDate);
    rtl::OUString toTimeString(const ::com::sun::star::util::Time& rTime);
    rtl::OUString toDateTimeString(const ::com::sun::star::util::DateTime& rDateTime);

    // typedefs
    typedef std::vector< ::com::sun::star::uno::WeakReferenceHelper > OWeakRefArray;
    typedef ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XColumnsSupplier>    OSQLTable;

    DECLARE_STL_MAP(::rtl::OUString,OSQLTable,comphelper::UStringMixLess,  OSQLTables);

    // -------------------------------------------------------------------------
    // class ORefVector allows reference counting on a std::vector
    // -------------------------------------------------------------------------
    template< class VectorVal > class ORefVector : public ::std::vector< VectorVal >
    {
        oslInterlockedCount         m_refCount;
        //  ORefVector(const ORefVector&);
        //  ORefVector& operator=(const ORefVector&);

        typedef ::std::vector< VectorVal > BaseClass;
    protected:
        virtual ~ORefVector(){}
    public:
        ORefVector() : m_refCount(0) {}
        ORefVector(size_t _st) : ::std::vector< VectorVal > (_st) , m_refCount(0) {}
        ORefVector(const ORefVector& _rRH) : ::std::vector< VectorVal > (_rRH),m_refCount(0)
        {
        }
        ORefVector& operator=(const ORefVector& _rRH)
        {
            if ( &_rRH != this )
            {
                BaseClass::operator=(_rRH);
            }
            return *this;
        }

        inline static void * SAL_CALL operator new( size_t nSize ) SAL_THROW( () )
            { return ::rtl_allocateMemory( nSize ); }
        inline static void SAL_CALL operator delete( void * pMem ) SAL_THROW( () )
            { ::rtl_freeMemory( pMem ); }
        inline static void * SAL_CALL operator new( size_t, void * pMem ) SAL_THROW( () )
            { return pMem; }
        inline static void SAL_CALL operator delete( void *, void * ) SAL_THROW( () )
            {}

        void acquire()
        {
            osl_incrementInterlockedCount( &m_refCount );
        }
        void release()
        {
            if (! osl_decrementInterlockedCount( &m_refCount ))
                delete this;
        }

    };
    // -------------------------------------------------------------------------
    // class ORowVector incudes refcounting and initialze himself
    // with at least one element. This first element is reserved for
    // the bookmark
    // -------------------------------------------------------------------------
    template< class VectorVal > class ORowVector : public  ORefVector< VectorVal >
    {
    public:
        ORowVector() : ORefVector< VectorVal >(1){}
        ORowVector(size_t _st) : ORefVector< VectorVal >(_st+1)
            {}
    };

    typedef ORefVector< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> > OSQLColumns;

    // =======================================================================================
    // search from __first to __last the column with the name _rVal
    // when no such column exist __last is returned
    OSQLColumns::const_iterator find(   OSQLColumns::const_iterator __first,
                                        OSQLColumns::const_iterator __last,
                                        const ::rtl::OUString& _rVal,
                                        const ::comphelper::UStringMixEqual& _rCase);
    // =======================================================================================
    // search from __first to __last the column with the realname _rVal
    // when no such column exist __last is returned
    OSQLColumns::const_iterator findRealName(   OSQLColumns::const_iterator __first,
                                                OSQLColumns::const_iterator __last,
                                                const ::rtl::OUString& _rVal,
                                                const ::comphelper::UStringMixEqual& _rCase);

    // =======================================================================================
    // the first two find methods are much faster than the one below
    // =======================================================================================
    // search from __first to __last the column with the property _rProp equals the value _rVal
    // when no such column exist __last is returned
    OSQLColumns::const_iterator find(   OSQLColumns::const_iterator __first,
                                        OSQLColumns::const_iterator __last,
                                        const ::rtl::OUString& _rProp,
                                        const ::rtl::OUString& _rVal,
                                        const ::comphelper::UStringMixEqual& _rCase);

    void checkDisposed(sal_Bool _bThrow) throw ( ::com::sun::star::lang::DisposedException );
}

//==================================================================================

#define DECLARE_SERVICE_INFO()  \
    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException); \
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); \
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException) \

#define IMPLEMENT_SERVICE_INFO(classname, implasciiname, serviceasciiname)  \
    ::rtl::OUString SAL_CALL classname::getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException)   \
    {   \
        return ::rtl::OUString::createFromAscii(implasciiname); \
    }   \
    ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL classname::getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException)  \
    {   \
        ::com::sun::star::uno::Sequence< ::rtl::OUString > aSupported(1);   \
        aSupported[0] = ::rtl::OUString::createFromAscii(serviceasciiname); \
        return aSupported;  \
    }   \
    sal_Bool SAL_CALL classname::supportsService( const ::rtl::OUString& _rServiceName ) throw(::com::sun::star::uno::RuntimeException) \
    {   \
        Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());             \
        const ::rtl::OUString* pSupported = aSupported.getConstArray();                 \
        const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();              \
        for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)   \
            ;                                                                           \
                                                                                \
        return pSupported != pEnd;                                                      \
    }   \

//==================================================================================

#endif // _CONNECTIVITY_COMMONTOOLS_HXX_

<commit_msg>INTEGRATION: CWS insight01 (1.15.98); FILE MERGED 2004/01/02 09:03:59 oj 1.15.98.2: #111075# ongoing work 2003/08/04 06:11:42 oj 1.15.98.1: #111075# ongoing work<commit_after>/*************************************************************************
 *
 *  $RCSfile: CommonTools.hxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: hr $ $Date: 2004-08-02 16:48:07 $
 *
 *  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 _CONNECTIVITY_COMMONTOOLS_HXX_
#define _CONNECTIVITY_COMMONTOOLS_HXX_

#ifndef _RTL_USTRING_
#include <rtl/ustring>
#endif
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif
#ifndef _VECTOR_
#include <vector>
#endif
#ifndef _CPPUHELPER_WEAKREF_HXX_
#include <cppuhelper/weakref.hxx>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#endif
#ifndef _OSL_INTERLOCK_H_
#include <osl/interlck.h>
#endif
#ifndef INCLUDED_JVMACCESS_VIRTUALMACHINE_HXX
#include <jvmaccess/virtualmachine.hxx>
#endif // INCLUDED_JVMACCESS_VIRTUALMACHINE_HXX
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

namespace com { namespace sun { namespace star { namespace util {
    struct Date;
    struct DateTime;
    struct Time;
}
}}}

namespace connectivity
{
    //------------------------------------------------------------------------------
    sal_Bool match(const sal_Unicode* pWild, const sal_Unicode* pStr, const sal_Unicode cEscape);
    //------------------------------------------------------------------------------
    rtl::OUString toString(const ::com::sun::star::uno::Any& rValue);
    rtl::OUString toDateString(const ::com::sun::star::util::Date& rDate);
    rtl::OUString toTimeString(const ::com::sun::star::util::Time& rTime);
    rtl::OUString toDateTimeString(const ::com::sun::star::util::DateTime& rDateTime);

    // typedefs
    typedef std::vector< ::com::sun::star::uno::WeakReferenceHelper > OWeakRefArray;
    typedef ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XColumnsSupplier>    OSQLTable;

    DECLARE_STL_MAP(::rtl::OUString,OSQLTable,comphelper::UStringMixLess,  OSQLTables);

    // -------------------------------------------------------------------------
    // class ORefVector allows reference counting on a std::vector
    // -------------------------------------------------------------------------
    template< class VectorVal > class ORefVector : public ::std::vector< VectorVal >
    {
        oslInterlockedCount         m_refCount;
        //  ORefVector(const ORefVector&);
        //  ORefVector& operator=(const ORefVector&);

        typedef ::std::vector< VectorVal > BaseClass;
    protected:
        virtual ~ORefVector(){}
    public:
        ORefVector() : m_refCount(0) {}
        ORefVector(size_t _st) : ::std::vector< VectorVal > (_st) , m_refCount(0) {}
        ORefVector(const ORefVector& _rRH) : ::std::vector< VectorVal > (_rRH),m_refCount(0)
        {
        }
        ORefVector& operator=(const ORefVector& _rRH)
        {
            if ( &_rRH != this )
            {
                BaseClass::operator=(_rRH);
            }
            return *this;
        }

        inline static void * SAL_CALL operator new( size_t nSize ) SAL_THROW( () )
            { return ::rtl_allocateMemory( nSize ); }
        inline static void SAL_CALL operator delete( void * pMem ) SAL_THROW( () )
            { ::rtl_freeMemory( pMem ); }
        inline static void * SAL_CALL operator new( size_t, void * pMem ) SAL_THROW( () )
            { return pMem; }
        inline static void SAL_CALL operator delete( void *, void * ) SAL_THROW( () )
            {}

        void acquire()
        {
            osl_incrementInterlockedCount( &m_refCount );
        }
        void release()
        {
            if (! osl_decrementInterlockedCount( &m_refCount ))
                delete this;
        }

    };
    // -------------------------------------------------------------------------
    // class ORowVector incudes refcounting and initialze himself
    // with at least one element. This first element is reserved for
    // the bookmark
    // -------------------------------------------------------------------------
    template< class VectorVal > class ORowVector : public  ORefVector< VectorVal >
    {
    public:
        ORowVector() : ORefVector< VectorVal >(1){}
        ORowVector(size_t _st) : ORefVector< VectorVal >(_st+1)
            {}
    };

    typedef ORefVector< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> > OSQLColumns;

    // =======================================================================================
    // search from __first to __last the column with the name _rVal
    // when no such column exist __last is returned
    OSQLColumns::const_iterator find(   OSQLColumns::const_iterator __first,
                                        OSQLColumns::const_iterator __last,
                                        const ::rtl::OUString& _rVal,
                                        const ::comphelper::UStringMixEqual& _rCase);
    // =======================================================================================
    // search from __first to __last the column with the realname _rVal
    // when no such column exist __last is returned
    OSQLColumns::const_iterator findRealName(   OSQLColumns::const_iterator __first,
                                                OSQLColumns::const_iterator __last,
                                                const ::rtl::OUString& _rVal,
                                                const ::comphelper::UStringMixEqual& _rCase);

    // =======================================================================================
    // the first two find methods are much faster than the one below
    // =======================================================================================
    // search from __first to __last the column with the property _rProp equals the value _rVal
    // when no such column exist __last is returned
    OSQLColumns::const_iterator find(   OSQLColumns::const_iterator __first,
                                        OSQLColumns::const_iterator __last,
                                        const ::rtl::OUString& _rProp,
                                        const ::rtl::OUString& _rVal,
                                        const ::comphelper::UStringMixEqual& _rCase);

    void checkDisposed(sal_Bool _bThrow) throw ( ::com::sun::star::lang::DisposedException );

    /** creates a java virtual machine
        @param  _rxFactory
            The ORB.
        @return
            The JavaVM.
    */
    ::rtl::Reference< jvmaccess::VirtualMachine > getJavaVM(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory);

    /** return <TRUE/> if the java class exists, otherwise <FALSE/>.
        @param  _pJVM
            The JavaVM.
        @param  _sClassName
            The class name to look for.
    */
    sal_Bool existsJavaClassByName( const ::rtl::Reference< jvmaccess::VirtualMachine >& _pJVM,const ::rtl::OUString& _sClassName );
}

//==================================================================================

#define DECLARE_SERVICE_INFO()  \
    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException); \
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); \
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException) \

#define IMPLEMENT_SERVICE_INFO(classname, implasciiname, serviceasciiname)  \
    ::rtl::OUString SAL_CALL classname::getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException)   \
    {   \
        return ::rtl::OUString::createFromAscii(implasciiname); \
    }   \
    ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL classname::getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException)  \
    {   \
        ::com::sun::star::uno::Sequence< ::rtl::OUString > aSupported(1);   \
        aSupported[0] = ::rtl::OUString::createFromAscii(serviceasciiname); \
        return aSupported;  \
    }   \
    sal_Bool SAL_CALL classname::supportsService( const ::rtl::OUString& _rServiceName ) throw(::com::sun::star::uno::RuntimeException) \
    {   \
        Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());             \
        const ::rtl::OUString* pSupported = aSupported.getConstArray();                 \
        const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();              \
        for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)   \
            ;                                                                           \
                                                                                \
        return pSupported != pEnd;                                                      \
    }   \

//==================================================================================

#endif // _CONNECTIVITY_COMMONTOOLS_HXX_

<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2016-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once
#include <net/stream.hpp>
#include <s2n.h>
#include <util/ringbuffer.hpp>
#include <errno.h>

//#define VERBOSE_S2N
#ifdef VERBOSE_S2N
#define S2N_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define S2N_PRINT(fmt, ...) /* fmt */
#endif

typedef enum {
  CLIENT_HELLO=0,
  SERVER_HELLO,
  SERVER_CERT,
  SERVER_NEW_SESSION_TICKET,
  SERVER_CERT_STATUS,
  SERVER_KEY,
  SERVER_CERT_REQ,
  SERVER_HELLO_DONE,
  CLIENT_CERT,
  CLIENT_KEY,
  CLIENT_CERT_VERIFY,
  CLIENT_CHANGE_CIPHER_SPEC,
  CLIENT_FINISHED,
  SERVER_CHANGE_CIPHER_SPEC,
  SERVER_FINISHED,
  APPLICATION_DATA
} message_type_t;
extern "C" message_type_t s2n_conn_get_current_message_type(struct s2n_connection*);
extern "C" ssize_t s2n_conn_serialize_to(struct s2n_connection*, void* addr, size_t);

namespace s2n
{
  typedef int s2n_connection_send(void *io_context, const uint8_t *buf, uint32_t len);
  typedef int s2n_connection_recv(void *io_context, uint8_t *buf, uint32_t len);
  static inline s2n_connection_send s2n_send;
  static inline s2n_connection_recv s2n_recv;

  static void print_s2n_error(const char* app_error)
  {
      fprintf(stderr, "%s: '%s' : '%s'\n",
              app_error,
              s2n_strerror(s2n_errno, "EN"),
              s2n_strerror_debug(s2n_errno, "EN"));
  }

  struct TLS_stream : public net::Stream
  {
    using Stream_ptr = net::Stream_ptr;

    TLS_stream(s2n_config*, Stream_ptr, bool outgoing = false);
    TLS_stream(s2n_connection*, Stream_ptr, bool outgoing = false);
    virtual ~TLS_stream();

    void write(buffer_t buffer) override;
    void write(const std::string&) override;
    void write(const void* buf, size_t n) override;
    void close() override;
    void reset_callbacks() override;

    net::Socket local() const override {
      return m_transport->local();
    }
    net::Socket remote() const override {
      return m_transport->remote();
    }
    std::string to_string() const override {
      return m_transport->to_string();
    }

    void on_connect(ConnectCallback cb) override {
      m_on_connect = std::move(cb);
    }
    void on_read(size_t, ReadCallback cb) override {
      m_on_read = std::move(cb);
    }
    void on_close(CloseCallback cb) override {
      m_on_close = std::move(cb);
    }
    void on_write(WriteCallback cb) override {
      m_on_write = std::move(cb);
    }

    bool is_connected() const noexcept override {
      return handshake_completed() && m_transport->is_connected();
    }
    bool is_writable() const noexcept override {
      return is_connected() && m_transport->is_writable();
    }
    bool is_readable() const noexcept override {
      return m_transport->is_readable();
    }
    bool is_closing() const noexcept override {
      return m_transport->is_closing();
    }
    bool is_closed() const noexcept override {
      return m_transport->is_closed();
    }

    int get_cpuid() const noexcept override {
      return m_transport->get_cpuid();
    }

    Stream* transport() noexcept override {
      return m_transport.get();
    }

    size_t serialize_to(void*, size_t) const override;

  private:
    void initialize(bool outgoing);
    void tls_read(buffer_t);
    bool handshake_completed() const noexcept;
    void close_callback_once();

    Stream_ptr m_transport = nullptr;
    s2n_connection* m_conn = nullptr;
    bool  m_busy = false;
    bool  m_deferred_close = false;
    ConnectCallback  m_on_connect = nullptr;
    ReadCallback     m_on_read    = nullptr;
    WriteCallback    m_on_write   = nullptr;
    CloseCallback    m_on_close   = nullptr;
    FixedRingBuffer<16384> m_readq;

    friend s2n_connection_recv s2n_recv;
    friend s2n_connection_send s2n_send;
  };

  inline TLS_stream::TLS_stream(s2n_config* config, Stream_ptr t,
                                const bool outgoing)
    : m_transport(std::move(t))
  {
    assert(this->m_transport != nullptr);
    this->m_conn = s2n_connection_new(outgoing ? S2N_CLIENT : S2N_SERVER);
    if (s2n_connection_set_config(this->m_conn, config) < 0) {
      print_s2n_error("Error setting config");
      throw std::runtime_error("Error setting s2n::TLS_stream config");
    }
    this->initialize(outgoing);
  }
  inline TLS_stream::TLS_stream(s2n_connection* conn, Stream_ptr t,
                                const bool outgoing)
    : m_transport(std::move(t)), m_conn(conn)
  {
    assert(this->m_transport != nullptr);
    assert(this->m_conn != nullptr);
    this->initialize(outgoing);
  }
  inline void TLS_stream::initialize(bool outgoing)
  {
    s2n_connection_set_send_cb(this->m_conn, s2n_send);
    s2n_connection_set_recv_cb(this->m_conn, s2n_recv);
    s2n_connection_set_send_ctx(this->m_conn, this);
    s2n_connection_set_recv_ctx(this->m_conn, this);
    s2n_connection_set_ctx(this->m_conn, this);
    this->m_transport->on_read(8192, {this, &TLS_stream::tls_read});

    // initial handshake on outgoing connections
    if (outgoing)
    {
      s2n_blocked_status blocked;
      int r = s2n_negotiate(this->m_conn, &blocked);
      S2N_PRINT("s2n_negotiate: %d / %d, blocked = %x\n",
                r, m_readq.size(), blocked);
      if (r < 0) {
        if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED)
        {
          fprintf(stderr, "Failed to negotiate: '%s'. %s\n", s2n_strerror(s2n_errno, "EN"), s2n_strerror_debug(s2n_errno, "EN"));
          fprintf(stderr, "Alert: %d\n", s2n_connection_get_alert(this->m_conn));
          this->close();
        }
        return;
      }
    }
  }
  inline TLS_stream::~TLS_stream()
  {
    S2N_PRINT("s2n::TLS_stream::~TLS_stream(%p)\n", this);
    assert(m_busy == false && "Cannot delete stream while in its call stack");
    s2n_connection_free(this->m_conn);
  }

  inline void TLS_stream::write(buffer_t buffer)
  {
    assert(handshake_completed());
    s2n_blocked_status blocked;
    s2n_send(this->m_conn, buffer->data(), buffer->size(), &blocked);
    S2N_PRINT("write %zu bytes, blocked = %x\n", buffer->size(), blocked);
  }
  inline void TLS_stream::write(const std::string& str)
  {
    assert(handshake_completed());
    s2n_blocked_status blocked;
    s2n_send(this->m_conn, str.data(), str.size(), &blocked);
    S2N_PRINT("write %zu bytes, blocked = %x\n", str.size(), blocked);
  }
  inline void TLS_stream::write(const void* data, const size_t len)
  {
    assert(handshake_completed());
    auto* buf = static_cast<const uint8_t*> (data);
    s2n_blocked_status blocked;
    s2n_send(this->m_conn, buf, len, &blocked);
    S2N_PRINT("write %zu bytes, blocked = %x\n", len, blocked);
  }

  inline void TLS_stream::tls_read(buffer_t data_in)
  {
    S2N_PRINT("s2n::tls_read(%p): %p, %zu bytes -> %p\n",
              this, data_in->data(), data_in->size(), m_readq.data());
    m_readq.write(data_in->data(), data_in->size());

    s2n_blocked_status blocked;
    do {
      int r = 0;
      if (handshake_completed())
      {
        char buffer[8192];
        const int size = sizeof(buffer);
        r = s2n_recv(this->m_conn, buffer, size, &blocked);
        S2N_PRINT("s2n_recv: %d, blocked = %x\n", r, blocked);
        if (r > 0) {
          if (this->m_on_read != nullptr)
            this->m_on_read(
               net::Stream::construct_buffer(buffer, buffer + r));
        }
        else if (r == 0) {
          // normal peer shutdown
          this->close();
          return;
        }
        else if (r < 0) {
          if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED)
          {
            fprintf(stderr, "Failed to negotiate: '%s'. %s\n", s2n_strerror(s2n_errno, "EN"), s2n_strerror_debug(s2n_errno, "EN"));
            fprintf(stderr, "Alert: %d\n", s2n_connection_get_alert(this->m_conn));
            this->close();
          }
          return;
        }
      } else {
        S2N_PRINT("calling s2n_negotiate\n");
        r = s2n_negotiate(this->m_conn, &blocked);
        S2N_PRINT("s2n_negotiate: %d / %d, blocked = %x\n",
                  r, m_readq.size(), blocked);
        if (r == 0) {
          if (this->m_on_connect) m_on_connect(*this);
        }
        else if (r < 0) {
          if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED)
          {
            fprintf(stderr, "Failed to negotiate: '%s'. %s\n", s2n_strerror(s2n_errno, "EN"), s2n_strerror_debug(s2n_errno, "EN"));
            fprintf(stderr, "Alert: %d\n", s2n_connection_get_alert(this->m_conn));
            this->close();
          }
          return;
        }
      }
    } while (blocked != S2N_NOT_BLOCKED);
  }
  int s2n_recv(void* ctx, uint8_t* buf, uint32_t len)
  {
    auto* self = (TLS_stream*) ctx;
    if ((uint32_t) self->m_readq.size() < len) {
      S2N_PRINT("s2n_recv(%p): %p, %u = BLOCKED\n", ctx, buf, len);
      errno = EWOULDBLOCK;
      return -1;
    }
    int res = self->m_readq.read((char*) buf, len);
    S2N_PRINT("s2n_recv(%p): %p, %u = %d\n", ctx, buf, len, res);
    return res;
  }
  int s2n_send(void* ctx, const uint8_t* buf, uint32_t len)
  {
    S2N_PRINT("s2n_send(%p): %p, %u\n", ctx, buf, len);
    ((TLS_stream*) ctx)->m_transport->write(buf, len);
    return len;
  }

  inline void TLS_stream::close()
  {
    if (this->m_busy) {
      this->m_deferred_close = true; return;
    }
    CloseCallback func = std::move(this->m_on_close);
    this->reset_callbacks();
    if (m_transport->is_connected())
        m_transport->close();
    if (func) func();
  }
  inline void TLS_stream::close_callback_once()
  {
    if (this->m_busy) {
      this->m_deferred_close = true; return;
    }
    CloseCallback func = std::move(this->m_on_close);
    this->reset_callbacks();
    if (func) func();
  }
  inline void TLS_stream::reset_callbacks()
  {
    this->m_on_close = nullptr;
    this->m_on_connect = nullptr;
    this->m_on_read  = nullptr;
    this->m_on_write = nullptr;
  }

  inline bool TLS_stream::handshake_completed() const noexcept
  {
    return APPLICATION_DATA == s2n_conn_get_current_message_type(this->m_conn);
  }

  inline size_t TLS_stream::serialize_to(void* addr, size_t size) const {
    ssize_t ret = s2n_conn_serialize_to(this->m_conn, addr, size);
    if (ret < 0) throw std::runtime_error("Failed to serialize TLS connection");
    return ret;
  }
} // s2n
<commit_msg>s2n: Simplify write() to avoid code duplication<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2016-2017 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once
#include <net/stream.hpp>
#include <s2n.h>
#include <util/ringbuffer.hpp>
#include <errno.h>

//#define VERBOSE_S2N
#ifdef VERBOSE_S2N
#define S2N_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define S2N_PRINT(fmt, ...) /* fmt */
#endif

typedef enum {
  CLIENT_HELLO=0,
  SERVER_HELLO,
  SERVER_CERT,
  SERVER_NEW_SESSION_TICKET,
  SERVER_CERT_STATUS,
  SERVER_KEY,
  SERVER_CERT_REQ,
  SERVER_HELLO_DONE,
  CLIENT_CERT,
  CLIENT_KEY,
  CLIENT_CERT_VERIFY,
  CLIENT_CHANGE_CIPHER_SPEC,
  CLIENT_FINISHED,
  SERVER_CHANGE_CIPHER_SPEC,
  SERVER_FINISHED,
  APPLICATION_DATA
} message_type_t;
extern "C" message_type_t s2n_conn_get_current_message_type(struct s2n_connection*);
extern "C" ssize_t s2n_conn_serialize_to(struct s2n_connection*, void* addr, size_t);

namespace s2n
{
  typedef int s2n_connection_send(void *io_context, const uint8_t *buf, uint32_t len);
  typedef int s2n_connection_recv(void *io_context, uint8_t *buf, uint32_t len);
  static inline s2n_connection_send s2n_send;
  static inline s2n_connection_recv s2n_recv;

  static void print_s2n_error(const char* app_error)
  {
      fprintf(stderr, "%s: '%s' : '%s'\n",
              app_error,
              s2n_strerror(s2n_errno, "EN"),
              s2n_strerror_debug(s2n_errno, "EN"));
  }

  struct TLS_stream : public net::Stream
  {
    using Stream_ptr = net::Stream_ptr;

    TLS_stream(s2n_config*, Stream_ptr, bool outgoing = false);
    TLS_stream(s2n_connection*, Stream_ptr, bool outgoing = false);
    virtual ~TLS_stream();

    void write(buffer_t buffer) override;
    void write(const std::string&) override;
    void write(const void* buf, size_t n) override;
    void close() override;
    void reset_callbacks() override;

    net::Socket local() const override {
      return m_transport->local();
    }
    net::Socket remote() const override {
      return m_transport->remote();
    }
    std::string to_string() const override {
      return m_transport->to_string();
    }

    void on_connect(ConnectCallback cb) override {
      m_on_connect = std::move(cb);
    }
    void on_read(size_t, ReadCallback cb) override {
      m_on_read = std::move(cb);
    }
    void on_close(CloseCallback cb) override {
      m_on_close = std::move(cb);
    }
    void on_write(WriteCallback cb) override {
      m_on_write = std::move(cb);
    }

    bool is_connected() const noexcept override {
      return handshake_completed() && m_transport->is_connected();
    }
    bool is_writable() const noexcept override {
      return is_connected() && m_transport->is_writable();
    }
    bool is_readable() const noexcept override {
      return m_transport->is_readable();
    }
    bool is_closing() const noexcept override {
      return m_transport->is_closing();
    }
    bool is_closed() const noexcept override {
      return m_transport->is_closed();
    }

    int get_cpuid() const noexcept override {
      return m_transport->get_cpuid();
    }

    Stream* transport() noexcept override {
      return m_transport.get();
    }

    size_t serialize_to(void*, size_t) const override;

  private:
    void initialize(bool outgoing);
    void tls_read(buffer_t);
    bool handshake_completed() const noexcept;
    void close_callback_once();

    Stream_ptr m_transport = nullptr;
    s2n_connection* m_conn = nullptr;
    bool  m_busy = false;
    bool  m_deferred_close = false;
    ConnectCallback  m_on_connect = nullptr;
    ReadCallback     m_on_read    = nullptr;
    WriteCallback    m_on_write   = nullptr;
    CloseCallback    m_on_close   = nullptr;
    FixedRingBuffer<16384> m_readq;

    friend s2n_connection_recv s2n_recv;
    friend s2n_connection_send s2n_send;
  };

  inline TLS_stream::TLS_stream(s2n_config* config, Stream_ptr t,
                                const bool outgoing)
    : m_transport(std::move(t))
  {
    assert(this->m_transport != nullptr);
    this->m_conn = s2n_connection_new(outgoing ? S2N_CLIENT : S2N_SERVER);
    if (s2n_connection_set_config(this->m_conn, config) < 0) {
      print_s2n_error("Error setting config");
      throw std::runtime_error("Error setting s2n::TLS_stream config");
    }
    this->initialize(outgoing);
  }
  inline TLS_stream::TLS_stream(s2n_connection* conn, Stream_ptr t,
                                const bool outgoing)
    : m_transport(std::move(t)), m_conn(conn)
  {
    assert(this->m_transport != nullptr);
    assert(this->m_conn != nullptr);
    this->initialize(outgoing);
  }
  inline void TLS_stream::initialize(bool outgoing)
  {
    s2n_connection_set_send_cb(this->m_conn, s2n_send);
    s2n_connection_set_recv_cb(this->m_conn, s2n_recv);
    s2n_connection_set_send_ctx(this->m_conn, this);
    s2n_connection_set_recv_ctx(this->m_conn, this);
    s2n_connection_set_ctx(this->m_conn, this);
    this->m_transport->on_read(8192, {this, &TLS_stream::tls_read});

    // initial handshake on outgoing connections
    if (outgoing)
    {
      s2n_blocked_status blocked;
      int r = s2n_negotiate(this->m_conn, &blocked);
      S2N_PRINT("s2n_negotiate: %d / %d, blocked = %x\n",
                r, m_readq.size(), blocked);
      if (r < 0) {
        if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED)
        {
          fprintf(stderr, "Failed to negotiate: '%s'. %s\n", s2n_strerror(s2n_errno, "EN"), s2n_strerror_debug(s2n_errno, "EN"));
          fprintf(stderr, "Alert: %d\n", s2n_connection_get_alert(this->m_conn));
          this->close();
        }
        return;
      }
    }
  }
  inline TLS_stream::~TLS_stream()
  {
    S2N_PRINT("s2n::TLS_stream::~TLS_stream(%p)\n", this);
    assert(m_busy == false && "Cannot delete stream while in its call stack");
    s2n_connection_free(this->m_conn);
  }

  inline void TLS_stream::write(buffer_t buffer)
  {
    this->write(buffer->data(), buffer->size());
  }
  inline void TLS_stream::write(const std::string& str)
  {
    this->write(str.data(), str.size());
  }
  inline void TLS_stream::write(const void* data, const size_t len)
  {
    assert(handshake_completed());
    auto* buf = static_cast<const uint8_t*> (data);
    s2n_blocked_status blocked;
    s2n_send(this->m_conn, buf, len, &blocked);
    S2N_PRINT("write %zu bytes, blocked = %x\n", len, blocked);
  }

  inline void TLS_stream::tls_read(buffer_t data_in)
  {
    S2N_PRINT("s2n::tls_read(%p): %p, %zu bytes -> %p\n",
              this, data_in->data(), data_in->size(), m_readq.data());
    m_readq.write(data_in->data(), data_in->size());

    s2n_blocked_status blocked;
    do {
      int r = 0;
      if (handshake_completed())
      {
        char buffer[8192];
        const int size = sizeof(buffer);
        r = s2n_recv(this->m_conn, buffer, size, &blocked);
        S2N_PRINT("s2n_recv: %d, blocked = %x\n", r, blocked);
        if (r > 0) {
          if (this->m_on_read != nullptr)
            this->m_on_read(
               net::Stream::construct_buffer(buffer, buffer + r));
        }
        else if (r == 0) {
          // normal peer shutdown
          this->close();
          return;
        }
        else if (r < 0) {
          if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED)
          {
            fprintf(stderr, "Failed to negotiate: '%s'. %s\n", s2n_strerror(s2n_errno, "EN"), s2n_strerror_debug(s2n_errno, "EN"));
            fprintf(stderr, "Alert: %d\n", s2n_connection_get_alert(this->m_conn));
            this->close();
          }
          return;
        }
      } else {
        S2N_PRINT("calling s2n_negotiate\n");
        r = s2n_negotiate(this->m_conn, &blocked);
        S2N_PRINT("s2n_negotiate: %d / %d, blocked = %x\n",
                  r, m_readq.size(), blocked);
        if (r == 0) {
          if (this->m_on_connect) m_on_connect(*this);
        }
        else if (r < 0) {
          if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED)
          {
            fprintf(stderr, "Failed to negotiate: '%s'. %s\n", s2n_strerror(s2n_errno, "EN"), s2n_strerror_debug(s2n_errno, "EN"));
            fprintf(stderr, "Alert: %d\n", s2n_connection_get_alert(this->m_conn));
            this->close();
          }
          return;
        }
      }
    } while (blocked != S2N_NOT_BLOCKED);
  }
  int s2n_recv(void* ctx, uint8_t* buf, uint32_t len)
  {
    auto* self = (TLS_stream*) ctx;
    if ((uint32_t) self->m_readq.size() < len) {
      S2N_PRINT("s2n_recv(%p): %p, %u = BLOCKED\n", ctx, buf, len);
      errno = EWOULDBLOCK;
      return -1;
    }
    int res = self->m_readq.read((char*) buf, len);
    S2N_PRINT("s2n_recv(%p): %p, %u = %d\n", ctx, buf, len, res);
    return res;
  }
  int s2n_send(void* ctx, const uint8_t* buf, uint32_t len)
  {
    S2N_PRINT("s2n_send(%p): %p, %u\n", ctx, buf, len);
    ((TLS_stream*) ctx)->m_transport->write(buf, len);
    return len;
  }

  inline void TLS_stream::close()
  {
    if (this->m_busy) {
      this->m_deferred_close = true; return;
    }
    CloseCallback func = std::move(this->m_on_close);
    this->reset_callbacks();
    if (m_transport->is_connected())
        m_transport->close();
    if (func) func();
  }
  inline void TLS_stream::close_callback_once()
  {
    if (this->m_busy) {
      this->m_deferred_close = true; return;
    }
    CloseCallback func = std::move(this->m_on_close);
    this->reset_callbacks();
    if (func) func();
  }
  inline void TLS_stream::reset_callbacks()
  {
    this->m_on_close = nullptr;
    this->m_on_connect = nullptr;
    this->m_on_read  = nullptr;
    this->m_on_write = nullptr;
  }

  inline bool TLS_stream::handshake_completed() const noexcept
  {
    return APPLICATION_DATA == s2n_conn_get_current_message_type(this->m_conn);
  }

  inline size_t TLS_stream::serialize_to(void* addr, size_t size) const {
    ssize_t ret = s2n_conn_serialize_to(this->m_conn, addr, size);
    if (ret < 0) throw std::runtime_error("Failed to serialize TLS connection");
    return ret;
  }
} // s2n
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XSIMD_CONFIG_HPP
#define XSIMD_CONFIG_HPP

#include "xsimd_align.hpp"

#define XSIMD_VERSION_MAJOR 7
#define XSIMD_VERSION_MINOR 0
#define XSIMD_VERSION_PATCH 0

#ifndef XSIMD_DEFAULT_ALLOCATOR
    #if XSIMD_X86_INSTR_SET_AVAILABLE
        #define XSIMD_DEFAULT_ALLOCATOR(T) xsimd::aligned_allocator<T, XSIMD_DEFAULT_ALIGNMENT>
    #else
        #define XSIMD_DEFAULT_ALLOCATOR(T) std::allocator<T>
    #endif
#endif

#ifndef XSIMD_STACK_ALLOCATION_LIMIT
    #define XSIMD_STACK_ALLOCATION_LIMIT 20000
#endif

#if defined(__LP64__) || defined(_WIN64)
    #define XSIMD_64_BIT_ABI
#else
    #define XSIMD_32_BIT_ABI
#endif

#endif
<commit_msg>Release 7.1.0<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef XSIMD_CONFIG_HPP
#define XSIMD_CONFIG_HPP

#include "xsimd_align.hpp"

#define XSIMD_VERSION_MAJOR 7
#define XSIMD_VERSION_MINOR 1
#define XSIMD_VERSION_PATCH 0

#ifndef XSIMD_DEFAULT_ALLOCATOR
    #if XSIMD_X86_INSTR_SET_AVAILABLE
        #define XSIMD_DEFAULT_ALLOCATOR(T) xsimd::aligned_allocator<T, XSIMD_DEFAULT_ALIGNMENT>
    #else
        #define XSIMD_DEFAULT_ALLOCATOR(T) std::allocator<T>
    #endif
#endif

#ifndef XSIMD_STACK_ALLOCATION_LIMIT
    #define XSIMD_STACK_ALLOCATION_LIMIT 20000
#endif

#if defined(__LP64__) || defined(_WIN64)
    #define XSIMD_64_BIT_ABI
#else
    #define XSIMD_32_BIT_ABI
#endif

#endif
<|endoftext|>


<commit_before>/*!
    \file file_lock.cpp
    \brief File-lock synchronization primitive implementation
    \author Ivan Shynkarenka
    \date 01.09.2016
    \copyright MIT License
*/

#include "threads/file_lock.h"

#include "errors/fatal.h"
#include "filesystem/exceptions.h"
#include "threads/thread.h"

#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#include <windows.h>
#undef Yield
#endif

namespace CppCommon {

//! @cond INTERNALS

// In case we are on a system with glibc version earlier than 2.20
#ifndef F_OFD_GETLK
#define F_OFD_GETLK  36
#define F_OFD_SETLK  37
#define F_OFD_SETLKW 38
#endif

class FileLock::Impl
{
public:
    Impl(const Path& path) : _path(path)
    {
#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        _file = open(_path.string().c_str(), O_CREAT | O_EXCL | O_RDWR, 0644);
        if (_file < 0)
        {
            if (errno == EEXIST)
            {
                _file = open(_path.string().c_str(), O_CREAT | O_RDWR, 0644);
                if (_file >= 0)
                {
                    _owner = false;
                    return;
                }
            }
        }
        else
        {
            _owner = true;
            return;
        }
        throwex FileSystemException("Cannot create or open file-lock! file").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        std::wstring wpath = _path.wstring();

        // Retries in CreateFile, see http://support.microsoft.com/kb/316609
        const int attempts = 5;
        const int sleep = 250;
        for (int attempt = 0; attempt < attempts; ++attempt)
        {
            _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, nullptr);
            if (_file == INVALID_HANDLE_VALUE)
            {
                if (GetLastError() == ERROR_SHARING_VIOLATION)
                {
                    Sleep(sleep);
                    continue;
                }
                else
                {
                    _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, nullptr);
                    if (_file == INVALID_HANDLE_VALUE)
                    {
                        if (GetLastError() == ERROR_SHARING_VIOLATION)
                        {
                            Sleep(sleep);
                            continue;
                        }
                        else
                            break;
                    }
                    else
                    {
                        _owner = false;
                        return;
                    }
                }
            }
            else
            {
                _owner = true;
                return;
            }
        }
        throwex FileSystemException("Cannot create or open file-lock file!").Attach(_path);
#endif
    }

    ~Impl()
    {
#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = close(_file);
        if (result != 0)
            fatality(FileSystemException("Cannot close the file-lock descriptor!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            result = unlink(_path.string().c_str());
            if (result != 0)
                fatality(FileSystemException("Cannot unlink the file-lock file!").Attach(_path));
        }
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        if (!CloseHandle(_file))
            fatality(FileSystemException("Cannot close the file-lock handle!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            if (!DeleteFileW(_path.wstring().c_str()))
                fatality(FileSystemException("Cannot delete the file-lock file!").Attach(_path));
        }
#endif
    }

    const Path& path() const noexcept { return _path; }

    bool TryLockRead()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        return true;
#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_SH | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        return true;
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#endif
    }

    bool TryLockWrite()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        return true;
#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_EX | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        return true;
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#endif
    }

    void LockRead()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_SH);
        if (result != 0)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, 0, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#endif
    }

    void LockWrite()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_EX);
        if (result != 0)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#endif
    }

    void UnlockRead()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#endif
    }

    void UnlockWrite()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64)  || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#endif
    }

private:
    Path _path;
#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
    int _file;
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
    HANDLE _file;
#endif
    bool _owner;
};

//! @endcond

FileLock::FileLock(const Path& path) : _pimpl(std::make_unique<Impl>(path))
{
}

FileLock::FileLock(FileLock&& lock) noexcept : _pimpl(std::move(lock._pimpl))
{
}

FileLock::~FileLock()
{
}

FileLock& FileLock::operator=(FileLock&& lock) noexcept
{
    _pimpl = std::move(lock._pimpl);
    return *this;
}

const Path& FileLock::path() const noexcept
{
    return _pimpl->path();
}

bool FileLock::TryLockRead()
{
    return _pimpl->TryLockRead();
}

bool FileLock::TryLockWrite()
{
    return _pimpl->TryLockWrite();
}

bool FileLock::TryLockReadFor(const Timespan& timespan)
{
    // Calculate a finish timestamp
    Timestamp finish = NanoTimestamp() + timespan;

    // Try to acquire read lock at least one time
    if (TryLockRead())
        return true;
    else
    {
        // Try lock or yield for the given timespan
        while (NanoTimestamp() < finish)
        {
            if (TryLockRead())
                return true;
            else
                Thread::Yield();
        }

        // Failed to acquire read lock
        return false;
    }
}

bool FileLock::TryLockWriteFor(const Timespan& timespan)
{
    // Calculate a finish timestamp
    Timestamp finish = NanoTimestamp() + timespan;

    // Try to acquire write lock at least one time
    if (TryLockWrite())
        return true;
    else
    {
        // Try lock or yield for the given timespan
        while (NanoTimestamp() < finish)
        {
            if (TryLockWrite())
                return true;
            else
                Thread::Yield();
        }

        // Failed to acquire write lock
        return false;
    }
}

void FileLock::LockRead()
{
    _pimpl->LockRead();
}

void FileLock::LockWrite()
{
    _pimpl->LockWrite();
}

void FileLock::UnlockRead()
{
    _pimpl->UnlockRead();
}

void FileLock::UnlockWrite()
{
    _pimpl->UnlockWrite();
}

} // namespace CppCommon
<commit_msg>Fix OSX build<commit_after>/*!
    \file file_lock.cpp
    \brief File-lock synchronization primitive implementation
    \author Ivan Shynkarenka
    \date 01.09.2016
    \copyright MIT License
*/

#include "threads/file_lock.h"

#include "errors/fatal.h"
#include "filesystem/exceptions.h"
#include "threads/thread.h"

#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#include <windows.h>
#undef Yield
#endif

namespace CppCommon {

//! @cond INTERNALS

// In case we are on a system with glibc version earlier than 2.20
#ifndef F_OFD_GETLK
#define F_OFD_GETLK  36
#define F_OFD_SETLK  37
#define F_OFD_SETLKW 38
#endif

class FileLock::Impl
{
public:
    Impl(const Path& path) : _path(path)
    {
#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        _file = open(_path.string().c_str(), O_CREAT | O_EXCL | O_RDWR, 0644);
        if (_file < 0)
        {
            if (errno == EEXIST)
            {
                _file = open(_path.string().c_str(), O_CREAT | O_RDWR, 0644);
                if (_file >= 0)
                {
                    _owner = false;
                    return;
                }
            }
        }
        else
        {
            _owner = true;
            return;
        }
        throwex FileSystemException("Cannot create or open file-lock! file").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        std::wstring wpath = _path.wstring();

        // Retries in CreateFile, see http://support.microsoft.com/kb/316609
        const int attempts = 5;
        const int sleep = 250;
        for (int attempt = 0; attempt < attempts; ++attempt)
        {
            _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, nullptr);
            if (_file == INVALID_HANDLE_VALUE)
            {
                if (GetLastError() == ERROR_SHARING_VIOLATION)
                {
                    Sleep(sleep);
                    continue;
                }
                else
                {
                    _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, nullptr);
                    if (_file == INVALID_HANDLE_VALUE)
                    {
                        if (GetLastError() == ERROR_SHARING_VIOLATION)
                        {
                            Sleep(sleep);
                            continue;
                        }
                        else
                            break;
                    }
                    else
                    {
                        _owner = false;
                        return;
                    }
                }
            }
            else
            {
                _owner = true;
                return;
            }
        }
        throwex FileSystemException("Cannot create or open file-lock file!").Attach(_path);
#endif
    }

    ~Impl()
    {
#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = close(_file);
        if (result != 0)
            fatality(FileSystemException("Cannot close the file-lock descriptor!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            result = unlink(_path.string().c_str());
            if (result != 0)
                fatality(FileSystemException("Cannot unlink the file-lock file!").Attach(_path));
        }
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        if (!CloseHandle(_file))
            fatality(FileSystemException("Cannot close the file-lock handle!").Attach(_path));

        // Remove the file-lock file (owner only)
        if (_owner)
        {
            if (!DeleteFileW(_path.wstring().c_str()))
                fatality(FileSystemException("Cannot delete the file-lock file!").Attach(_path));
        }
#endif
    }

    const Path& path() const noexcept { return _path; }

    bool TryLockRead()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        else
            return true;
#elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_SH | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for read!").Attach(_path);
        }
        else
            return true;
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#endif
    }

    bool TryLockWrite()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result == -1)
        {
           if  (errno == EAGAIN)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        else
            return true;
#elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_EX | LOCK_NB);
        if (result != 0)
        {
           if  (errno == EWOULDBLOCK)
               return false;
           else
               throwex FileSystemException("Failed to try lock for write!").Attach(_path);
        }
        else
            return true;
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        return LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) ? true : false;
#endif
    }

    void LockRead()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_SH);
        if (result != 0)
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, 0, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for read!").Attach(_path);
#endif
    }

    void LockWrite()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLKW, &lock);
        if (result == -1)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_EX);
        if (result != 0)
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to lock for write!").Attach(_path);
#endif
    }

    void UnlockRead()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the read lock!").Attach(_path);
#endif
    }

    void UnlockWrite()
    {
#if defined(linux) || defined(__linux) || defined(__linux__)
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_pid = 0;
        int result = fcntl(_file, F_OFD_SETLK, &lock);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
        int result = flock(_file, LOCK_UN);
        if (result != 0)
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#elif defined(_WIN32) || defined(_WIN64)  || defined(__CYGWIN__)
        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(OVERLAPPED));
        if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
            throwex FileSystemException("Failed to unlock the write lock!").Attach(_path);
#endif
    }

private:
    Path _path;
#if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
    int _file;
#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
    HANDLE _file;
#endif
    bool _owner;
};

//! @endcond

FileLock::FileLock(const Path& path) : _pimpl(std::make_unique<Impl>(path))
{
}

FileLock::FileLock(FileLock&& lock) noexcept : _pimpl(std::move(lock._pimpl))
{
}

FileLock::~FileLock()
{
}

FileLock& FileLock::operator=(FileLock&& lock) noexcept
{
    _pimpl = std::move(lock._pimpl);
    return *this;
}

const Path& FileLock::path() const noexcept
{
    return _pimpl->path();
}

bool FileLock::TryLockRead()
{
    return _pimpl->TryLockRead();
}

bool FileLock::TryLockWrite()
{
    return _pimpl->TryLockWrite();
}

bool FileLock::TryLockReadFor(const Timespan& timespan)
{
    // Calculate a finish timestamp
    Timestamp finish = NanoTimestamp() + timespan;

    // Try to acquire read lock at least one time
    if (TryLockRead())
        return true;
    else
    {
        // Try lock or yield for the given timespan
        while (NanoTimestamp() < finish)
        {
            if (TryLockRead())
                return true;
            else
                Thread::Yield();
        }

        // Failed to acquire read lock
        return false;
    }
}

bool FileLock::TryLockWriteFor(const Timespan& timespan)
{
    // Calculate a finish timestamp
    Timestamp finish = NanoTimestamp() + timespan;

    // Try to acquire write lock at least one time
    if (TryLockWrite())
        return true;
    else
    {
        // Try lock or yield for the given timespan
        while (NanoTimestamp() < finish)
        {
            if (TryLockWrite())
                return true;
            else
                Thread::Yield();
        }

        // Failed to acquire write lock
        return false;
    }
}

void FileLock::LockRead()
{
    _pimpl->LockRead();
}

void FileLock::LockWrite()
{
    _pimpl->LockWrite();
}

void FileLock::UnlockRead()
{
    _pimpl->UnlockRead();
}

void FileLock::UnlockWrite()
{
    _pimpl->UnlockWrite();
}

} // namespace CppCommon
<|endoftext|>


<commit_before>//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the clang::ParseAST method.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/ParseAST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TranslationUnit.h"
#include "Sema.h"
#include "clang/Parse/Parser.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// Public interface to the file
//===----------------------------------------------------------------------===//

/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed.  This takes ownership of the ASTConsumer and
/// ultimately deletes it.
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, bool PrintStats) {
  // Collect global stats on Decls/Stmts (until we have a module streamer).
  if (PrintStats) {
    Decl::CollectingStats(true);
    Stmt::CollectingStats(true);
  }

  ASTContext Context(PP.getLangOptions(), PP.getSourceManager(),
                     PP.getTargetInfo(),
                     PP.getIdentifierTable(), PP.getSelectorTable());

  TranslationUnit TU(Context);
  TU.SetOwnsDecls(false);

  Sema S(PP, Context, *Consumer);
  Parser P(PP, S);
  PP.EnterMainSourceFile();

  // Initialize the parser.
  P.Initialize();

  Consumer->InitializeTU(TU);

  Parser::DeclTy *ADecl;

  while (!P.ParseTopLevelDecl(ADecl)) {  // Not end of file.
    // If we got a null return and something *was* parsed, ignore it.  This
    // is due to a top-level semicolon, an action override, or a parse error
    // skipping something.
    if (ADecl) {
      Decl* D = static_cast<Decl*>(ADecl);
      TU.AddTopLevelDecl(D); // TranslationUnit now owns the Decl.
      Consumer->HandleTopLevelDecl(D);
    }
  };

  Consumer->HandleTranslationUnit(TU);

  if (PrintStats) {
    fprintf(stderr, "\nSTATISTICS:\n");
    P.getActions().PrintStats();
    Context.PrintStats();
    Decl::PrintStats();
    Stmt::PrintStats();
    Consumer->PrintStats();

    Decl::CollectingStats(false);
    Stmt::CollectingStats(false);
  }
}
<commit_msg>Re-enable deletion of AST nodes upon completion of ParseAST.<commit_after>//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the clang::ParseAST method.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/ParseAST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TranslationUnit.h"
#include "Sema.h"
#include "clang/Parse/Parser.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// Public interface to the file
//===----------------------------------------------------------------------===//

/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed.  This takes ownership of the ASTConsumer and
/// ultimately deletes it.
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, bool PrintStats) {
  // Collect global stats on Decls/Stmts (until we have a module streamer).
  if (PrintStats) {
    Decl::CollectingStats(true);
    Stmt::CollectingStats(true);
  }

  ASTContext Context(PP.getLangOptions(), PP.getSourceManager(),
                     PP.getTargetInfo(),
                     PP.getIdentifierTable(), PP.getSelectorTable());

  TranslationUnit TU(Context);
  Sema S(PP, Context, *Consumer);
  Parser P(PP, S);
  PP.EnterMainSourceFile();

  // Initialize the parser.
  P.Initialize();

  Consumer->InitializeTU(TU);

  Parser::DeclTy *ADecl;

  while (!P.ParseTopLevelDecl(ADecl)) {  // Not end of file.
    // If we got a null return and something *was* parsed, ignore it.  This
    // is due to a top-level semicolon, an action override, or a parse error
    // skipping something.
    if (ADecl) {
      Decl* D = static_cast<Decl*>(ADecl);
      TU.AddTopLevelDecl(D); // TranslationUnit now owns the Decl.
      Consumer->HandleTopLevelDecl(D);
    }
  };

  Consumer->HandleTranslationUnit(TU);

  if (PrintStats) {
    fprintf(stderr, "\nSTATISTICS:\n");
    P.getActions().PrintStats();
    Context.PrintStats();
    Decl::PrintStats();
    Stmt::PrintStats();
    Consumer->PrintStats();

    Decl::CollectingStats(false);
    Stmt::CollectingStats(false);
  }
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include <QTimer>
#include <QList>
#include <QDebug>
#include <QMutexLocker>
#include <iostream>
#include "TCPLink.h"
#include "LinkManager.h"
#include "QGC.h"
#include <QHostInfo>
#include <QSignalSpy>

/// @file
///     @brief TCP link type for SITL support
///
///     @author Don Gagne <don@thegagnes.com>

TCPLink::TCPLink(SharedLinkConfigurationPointer& config)
    : LinkInterface(config)
    , _tcpConfig(qobject_cast<TCPConfiguration*>(config.data()))
    , _socket(nullptr)
    , _socketIsConnected(false)
{
    Q_ASSERT(_tcpConfig);
    moveToThread(this);
}

TCPLink::~TCPLink()
{
    _disconnect();
    // Tell the thread to exit
    quit();
    // Wait for it to exit
    wait();
}

void TCPLink::run()
{
    _hardwareConnect();
    exec();
}

#ifdef TCPLINK_READWRITE_DEBUG
void TCPLink::_writeDebugBytes(const QByteArray data)
{
    QString bytes;
    QString ascii;
    for (int i=0, size = data.size(); i<size; i++)
    {
        unsigned char v = data[i];
        bytes.append(QString::asprintf("%02x ", v));
        if (data[i] > 31 && data[i] < 127)
        {
            ascii.append(data[i]);
        }
        else
        {
            ascii.append(219);
        }
    }
    qDebug() << "Sent" << size << "bytes to" << _tcpConfig->address().toString() << ":" << _tcpConfig->port() << "data:";
    qDebug() << bytes;
    qDebug() << "ASCII:" << ascii;
}
#endif

void TCPLink::_writeBytes(const QByteArray data)
{
#ifdef TCPLINK_READWRITE_DEBUG
    _writeDebugBytes(data);
#endif

    if (_socket) {
        _socket->write(data);
        emit bytesSent(this, data);
        _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch());
    }
}

/**
 * @brief Read a number of bytes from the interface.
 *
 * @param data Pointer to the data byte array to write the bytes to
 * @param maxLength The maximum number of bytes to write
 **/
void TCPLink::readBytes()
{
    if (_socket) {
        qint64 byteCount = _socket->bytesAvailable();
        if (byteCount)
        {
            QByteArray buffer;
            buffer.resize(byteCount);
            _socket->read(buffer.data(), buffer.size());
            emit bytesReceived(this, buffer);
            _logInputDataRate(byteCount, QDateTime::currentMSecsSinceEpoch());
#ifdef TCPLINK_READWRITE_DEBUG
            writeDebugBytes(buffer.data(), buffer.size());
#endif
        }
    }
}

/**
 * @brief Disconnect the connection.
 *
 * @return True if connection has been disconnected, false if connection couldn't be disconnected.
 **/
void TCPLink::_disconnect(void)
{
    quit();
    wait();
    if (_socket) {
        _socketIsConnected = false;
        _socket->disconnectFromHost(); // Disconnect tcp
        _socket->waitForDisconnected();
        _socket->deleteLater(); // Make sure delete happens on correct thread
        _socket = nullptr;
        emit disconnected();
    }
}

/**
 * @brief Connect the connection.
 *
 * @return True if connection has been established, false if connection couldn't be established.
 **/
bool TCPLink::_connect(void)
{
    if (isRunning())
    {
        quit();
        wait();
    }
    start(HighPriority);
    return true;
}

bool TCPLink::_hardwareConnect()
{
    Q_ASSERT(_socket == nullptr);
    _socket = new QTcpSocket();

#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    QSignalSpy errorSpy(_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error));
#else
    QSignalSpy errorSpy(_socket, &QAbstractSocket::errorOccurred);
#endif

    _socket->connectToHost(_tcpConfig->address(), _tcpConfig->port());
    QObject::connect(_socket, &QTcpSocket::readyRead, this, &TCPLink::readBytes);

#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    QObject::connect(_socket,static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error),
                     this, &TCPLink::_socketError);
#else
    QObject::connect(_socket, &QAbstractSocket::errorOccurred, this, &TCPLink::_socketError);
#endif

    // Give the socket a second to connect to the other side otherwise error out
    if (!_socket->waitForConnected(1000))
    {
        // Whether a failed connection emits an error signal or not is platform specific.
        // So in cases where it is not emitted, we emit one ourselves.
        if (errorSpy.count() == 0) {
            emit communicationError(tr("Link Error"), tr("Error on link %1. Connection failed").arg(getName()));
        }
        delete _socket;
        _socket = nullptr;
        return false;
    }
    _socketIsConnected = true;
    emit connected();
    return true;
}

void TCPLink::_socketError(QAbstractSocket::SocketError socketError)
{
    Q_UNUSED(socketError);
    emit communicationError(tr("Link Error"), tr("Error on link %1. Error on socket: %2.").arg(getName()).arg(_socket->errorString()));
}

/**
 * @brief Check if connection is active.
 *
 * @return True if link is connected, false otherwise.
 **/
bool TCPLink::isConnected() const
{
    return _socketIsConnected;
}

QString TCPLink::getName() const
{
    return _tcpConfig->name();
}

qint64 TCPLink::getConnectionSpeed() const
{
    return 54000000; // 54 Mbit
}

qint64 TCPLink::getCurrentInDataRate() const
{
    return 0;
}

qint64 TCPLink::getCurrentOutDataRate() const
{
    return 0;
}

void TCPLink::waitForBytesWritten(int msecs)
{
    Q_ASSERT(_socket);
    _socket->waitForBytesWritten(msecs);
}

void TCPLink::waitForReadyRead(int msecs)
{
    Q_ASSERT(_socket);
    _socket->waitForReadyRead(msecs);
}

void TCPLink::_restartConnection()
{
    if(this->isConnected())
    {
        _disconnect();
        _connect();
    }
}

//--------------------------------------------------------------------------
//-- TCPConfiguration

static bool is_ip(const QString& address)
{
    int a,b,c,d;
    if (sscanf(address.toStdString().c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4
            && strcmp("::1", address.toStdString().c_str())) {
        return false;
    } else {
        return true;
    }
}

static QString get_ip_address(const QString& address)
{
    if(is_ip(address))
        return address;
    // Need to look it up
    QHostInfo info = QHostInfo::fromName(address);
    if (info.error() == QHostInfo::NoError)
    {
        QList<QHostAddress> hostAddresses = info.addresses();
        for (int i = 0; i < hostAddresses.size(); i++)
        {
            // Exclude all IPv6 addresses
            if (!hostAddresses.at(i).toString().contains(":"))
            {
                return hostAddresses.at(i).toString();
            }
        }
    }
    return {};
}

TCPConfiguration::TCPConfiguration(const QString& name) : LinkConfiguration(name)
{
    _port    = QGC_TCP_PORT;
    _address = QHostAddress::Any;
}

TCPConfiguration::TCPConfiguration(TCPConfiguration* source) : LinkConfiguration(source)
{
    _port    = source->port();
    _address = source->address();
}

void TCPConfiguration::copyFrom(LinkConfiguration *source)
{
    LinkConfiguration::copyFrom(source);
    auto* usource = qobject_cast<TCPConfiguration*>(source);
    Q_ASSERT(usource != nullptr);
    _port    = usource->port();
    _address = usource->address();
}

void TCPConfiguration::setPort(quint16 port)
{
    _port = port;
}

void TCPConfiguration::setAddress(const QHostAddress& address)
{
    _address = address;
}

void TCPConfiguration::setHost(const QString host)
{
    QString ipAdd = get_ip_address(host);
    if(ipAdd.isEmpty()) {
        qWarning() << "TCP:" << "Could not resolve host:" << host;
    } else {
        _address = QHostAddress(ipAdd);
    }
}

void TCPConfiguration::saveSettings(QSettings& settings, const QString& root)
{
    settings.beginGroup(root);
    settings.setValue("port", (int)_port);
    settings.setValue("host", address().toString());
    settings.endGroup();
}

void TCPConfiguration::loadSettings(QSettings& settings, const QString& root)
{
    settings.beginGroup(root);
    _port = (quint16)settings.value("port", QGC_TCP_PORT).toUInt();
    QString address = settings.value("host", _address.toString()).toString();
    _address = address;
    settings.endGroup();
}

void TCPConfiguration::updateSettings()
{
    if(_link) {
        auto* ulink = qobject_cast<TCPLink*>(_link);
        if(ulink) {
            ulink->_restartConnection();
        }
    }
}
<commit_msg>TCPLink: Use QHostAddress constructor since QHostAddress::operator= is deprecated<commit_after>/****************************************************************************
 *
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include <QTimer>
#include <QList>
#include <QDebug>
#include <QMutexLocker>
#include <iostream>
#include "TCPLink.h"
#include "LinkManager.h"
#include "QGC.h"
#include <QHostInfo>
#include <QSignalSpy>

/// @file
///     @brief TCP link type for SITL support
///
///     @author Don Gagne <don@thegagnes.com>

TCPLink::TCPLink(SharedLinkConfigurationPointer& config)
    : LinkInterface(config)
    , _tcpConfig(qobject_cast<TCPConfiguration*>(config.data()))
    , _socket(nullptr)
    , _socketIsConnected(false)
{
    Q_ASSERT(_tcpConfig);
    moveToThread(this);
}

TCPLink::~TCPLink()
{
    _disconnect();
    // Tell the thread to exit
    quit();
    // Wait for it to exit
    wait();
}

void TCPLink::run()
{
    _hardwareConnect();
    exec();
}

#ifdef TCPLINK_READWRITE_DEBUG
void TCPLink::_writeDebugBytes(const QByteArray data)
{
    QString bytes;
    QString ascii;
    for (int i=0, size = data.size(); i<size; i++)
    {
        unsigned char v = data[i];
        bytes.append(QString::asprintf("%02x ", v));
        if (data[i] > 31 && data[i] < 127)
        {
            ascii.append(data[i]);
        }
        else
        {
            ascii.append(219);
        }
    }
    qDebug() << "Sent" << size << "bytes to" << _tcpConfig->address().toString() << ":" << _tcpConfig->port() << "data:";
    qDebug() << bytes;
    qDebug() << "ASCII:" << ascii;
}
#endif

void TCPLink::_writeBytes(const QByteArray data)
{
#ifdef TCPLINK_READWRITE_DEBUG
    _writeDebugBytes(data);
#endif

    if (_socket) {
        _socket->write(data);
        emit bytesSent(this, data);
        _logOutputDataRate(data.size(), QDateTime::currentMSecsSinceEpoch());
    }
}

/**
 * @brief Read a number of bytes from the interface.
 *
 * @param data Pointer to the data byte array to write the bytes to
 * @param maxLength The maximum number of bytes to write
 **/
void TCPLink::readBytes()
{
    if (_socket) {
        qint64 byteCount = _socket->bytesAvailable();
        if (byteCount)
        {
            QByteArray buffer;
            buffer.resize(byteCount);
            _socket->read(buffer.data(), buffer.size());
            emit bytesReceived(this, buffer);
            _logInputDataRate(byteCount, QDateTime::currentMSecsSinceEpoch());
#ifdef TCPLINK_READWRITE_DEBUG
            writeDebugBytes(buffer.data(), buffer.size());
#endif
        }
    }
}

/**
 * @brief Disconnect the connection.
 *
 * @return True if connection has been disconnected, false if connection couldn't be disconnected.
 **/
void TCPLink::_disconnect(void)
{
    quit();
    wait();
    if (_socket) {
        _socketIsConnected = false;
        _socket->disconnectFromHost(); // Disconnect tcp
        _socket->waitForDisconnected();
        _socket->deleteLater(); // Make sure delete happens on correct thread
        _socket = nullptr;
        emit disconnected();
    }
}

/**
 * @brief Connect the connection.
 *
 * @return True if connection has been established, false if connection couldn't be established.
 **/
bool TCPLink::_connect(void)
{
    if (isRunning())
    {
        quit();
        wait();
    }
    start(HighPriority);
    return true;
}

bool TCPLink::_hardwareConnect()
{
    Q_ASSERT(_socket == nullptr);
    _socket = new QTcpSocket();

#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    QSignalSpy errorSpy(_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error));
#else
    QSignalSpy errorSpy(_socket, &QAbstractSocket::errorOccurred);
#endif

    _socket->connectToHost(_tcpConfig->address(), _tcpConfig->port());
    QObject::connect(_socket, &QTcpSocket::readyRead, this, &TCPLink::readBytes);

#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    QObject::connect(_socket,static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error),
                     this, &TCPLink::_socketError);
#else
    QObject::connect(_socket, &QAbstractSocket::errorOccurred, this, &TCPLink::_socketError);
#endif

    // Give the socket a second to connect to the other side otherwise error out
    if (!_socket->waitForConnected(1000))
    {
        // Whether a failed connection emits an error signal or not is platform specific.
        // So in cases where it is not emitted, we emit one ourselves.
        if (errorSpy.count() == 0) {
            emit communicationError(tr("Link Error"), tr("Error on link %1. Connection failed").arg(getName()));
        }
        delete _socket;
        _socket = nullptr;
        return false;
    }
    _socketIsConnected = true;
    emit connected();
    return true;
}

void TCPLink::_socketError(QAbstractSocket::SocketError socketError)
{
    Q_UNUSED(socketError);
    emit communicationError(tr("Link Error"), tr("Error on link %1. Error on socket: %2.").arg(getName()).arg(_socket->errorString()));
}

/**
 * @brief Check if connection is active.
 *
 * @return True if link is connected, false otherwise.
 **/
bool TCPLink::isConnected() const
{
    return _socketIsConnected;
}

QString TCPLink::getName() const
{
    return _tcpConfig->name();
}

qint64 TCPLink::getConnectionSpeed() const
{
    return 54000000; // 54 Mbit
}

qint64 TCPLink::getCurrentInDataRate() const
{
    return 0;
}

qint64 TCPLink::getCurrentOutDataRate() const
{
    return 0;
}

void TCPLink::waitForBytesWritten(int msecs)
{
    Q_ASSERT(_socket);
    _socket->waitForBytesWritten(msecs);
}

void TCPLink::waitForReadyRead(int msecs)
{
    Q_ASSERT(_socket);
    _socket->waitForReadyRead(msecs);
}

void TCPLink::_restartConnection()
{
    if(this->isConnected())
    {
        _disconnect();
        _connect();
    }
}

//--------------------------------------------------------------------------
//-- TCPConfiguration

static bool is_ip(const QString& address)
{
    int a,b,c,d;
    if (sscanf(address.toStdString().c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4
            && strcmp("::1", address.toStdString().c_str())) {
        return false;
    } else {
        return true;
    }
}

static QString get_ip_address(const QString& address)
{
    if(is_ip(address))
        return address;
    // Need to look it up
    QHostInfo info = QHostInfo::fromName(address);
    if (info.error() == QHostInfo::NoError)
    {
        QList<QHostAddress> hostAddresses = info.addresses();
        for (int i = 0; i < hostAddresses.size(); i++)
        {
            // Exclude all IPv6 addresses
            if (!hostAddresses.at(i).toString().contains(":"))
            {
                return hostAddresses.at(i).toString();
            }
        }
    }
    return {};
}

TCPConfiguration::TCPConfiguration(const QString& name) : LinkConfiguration(name)
{
    _port    = QGC_TCP_PORT;
    _address = QHostAddress::Any;
}

TCPConfiguration::TCPConfiguration(TCPConfiguration* source) : LinkConfiguration(source)
{
    _port    = source->port();
    _address = source->address();
}

void TCPConfiguration::copyFrom(LinkConfiguration *source)
{
    LinkConfiguration::copyFrom(source);
    auto* usource = qobject_cast<TCPConfiguration*>(source);
    Q_ASSERT(usource != nullptr);
    _port    = usource->port();
    _address = usource->address();
}

void TCPConfiguration::setPort(quint16 port)
{
    _port = port;
}

void TCPConfiguration::setAddress(const QHostAddress& address)
{
    _address = address;
}

void TCPConfiguration::setHost(const QString host)
{
    QString ipAdd = get_ip_address(host);
    if(ipAdd.isEmpty()) {
        qWarning() << "TCP:" << "Could not resolve host:" << host;
    } else {
        _address = QHostAddress(ipAdd);
    }
}

void TCPConfiguration::saveSettings(QSettings& settings, const QString& root)
{
    settings.beginGroup(root);
    settings.setValue("port", (int)_port);
    settings.setValue("host", address().toString());
    settings.endGroup();
}

void TCPConfiguration::loadSettings(QSettings& settings, const QString& root)
{
    settings.beginGroup(root);
    _port = (quint16)settings.value("port", QGC_TCP_PORT).toUInt();
    QString address = settings.value("host", _address.toString()).toString();
    _address = QHostAddress(address);
    settings.endGroup();
}

void TCPConfiguration::updateSettings()
{
    if(_link) {
        auto* ulink = qobject_cast<TCPLink*>(_link);
        if(ulink) {
            ulink->_restartConnection();
        }
    }
}
<|endoftext|>