<commit_before>/*************************************************************************
 *
 *  $RCSfile: xiroot.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2003-05-21 08:04:08 $
 *
 *  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 SC_XIROOT_HXX
#define SC_XIROOT_HXX

#ifndef SC_XLROOT_HXX
#include "xlroot.hxx"
#endif

// Global data ================================================================

class XclImpSst;
class XclImpPalette;
class XclImpFontBuffer;
class XclImpNumFmtBuffer;
class XclImpXFBuffer;
class XclImpXFIndexBuffer;
class XclImpTabIdBuffer;
class XclImpLinkManager;
class XclImpObjectManager;
class XclImpWebQueryBuffer;

/** Stores global buffers and data needed for Excel import filter. */
struct XclImpRootData : public XclRootData
{
    typedef ::std::auto_ptr< XclImpSst >            XclImpSstPtr;
    typedef ::std::auto_ptr< XclImpPalette >        XclImpPalettePtr;
    typedef ::std::auto_ptr< XclImpFontBuffer >     XclImpFontBufferPtr;
    typedef ::std::auto_ptr< XclImpNumFmtBuffer >   XclImpNumFmtBufferPtr;
    typedef ::std::auto_ptr< XclImpXFBuffer >       XclImpXFBufferPtr;
    typedef ::std::auto_ptr< XclImpXFIndexBuffer >  XclImpXFIndexBufferPtr;
    typedef ::std::auto_ptr< XclImpTabIdBuffer >    XclImpTabIdBufferPtr;
    typedef ::std::auto_ptr< XclImpLinkManager >    XclImpLinkManagerPtr;
    typedef ::std::auto_ptr< XclImpObjectManager >  XclImpObjectManagerPtr;
    typedef ::std::auto_ptr< XclImpWebQueryBuffer > XclImpWebQueryBufferPtr;

    XclImpSstPtr                mpSst;              /// The shared string table.

    XclImpPalettePtr            mpPalette;          /// The color buffer.
    XclImpFontBufferPtr         mpFontBuffer;       /// All fonts in the file.
    XclImpNumFmtBufferPtr       mpNumFmtBuffer;     /// All number formats in the file.
    XclImpXFBufferPtr           mpXFBuffer;         /// All XF record data in the file.
    XclImpXFIndexBufferPtr      mpXFIndexBuffer;    /// Buffer of XF indexes in a sheet.

    XclImpTabIdBufferPtr        mpTabIdBuffer;      /// Sheet creation order list.
    XclImpLinkManagerPtr        mpLinkManager;      /// Manager for internal/external links.

    XclImpObjectManagerPtr      mpObjManager;       /// All drawing objects.
    XclImpWebQueryBufferPtr     mpWebQBuffer;       /// All web queries.

    explicit                    XclImpRootData(
                                    XclBiff eBiff,
                                    ScDocument& rDocument,
                                    const String& rBasePath,
                                    CharSet eCharSet );
    virtual                     ~XclImpRootData();
};

// ----------------------------------------------------------------------------

class ExcelToSc;

/** Access to global data from other classes. */
class XclImpRoot : public XclRoot
{
private:
    mutable XclImpRootData&     mrImpData;      /// Reference to the global import data struct.

public:
                                XclImpRoot( const XclImpRoot& rRoot );

    XclImpRoot&                 operator=( const XclImpRoot& rRoot );

    /** Returns this root instance - for code readability in derived classes. */
    inline const XclImpRoot&    GetRoot() const { return *this; }

    /** Returns the shared string table. */
    XclImpSst&                  GetSst() const;

    /** Returns the color buffer. */
    XclImpPalette&              GetPalette() const;
    /** Returns the font buffer. */
    XclImpFontBuffer&           GetFontBuffer() const;
    /** Returns the number format buffer. */
    XclImpNumFmtBuffer&         GetNumFmtBuffer() const;
    /** Returns the cell formatting attributes buffer. */
    XclImpXFBuffer&             GetXFBuffer() const;
    /** Returns the buffer of XF indexes for a sheet. */
    XclImpXFIndexBuffer&        GetXFIndexBuffer() const;

    /** Returns the buffer that contains the sheet creation order. */
    XclImpTabIdBuffer&          GetTabIdBuffer() const;
    /** Returns the link manager. */
    XclImpLinkManager&          GetLinkManager() const;

    /** Returns the drawing object manager. */
    XclImpObjectManager&        GetObjectManager() const;
    /** Returns the web query buffer. */
    XclImpWebQueryBuffer&       GetWebQueryBuffer() const;

    /** Returns the formula converter. */
    ExcelToSc&                  GetFmlaConverter() const;

    /** Returns the Calc add-in function name for an Excel function name. */
    String                      GetScAddInName( const String& rXclName ) const;

    /** Checks if the passed cell address is a valid Calc cell position.
        @descr  See XclRoot::CheckCellAddress for details. */
    bool                        CheckCellAddress( const ScAddress& rPos ) const;
    /** Checks and eventually crops the cell range to valid Calc dimensions.
        @descr  See XclRoot::CheckCellRange for details. */
    bool                        CheckCellRange( ScRange& rRange ) const;
    /** Checks and eventually crops the cell ranges to valid Calc dimensions.
        @descr  See XclRoot::CheckCellRangeList for details. */
    void                        CheckCellRangeList( ScRangeList& rRanges ) const;

protected:
    explicit                    XclImpRoot( XclImpRootData& rImpRootData );

    /** Sets the BIFF version and BOF/EOF block type. */
    void                        SetBiff( XclBiff eBiff );
};

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

#endif

<commit_msg>INTEGRATION: CWS filtertracer01 (1.4.36); FILE MERGED 2003/07/15 12:05:57 dr 1.4.36.1: filter tracer<commit_after>/*************************************************************************
 *
 *  $RCSfile: xiroot.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2003-08-07 15:30:58 $
 *
 *  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 SC_XIROOT_HXX
#define SC_XIROOT_HXX

#ifndef SC_XLROOT_HXX
#include "xlroot.hxx"
#endif

// Global data ================================================================

class XclImpSst;
class XclImpPalette;
class XclImpFontBuffer;
class XclImpNumFmtBuffer;
class XclImpXFBuffer;
class XclImpXFIndexBuffer;
class XclImpTabIdBuffer;
class XclImpLinkManager;
class XclImpObjectManager;
class XclImpWebQueryBuffer;

/** Stores global buffers and data needed for Excel import filter. */
struct XclImpRootData : public XclRootData
{
    typedef ::std::auto_ptr< XclImpSst >            XclImpSstPtr;
    typedef ::std::auto_ptr< XclImpPalette >        XclImpPalettePtr;
    typedef ::std::auto_ptr< XclImpFontBuffer >     XclImpFontBufferPtr;
    typedef ::std::auto_ptr< XclImpNumFmtBuffer >   XclImpNumFmtBufferPtr;
    typedef ::std::auto_ptr< XclImpXFBuffer >       XclImpXFBufferPtr;
    typedef ::std::auto_ptr< XclImpXFIndexBuffer >  XclImpXFIndexBufferPtr;
    typedef ::std::auto_ptr< XclImpTabIdBuffer >    XclImpTabIdBufferPtr;
    typedef ::std::auto_ptr< XclImpLinkManager >    XclImpLinkManagerPtr;
    typedef ::std::auto_ptr< XclImpObjectManager >  XclImpObjectManagerPtr;
    typedef ::std::auto_ptr< XclImpWebQueryBuffer > XclImpWebQueryBufferPtr;

    XclImpSstPtr                mpSst;              /// The shared string table.

    XclImpPalettePtr            mpPalette;          /// The color buffer.
    XclImpFontBufferPtr         mpFontBuffer;       /// All fonts in the file.
    XclImpNumFmtBufferPtr       mpNumFmtBuffer;     /// All number formats in the file.
    XclImpXFBufferPtr           mpXFBuffer;         /// All XF record data in the file.
    XclImpXFIndexBufferPtr      mpXFIndexBuffer;    /// Buffer of XF indexes in a sheet.

    XclImpTabIdBufferPtr        mpTabIdBuffer;      /// Sheet creation order list.
    XclImpLinkManagerPtr        mpLinkManager;      /// Manager for internal/external links.

    XclImpObjectManagerPtr      mpObjManager;       /// All drawing objects.
    XclImpWebQueryBufferPtr     mpWebQBuffer;       /// All web queries.

    explicit                    XclImpRootData(
                                    XclBiff eBiff,
                                    ScDocument& rDocument,
                                    const String& rDocUrl,
                                    CharSet eCharSet );
    virtual                     ~XclImpRootData();
};

// ----------------------------------------------------------------------------

class ExcelToSc;

/** Access to global data from other classes. */
class XclImpRoot : public XclRoot
{
private:
    mutable XclImpRootData&     mrImpData;      /// Reference to the global import data struct.

public:
                                XclImpRoot( const XclImpRoot& rRoot );

    XclImpRoot&                 operator=( const XclImpRoot& rRoot );

    /** Returns this root instance - for code readability in derived classes. */
    inline const XclImpRoot&    GetRoot() const { return *this; }

    /** Returns the shared string table. */
    XclImpSst&                  GetSst() const;

    /** Returns the color buffer. */
    XclImpPalette&              GetPalette() const;
    /** Returns the font buffer. */
    XclImpFontBuffer&           GetFontBuffer() const;
    /** Returns the number format buffer. */
    XclImpNumFmtBuffer&         GetNumFmtBuffer() const;
    /** Returns the cell formatting attributes buffer. */
    XclImpXFBuffer&             GetXFBuffer() const;
    /** Returns the buffer of XF indexes for a sheet. */
    XclImpXFIndexBuffer&        GetXFIndexBuffer() const;

    /** Returns the buffer that contains the sheet creation order. */
    XclImpTabIdBuffer&          GetTabIdBuffer() const;
    /** Returns the link manager. */
    XclImpLinkManager&          GetLinkManager() const;

    /** Returns the drawing object manager. */
    XclImpObjectManager&        GetObjectManager() const;
    /** Returns the web query buffer. */
    XclImpWebQueryBuffer&       GetWebQueryBuffer() const;

    /** Returns the formula converter. */
    ExcelToSc&                  GetFmlaConverter() const;

    /** Returns the Calc add-in function name for an Excel function name. */
    String                      GetScAddInName( const String& rXclName ) const;

    /** Checks if the passed cell address is a valid Calc cell position.
        @descr  See XclRoot::CheckCellAddress for details. */
    bool                        CheckCellAddress( const ScAddress& rPos ) const;
    /** Checks and eventually crops the cell range to valid Calc dimensions.
        @descr  See XclRoot::CheckCellRange for details. */
    bool                        CheckCellRange( ScRange& rRange ) const;
    /** Checks and eventually crops the cell ranges to valid Calc dimensions.
        @descr  See XclRoot::CheckCellRangeList for details. */
    void                        CheckCellRangeList( ScRangeList& rRanges ) const;

protected:
    explicit                    XclImpRoot( XclImpRootData& rImpRootData );

    /** Sets the BIFF version and BOF/EOF block type. */
    void                        SetBiff( XclBiff eBiff );
};

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

#endif

<|endoftext|>


<commit_before>#include <algorithm>
#include <cryptopp/dh.h>
#include "Log.h"
#include "util.h"
#include "NetDb.h"
#include "Destination.h"

namespace i2p
{
namespace client
{
	ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic):
		m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
		m_Keys (keys), m_LeaseSet (nullptr), m_IsPublic (isPublic), m_PublishReplyToken (0),
		m_DatagramDestination (nullptr), m_PublishConfirmationTimer (nullptr)
	{
		CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
		dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
		m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
		if (m_IsPublic)
			LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
		m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
	}

	ClientDestination::~ClientDestination ()
	{
		Stop ();
		for (auto it: m_RemoteLeaseSets)
			delete it.second;
		if (m_Pool)
			i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
		delete m_LeaseSet;
		delete m_Work;
		delete m_PublishConfirmationTimer;
		delete m_Service;
		delete m_StreamingDestination;
		delete m_DatagramDestination;
	}

	void ClientDestination::Run ()
	{
		if (m_Service)
			m_Service->run ();
	}

	void ClientDestination::Start ()
	{
		m_Service = new boost::asio::io_service;
		m_PublishConfirmationTimer = new boost::asio::deadline_timer (*m_Service);
		m_Work = new boost::asio::io_service::work (*m_Service);
		m_Pool->SetActive (true);
		m_IsRunning = true;
		m_Thread = new std::thread (std::bind (&ClientDestination::Run, this));
		m_StreamingDestination->Start ();
	}

	void ClientDestination::Stop ()
	{
		m_StreamingDestination->Stop ();
		if (m_DatagramDestination)
		{
			auto d = m_DatagramDestination;
			m_DatagramDestination = nullptr;
			delete d;
		}
		if (m_Pool)
			i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
		m_IsRunning = false;
		delete m_PublishConfirmationTimer;
		m_PublishConfirmationTimer = nullptr;
		if (m_Service)
			m_Service->stop ();
		if (m_Thread)
		{
			m_Thread->join ();
			delete m_Thread;
			m_Thread = 0;
		}
		delete m_Work; m_Work = nullptr;
		delete m_Service; m_Service = nullptr;
	}

	const i2p::data::LeaseSet * ClientDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
	{
		auto it = m_RemoteLeaseSets.find (ident);
		if (it != m_RemoteLeaseSets.end ())
		{
			if (it->second->HasNonExpiredLeases ())
				return it->second;
			else
			{
				LogPrint ("All leases of remote LeaseSet expired. Request it");
				i2p::data::netdb.RequestDestination (ident, true, m_Pool);
			}
		}
		else
		{
			auto ls = i2p::data::netdb.FindLeaseSet (ident);
			if (ls)
			{
				ls = new i2p::data::LeaseSet (*ls);
				m_RemoteLeaseSets[ident] = ls;
				return ls;
			}
		}
		return nullptr;
	}

	const i2p::data::LeaseSet * ClientDestination::GetLeaseSet ()
	{
		if (!m_Pool) return nullptr;
		if (!m_LeaseSet)
			UpdateLeaseSet ();
		return m_LeaseSet;
	}

	void ClientDestination::UpdateLeaseSet ()
	{
		auto newLeaseSet = new i2p::data::LeaseSet (*m_Pool);
		if (!m_LeaseSet)
			m_LeaseSet = newLeaseSet;
		else
		{
			// TODO: implement it better
			*m_LeaseSet = *newLeaseSet;
			delete newLeaseSet;
		}
	}

	void ClientDestination::ProcessGarlicMessage (I2NPMessage * msg)
	{
		if (m_Service)
			m_Service->post (std::bind (&ClientDestination::HandleGarlicMessage, this, msg));
	}

	void ClientDestination::ProcessDeliveryStatusMessage (I2NPMessage * msg)
	{
		if (m_Service)
			m_Service->post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, this, msg));
	}

	void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, i2p::tunnel::InboundTunnel * from)
	{
		I2NPHeader * header = (I2NPHeader *)buf;
		switch (header->typeID)
		{
			case eI2NPData:
				HandleDataMessage (buf + sizeof (I2NPHeader), be16toh (header->size));
			break;
			case eI2NPDatabaseStore:
				HandleDatabaseStoreMessage (buf + sizeof (I2NPHeader), be16toh (header->size));
				i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); // TODO: remove
			break;
			default:
				i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
		}
	}

	void ClientDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
	{
		I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)buf;
		size_t offset = sizeof (I2NPDatabaseStoreMsg);
		if (msg->replyToken) // TODO:
			offset += 36;
		if (msg->type == 1) // LeaseSet
		{
			LogPrint (eLogDebug, "Remote LeaseSet");
			auto it = m_RemoteLeaseSets.find (msg->key);
			if (it != m_RemoteLeaseSets.end ())
			{
				it->second->Update (buf + offset, len - offset);
				LogPrint (eLogDebug, "Remote LeaseSet updated");
			}
			else
			{
				LogPrint (eLogDebug, "New remote LeaseSet added");
				m_RemoteLeaseSets[msg->key] = new i2p::data::LeaseSet (buf + offset, len - offset);
			}
		}
		else
			LogPrint (eLogError, "Unexpected client's DatabaseStore type ", msg->type, ". Dropped");
	}

	void ClientDestination::HandleDeliveryStatusMessage (I2NPMessage * msg)
	{
		I2NPDeliveryStatusMsg * deliveryStatus = (I2NPDeliveryStatusMsg *)msg->GetPayload ();
		uint32_t msgID = be32toh (deliveryStatus->msgID);
		if (msgID == m_PublishReplyToken)
		{
			LogPrint (eLogDebug, "Publishing confirmed");
			m_PublishReplyToken = 0;
			i2p::DeleteI2NPMessage (msg);
		}
		else
			i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
	}

	void ClientDestination::SetLeaseSetUpdated ()
	{
		i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
		UpdateLeaseSet ();
		if (m_IsPublic)
			Publish ();
	}

	void ClientDestination::Publish ()
	{
		if (!m_LeaseSet || !m_Pool)
		{
			LogPrint (eLogError, "Can't publish non-existing LeaseSet");
			return;
		}
		if (m_PublishReplyToken)
		{
			LogPrint (eLogInfo, "Publishing is pending");
			return;
		}
		auto outbound = m_Pool->GetNextOutboundTunnel ();
		if (!outbound)
		{
			LogPrint ("Can't publish LeaseSet. No outbound tunnels");
			return;
		}
		std::set<i2p::data::IdentHash> excluded;
		auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), excluded);
		if (!floodfill)
		{
			LogPrint ("Can't publish LeaseSet. No floodfills found");
			return;
		}
		LogPrint (eLogDebug, "Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
		m_PublishReplyToken = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
		auto msg = WrapMessage (*floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken));
		if (m_PublishConfirmationTimer)
		{
			m_PublishConfirmationTimer->expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
			m_PublishConfirmationTimer->async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer,
				this, std::placeholders::_1));
		}
		else
		{
			LogPrint (eLogWarning, "Destination's thread is not running");
			m_PublishReplyToken = 0;
		}
		outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
	}

	void ClientDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode)
	{
		if (ecode != boost::asio::error::operation_aborted)
		{
			if (m_PublishReplyToken)
			{
				LogPrint (eLogWarning, "Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT,  "seconds. Try again");
				m_PublishReplyToken = 0;
				Publish ();
			}
		}
	}

	void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
	{
		uint32_t length = be32toh (*(uint32_t *)buf);
		buf += 4;
		// we assume I2CP payload
		switch (buf[9])
		{
			case PROTOCOL_TYPE_STREAMING:
				// streaming protocol
				if (m_StreamingDestination)
					m_StreamingDestination->HandleDataMessagePayload (buf, length);
				else
					LogPrint ("Missing streaming destination");
			break;
			case PROTOCOL_TYPE_DATAGRAM:
				// datagram protocol
				if (m_DatagramDestination)
					m_DatagramDestination->HandleDataMessagePayload (buf, length);
				else
					LogPrint ("Missing streaming destination");
			break;
			default:
				LogPrint ("Data: unexpected protocol ", buf[9]);
		}
	}

	std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::LeaseSet& remote, int port)
	{
		if (m_StreamingDestination)
			return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
		return nullptr;
	}

	void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
	{
		if (m_StreamingDestination)
			m_StreamingDestination->SetAcceptor (acceptor);
	}

	void ClientDestination::StopAcceptingStreams ()
	{
		if (m_StreamingDestination)
			m_StreamingDestination->ResetAcceptor ();
	}

	bool ClientDestination::IsAcceptingStreams () const
	{
		if (m_StreamingDestination)
			return m_StreamingDestination->IsAcceptorSet ();
		return false;
	}

	i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
	{
		if (!m_DatagramDestination)
			m_DatagramDestination = new i2p::datagram::DatagramDestination (*this);
		return m_DatagramDestination;
	}
}
}
<commit_msg>fixed crash<commit_after>#include <algorithm>
#include <cryptopp/dh.h>
#include "Log.h"
#include "util.h"
#include "NetDb.h"
#include "Destination.h"

namespace i2p
{
namespace client
{
	ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic):
		m_IsRunning (false), m_Thread (nullptr), m_Service (nullptr), m_Work (nullptr),
		m_Keys (keys), m_LeaseSet (nullptr), m_IsPublic (isPublic), m_PublishReplyToken (0),
		m_DatagramDestination (nullptr), m_PublishConfirmationTimer (nullptr)
	{
		CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg);
		dh.GenerateKeyPair(i2p::context.GetRandomNumberGenerator (), m_EncryptionPrivateKey, m_EncryptionPublicKey);
		m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (*this, 3); // 3-hops tunnel
		if (m_IsPublic)
			LogPrint ("Local address ", GetIdentHash ().ToBase32 (), ".b32.i2p created");
		m_StreamingDestination = new i2p::stream::StreamingDestination (*this); // TODO:
	}

	ClientDestination::~ClientDestination ()
	{
		Stop ();
		for (auto it: m_RemoteLeaseSets)
			delete it.second;
		if (m_Pool)
			i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
		delete m_LeaseSet;
		delete m_Work;
		delete m_PublishConfirmationTimer;
		delete m_Service;
		delete m_StreamingDestination;
		delete m_DatagramDestination;
	}

	void ClientDestination::Run ()
	{
		if (m_Service)
			m_Service->run ();
	}

	void ClientDestination::Start ()
	{
		m_Service = new boost::asio::io_service;
		m_PublishConfirmationTimer = new boost::asio::deadline_timer (*m_Service);
		m_Work = new boost::asio::io_service::work (*m_Service);
		m_Pool->SetActive (true);
		m_IsRunning = true;
		m_Thread = new std::thread (std::bind (&ClientDestination::Run, this));
		m_StreamingDestination->Start ();
	}

	void ClientDestination::Stop ()
	{
		m_StreamingDestination->Stop ();
		if (m_DatagramDestination)
		{
			auto d = m_DatagramDestination;
			m_DatagramDestination = nullptr;
			delete d;
		}
		if (m_Pool)
			i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
		m_IsRunning = false;
		if (m_Service)
			m_Service->stop ();
		if (m_Thread)
		{
			m_Thread->join ();
			delete m_Thread;
			m_Thread = 0;
		}
		delete m_PublishConfirmationTimer; m_PublishConfirmationTimer = nullptr;
		delete m_Work; m_Work = nullptr;
		delete m_Service; m_Service = nullptr;
	}

	const i2p::data::LeaseSet * ClientDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
	{
		auto it = m_RemoteLeaseSets.find (ident);
		if (it != m_RemoteLeaseSets.end ())
		{
			if (it->second->HasNonExpiredLeases ())
				return it->second;
			else
			{
				LogPrint ("All leases of remote LeaseSet expired. Request it");
				i2p::data::netdb.RequestDestination (ident, true, m_Pool);
			}
		}
		else
		{
			auto ls = i2p::data::netdb.FindLeaseSet (ident);
			if (ls)
			{
				ls = new i2p::data::LeaseSet (*ls);
				m_RemoteLeaseSets[ident] = ls;
				return ls;
			}
		}
		return nullptr;
	}

	const i2p::data::LeaseSet * ClientDestination::GetLeaseSet ()
	{
		if (!m_Pool) return nullptr;
		if (!m_LeaseSet)
			UpdateLeaseSet ();
		return m_LeaseSet;
	}

	void ClientDestination::UpdateLeaseSet ()
	{
		auto newLeaseSet = new i2p::data::LeaseSet (*m_Pool);
		if (!m_LeaseSet)
			m_LeaseSet = newLeaseSet;
		else
		{
			// TODO: implement it better
			*m_LeaseSet = *newLeaseSet;
			delete newLeaseSet;
		}
	}

	void ClientDestination::ProcessGarlicMessage (I2NPMessage * msg)
	{
		if (m_Service)
			m_Service->post (std::bind (&ClientDestination::HandleGarlicMessage, this, msg));
	}

	void ClientDestination::ProcessDeliveryStatusMessage (I2NPMessage * msg)
	{
		if (m_Service)
			m_Service->post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, this, msg));
	}

	void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, i2p::tunnel::InboundTunnel * from)
	{
		I2NPHeader * header = (I2NPHeader *)buf;
		switch (header->typeID)
		{
			case eI2NPData:
				HandleDataMessage (buf + sizeof (I2NPHeader), be16toh (header->size));
			break;
			case eI2NPDatabaseStore:
				HandleDatabaseStoreMessage (buf + sizeof (I2NPHeader), be16toh (header->size));
				i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); // TODO: remove
			break;
			default:
				i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
		}
	}

	void ClientDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
	{
		I2NPDatabaseStoreMsg * msg = (I2NPDatabaseStoreMsg *)buf;
		size_t offset = sizeof (I2NPDatabaseStoreMsg);
		if (msg->replyToken) // TODO:
			offset += 36;
		if (msg->type == 1) // LeaseSet
		{
			LogPrint (eLogDebug, "Remote LeaseSet");
			auto it = m_RemoteLeaseSets.find (msg->key);
			if (it != m_RemoteLeaseSets.end ())
			{
				it->second->Update (buf + offset, len - offset);
				LogPrint (eLogDebug, "Remote LeaseSet updated");
			}
			else
			{
				LogPrint (eLogDebug, "New remote LeaseSet added");
				m_RemoteLeaseSets[msg->key] = new i2p::data::LeaseSet (buf + offset, len - offset);
			}
		}
		else
			LogPrint (eLogError, "Unexpected client's DatabaseStore type ", msg->type, ". Dropped");
	}

	void ClientDestination::HandleDeliveryStatusMessage (I2NPMessage * msg)
	{
		I2NPDeliveryStatusMsg * deliveryStatus = (I2NPDeliveryStatusMsg *)msg->GetPayload ();
		uint32_t msgID = be32toh (deliveryStatus->msgID);
		if (msgID == m_PublishReplyToken)
		{
			LogPrint (eLogDebug, "Publishing confirmed");
			m_PublishReplyToken = 0;
			i2p::DeleteI2NPMessage (msg);
		}
		else
			i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
	}

	void ClientDestination::SetLeaseSetUpdated ()
	{
		i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
		UpdateLeaseSet ();
		if (m_IsPublic)
			Publish ();
	}

	void ClientDestination::Publish ()
	{
		if (!m_LeaseSet || !m_Pool)
		{
			LogPrint (eLogError, "Can't publish non-existing LeaseSet");
			return;
		}
		if (m_PublishReplyToken)
		{
			LogPrint (eLogInfo, "Publishing is pending");
			return;
		}
		auto outbound = m_Pool->GetNextOutboundTunnel ();
		if (!outbound)
		{
			LogPrint ("Can't publish LeaseSet. No outbound tunnels");
			return;
		}
		std::set<i2p::data::IdentHash> excluded;
		auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), excluded);
		if (!floodfill)
		{
			LogPrint ("Can't publish LeaseSet. No floodfills found");
			return;
		}
		LogPrint (eLogDebug, "Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
		m_PublishReplyToken = i2p::context.GetRandomNumberGenerator ().GenerateWord32 ();
		auto msg = WrapMessage (*floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken));
		if (m_PublishConfirmationTimer)
		{
			m_PublishConfirmationTimer->expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
			m_PublishConfirmationTimer->async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer,
				this, std::placeholders::_1));
		}
		else
		{
			LogPrint (eLogWarning, "Destination's thread is not running");
			m_PublishReplyToken = 0;
		}
		outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
	}

	void ClientDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode)
	{
		if (ecode != boost::asio::error::operation_aborted)
		{
			if (m_PublishReplyToken)
			{
				LogPrint (eLogWarning, "Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT,  "seconds. Try again");
				m_PublishReplyToken = 0;
				Publish ();
			}
		}
	}

	void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
	{
		uint32_t length = be32toh (*(uint32_t *)buf);
		buf += 4;
		// we assume I2CP payload
		switch (buf[9])
		{
			case PROTOCOL_TYPE_STREAMING:
				// streaming protocol
				if (m_StreamingDestination)
					m_StreamingDestination->HandleDataMessagePayload (buf, length);
				else
					LogPrint ("Missing streaming destination");
			break;
			case PROTOCOL_TYPE_DATAGRAM:
				// datagram protocol
				if (m_DatagramDestination)
					m_DatagramDestination->HandleDataMessagePayload (buf, length);
				else
					LogPrint ("Missing streaming destination");
			break;
			default:
				LogPrint ("Data: unexpected protocol ", buf[9]);
		}
	}

	std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::LeaseSet& remote, int port)
	{
		if (m_StreamingDestination)
			return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
		return nullptr;
	}

	void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
	{
		if (m_StreamingDestination)
			m_StreamingDestination->SetAcceptor (acceptor);
	}

	void ClientDestination::StopAcceptingStreams ()
	{
		if (m_StreamingDestination)
			m_StreamingDestination->ResetAcceptor ();
	}

	bool ClientDestination::IsAcceptingStreams () const
	{
		if (m_StreamingDestination)
			return m_StreamingDestination->IsAcceptorSet ();
		return false;
	}

	i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
	{
		if (!m_DatagramDestination)
			m_DatagramDestination = new i2p::datagram::DatagramDestination (*this);
		return m_DatagramDestination;
	}
}
}
<|endoftext|>


<commit_before>#include "ChLcpSolverParallel.h"
#include "math/ChThrustLinearAlgebra.h"

using namespace chrono;

//// TODO:  For now, this is hard-coded for Hunt-Crossley with Simple Sliding Friction.
__host__ __device__
void function_CalcContactForces(int&       index,           // index of this contact pair
                                real&      dT,              // integration time step
                                real3*     pos,             // body positions
                                real4*     rot,             // body orientations
                                real3*     vel,             // body linear velocity (global frame)
                                real3*     omg,             // body angular velocity (local frame)
                                real2*     elastic_moduli,  // Young's modulus (per body)
                                real*      mu,              // coefficient of friction (per body)
                                real*      alpha,           // disipation coefficient (per body)
                                real*      cr,              // coefficient of restitution (per body)
                                real*      cohesion,        // cohesion force (per body)
                                int2*      body_id,         // body IDs (per contact)
                                real3*     pt1,             // point on shape 1 (per contact)
                                real3*     pt2,             // point on shape 2 (per contact)
                                real3*     normal,          // contact normal (per contact)
                                real*      depth,           // penetration depth (per contact)
                                real*      eff_radius,      // effective contact radius (per contact)
                                int*       ext_body_id,     // [output] body IDs (two per contact)
                                real3*     ext_body_force,  // [output] body force (two per contact)
                                real3*     ext_body_torque) // [output] body torque (two per contact)
{
	// Identify the two bodies in contact.
	int body1 = body_id[index].x;
	int body2 = body_id[index].y;

	// If the two contact shapes are actually separated, set zero forces and torques
	if (depth[index] >= 0) {
		ext_body_id[2*index] = body1;
		ext_body_id[2*index+1] = body2;
		ext_body_force[2*index] = ZERO_VECTOR;
		ext_body_force[2*index+1] = ZERO_VECTOR;
		ext_body_torque[2*index] = ZERO_VECTOR;
		ext_body_torque[2*index+1] = ZERO_VECTOR;

		return;
	}

	// Kinematic information
	// ---------------------

	// Express contact point locations in local frames
	//   s' = At * s = At * (rP - r)
	real3 pt1_loc = TransformParentToLocal(pos[body1], rot[body1], pt1[index]);
	real3 pt2_loc = TransformParentToLocal(pos[body2], rot[body2], pt2[index]);

	// Calculate relative velocity (in global frame)
	//   vP = v + omg x s = v + A * (omg' x s')
	real3 vel1 = vel[body1] + quatRotateMat(cross(omg[body1], pt1_loc), rot[body1]);
	real3 vel2 = vel[body2] + quatRotateMat(cross(omg[body2], pt2_loc), rot[body2]);
	real3 relvel = vel2 - vel1;
	real  relvel_n_mag = dot(relvel, normal[index]);
	real3 relvel_n = relvel_n_mag * normal[index];
	real3 relvel_t = relvel - relvel_n;
	real  relvel_t_mag = length(relvel_t);

	// Calculate composite material properties
	// ---------------------------------------

	real Y1 = elastic_moduli[body1].x;
	real Y2 = elastic_moduli[body2].x;
	real nu1 = elastic_moduli[body1].y;
	real nu2 = elastic_moduli[body2].y;
	real inv_E = (1 - nu1 * nu1) / Y1 + (1 - nu2 * nu2) / Y2;
	real inv_G = 2 * (2 + nu1) * (1 - nu1) / Y1 + 2 * (2 + nu2) * (1 - nu2) / Y2;

	real E_eff = 1 / inv_E;
	real G_eff = 1 / inv_G;

	real mu_eff = min(mu[body1], mu[body2]);
	//real cr_eff = (cr[body1] + cr[body2]) / 2;
	real alpha_eff = (alpha[body1] + alpha[body2]) / 2;

	real cohesion_eff = min(cohesion[body1], cohesion[body2]);

	// Contact force
	// -------------

	// Normal force: Hunt-Crossley
	real delta = -depth[index];
	real kn = (4.0 / 3) * E_eff * sqrt(eff_radius[index]);
	real forceN_elastic = kn * delta * sqrt(delta);
	real forceN_dissipation = 1.5 * alpha_eff * forceN_elastic * relvel_n_mag;
	real forceN = forceN_elastic - forceN_dissipation;

	// Cohesion force
	forceN -= cohesion_eff;

	real3 force = forceN * normal[index];

	// Tangential force: Simple Coulomb Sliding
	if (relvel_t_mag > 1e-4) {
		real forceT = mu_eff * abs(forceN);

		force -= (forceT / relvel_t_mag) * relvel_t;
	}

	// Body forces (in global frame) & torques (in local frame)
	// --------------------------------------------------------

	// Convert force into the local body frames and calculate induced torques
	//    n' = s' x F' = s' x (A*F)
	real3 torque1_loc = cross(pt1_loc, quatRotateMatT(force, rot[body1]));
	real3 torque2_loc = cross(pt2_loc, quatRotateMatT(force, rot[body2]));

	// Store body forces and torques
	ext_body_id[2*index]   = body1;
	ext_body_id[2*index+1] = body2;
	ext_body_force[2*index]   = -force;
	ext_body_force[2*index+1] =  force;
	ext_body_torque[2*index]   = -torque1_loc;
	ext_body_torque[2*index+1] =  torque2_loc;
}

void ChLcpSolverParallelDEM::host_CalcContactForces(custom_vector<int>&   ext_body_id,
                                                    custom_vector<real3>& ext_body_force,
                                                    custom_vector<real3>& ext_body_torque)
{
#pragma omp parallel for
	for (int index = 0; index < data_container->number_of_rigid_rigid; index++) {
		function_CalcContactForces(
			index,
			step_size,
			data_container->host_data.pos_data.data(),
			data_container->host_data.rot_data.data(),
			data_container->host_data.vel_data.data(),
			data_container->host_data.omg_data.data(),
			data_container->host_data.elastic_moduli.data(),
			data_container->host_data.mu.data(),
			data_container->host_data.alpha.data(),
			data_container->host_data.cr.data(),
			data_container->host_data.cohesion_data.data(),
			data_container->host_data.bids_rigid_rigid.data(),
			data_container->host_data.cpta_rigid_rigid.data(),
			data_container->host_data.cptb_rigid_rigid.data(),
			data_container->host_data.norm_rigid_rigid.data(),
			data_container->host_data.dpth_rigid_rigid.data(),
			data_container->host_data.erad_rigid_rigid.data(),
			ext_body_id.data(),
			ext_body_force.data(),
			ext_body_torque.data());
	}
}

void ChLcpSolverParallelDEM::host_AddContactForces(uint                        ct_body_count,
                                                   const custom_vector<int>&   ct_body_id,
                                                   const custom_vector<real3>& ct_body_force,
                                                   const custom_vector<real3>& ct_body_torque)
{
#pragma omp parallel for
	for (int index = 0; index < ct_body_count; index++) {
		data_container->host_data.frc_data[ct_body_id[index]] += step_size * ct_body_force[index];
		data_container->host_data.trq_data[ct_body_id[index]] += step_size * ct_body_torque[index];
	}
}

void ChLcpSolverParallelDEM::ProcessContacts()
{
	// 0. If the narrowphase collision detection does not set the effective contact
	//    radius, fill it with the value 1.
	if (!data_container->erad_is_set)
		data_container->host_data.erad_rigid_rigid.resize(data_container->number_of_rigid_rigid, 1.0);

	// 1. Calculate contact forces and torques - per contact basis
	//    For each pair of contact shapes that overlap, we calculate and store
	//    the IDs of the two corresponding bodies and the resulting contact
	//    forces and torques on the two bodies.
	custom_vector<int>   ext_body_id(2 * data_container->number_of_rigid_rigid);
	custom_vector<real3> ext_body_force(2 * data_container->number_of_rigid_rigid);
	custom_vector<real3> ext_body_torque(2 * data_container->number_of_rigid_rigid);

	host_CalcContactForces(ext_body_id, ext_body_force, ext_body_torque);

	// 2. Calculate contact forces and torques - per body basis
	//    Accumulate the contact forces and torques for all bodies that are involved
	//    in at least one contact, by reducing the contact forces and torques from
	//    all contacts these bodies are involved in. The number of bodies that
	//    experience at least one contact is calculated in 'ct_body_count'.
	thrust::sort_by_key(
		ext_body_id.begin(), ext_body_id.end(),
		thrust::make_zip_iterator(thrust::make_tuple(ext_body_force.begin(), ext_body_torque.begin())));

	custom_vector<int>   ct_body_id(data_container->number_of_rigid);
	custom_vector<real3> ct_body_force(data_container->number_of_rigid);
	custom_vector<real3> ct_body_torque(data_container->number_of_rigid);

	// Reduce contact forces from all contacts and count bodies currently involved in contact
	uint ct_body_count = thrust::reduce_by_key(
		ext_body_id.begin(),
		ext_body_id.end(),
		thrust::make_zip_iterator(thrust::make_tuple(ext_body_force.begin(), ext_body_torque.begin())),
		ct_body_id.begin(),
		thrust::make_zip_iterator(thrust::make_tuple(ct_body_force.begin(), ct_body_torque.begin())),
		thrust::equal_to<int>(),
		sum_tuples()
		).first - ct_body_id.begin();

	// 3. Add contact forces and torques to existing forces (impulses)
	//    For all bodies involved in a contact, update the body forces and torques,
	//    scaled by the integration time step.
	host_AddContactForces(ct_body_count, ct_body_id, ct_body_force, ct_body_torque);
}

void ChLcpSolverParallelDEM::RunTimeStep(real step)
{
	step_size = step;
	data_container->step_size = step;

	number_of_constraints = data_container->number_of_bilaterals;
	number_of_objects = data_container->number_of_rigid;

	// Calculate contact forces (impulses) and append them to the body forces
	if (data_container->number_of_rigid_rigid)
		ProcessContacts();

	// Include forces and torques (update derivatives: v += m_inv * h * f)
	Preprocess();

	// Return now if there are no (bilateral) constraints
	if (number_of_constraints == 0)
		return;

	data_container->host_data.rhs_data.resize(number_of_constraints);
	data_container->host_data.diag.resize(number_of_constraints);
	data_container->host_data.gamma_data.resize(number_of_constraints);

	//// TODO: Is this needed?  If yes, we should initialize gamma_bilateral anyway...
#pragma omp parallel for
	for (int i = 0; i < number_of_constraints; i++) {
		data_container->host_data.gamma_data[i] = 0;
	}

	bilateral.Setup(data_container);

	solver.current_iteration = 0;
	solver.total_iteration = 0;
	solver.maxd_hist.clear();               ////
	solver.maxdeltalambda_hist.clear();     ////  currently not used
	solver.iter_hist.clear();               ////

	solver.SetTolerance(tolerance);

	////solver.lcp_omega_bilateral = lcp_omega_bilateral;  //// not used anywhere?
	solver.bilateral = &bilateral;
	solver.Initial(step, data_container);

	////bilateral.ComputeJacobians();    //// no-op
	bilateral.ComputeRHS();

	solver.SolveStab(data_container->host_data.gamma_bilateral, data_container->host_data.rhs_data, max_iter_bilateral);

	thrust::copy_n(data_container->host_data.gamma_bilateral.begin(), data_container->number_of_bilaterals, data_container->host_data.gamma_data.begin());

	solver.ComputeImpulses();

	tot_iterations = solver.GetIteration();
	residual = solver.GetResidual();

	////for (int i = 0; i < solver.iter_hist.size(); i++) {
	////	AtIterationEnd(solver.maxd_hist[i], solver.maxdeltalambda_hist[i], solver.iter_hist[i]);
	////}

}

<commit_msg>Add timers to the main DEM solver function.<commit_after>#include "ChLcpSolverParallel.h"
#include "math/ChThrustLinearAlgebra.h"

using namespace chrono;

//// TODO:  For now, this is hard-coded for Hunt-Crossley with Simple Sliding Friction.
__host__ __device__
void function_CalcContactForces(int&       index,           // index of this contact pair
                                real&      dT,              // integration time step
                                real3*     pos,             // body positions
                                real4*     rot,             // body orientations
                                real3*     vel,             // body linear velocity (global frame)
                                real3*     omg,             // body angular velocity (local frame)
                                real2*     elastic_moduli,  // Young's modulus (per body)
                                real*      mu,              // coefficient of friction (per body)
                                real*      alpha,           // disipation coefficient (per body)
                                real*      cr,              // coefficient of restitution (per body)
                                real*      cohesion,        // cohesion force (per body)
                                int2*      body_id,         // body IDs (per contact)
                                real3*     pt1,             // point on shape 1 (per contact)
                                real3*     pt2,             // point on shape 2 (per contact)
                                real3*     normal,          // contact normal (per contact)
                                real*      depth,           // penetration depth (per contact)
                                real*      eff_radius,      // effective contact radius (per contact)
                                int*       ext_body_id,     // [output] body IDs (two per contact)
                                real3*     ext_body_force,  // [output] body force (two per contact)
                                real3*     ext_body_torque) // [output] body torque (two per contact)
{
	// Identify the two bodies in contact.
	int body1 = body_id[index].x;
	int body2 = body_id[index].y;

	// If the two contact shapes are actually separated, set zero forces and torques
	if (depth[index] >= 0) {
		ext_body_id[2*index] = body1;
		ext_body_id[2*index+1] = body2;
		ext_body_force[2*index] = ZERO_VECTOR;
		ext_body_force[2*index+1] = ZERO_VECTOR;
		ext_body_torque[2*index] = ZERO_VECTOR;
		ext_body_torque[2*index+1] = ZERO_VECTOR;

		return;
	}

	// Kinematic information
	// ---------------------

	// Express contact point locations in local frames
	//   s' = At * s = At * (rP - r)
	real3 pt1_loc = TransformParentToLocal(pos[body1], rot[body1], pt1[index]);
	real3 pt2_loc = TransformParentToLocal(pos[body2], rot[body2], pt2[index]);

	// Calculate relative velocity (in global frame)
	//   vP = v + omg x s = v + A * (omg' x s')
	real3 vel1 = vel[body1] + quatRotateMat(cross(omg[body1], pt1_loc), rot[body1]);
	real3 vel2 = vel[body2] + quatRotateMat(cross(omg[body2], pt2_loc), rot[body2]);
	real3 relvel = vel2 - vel1;
	real  relvel_n_mag = dot(relvel, normal[index]);
	real3 relvel_n = relvel_n_mag * normal[index];
	real3 relvel_t = relvel - relvel_n;
	real  relvel_t_mag = length(relvel_t);

	// Calculate composite material properties
	// ---------------------------------------

	real Y1 = elastic_moduli[body1].x;
	real Y2 = elastic_moduli[body2].x;
	real nu1 = elastic_moduli[body1].y;
	real nu2 = elastic_moduli[body2].y;
	real inv_E = (1 - nu1 * nu1) / Y1 + (1 - nu2 * nu2) / Y2;
	real inv_G = 2 * (2 + nu1) * (1 - nu1) / Y1 + 2 * (2 + nu2) * (1 - nu2) / Y2;

	real E_eff = 1 / inv_E;
	real G_eff = 1 / inv_G;

	real mu_eff = min(mu[body1], mu[body2]);
	//real cr_eff = (cr[body1] + cr[body2]) / 2;
	real alpha_eff = (alpha[body1] + alpha[body2]) / 2;

	real cohesion_eff = min(cohesion[body1], cohesion[body2]);

	// Contact force
	// -------------

	// Normal force: Hunt-Crossley
	real delta = -depth[index];
	real kn = (4.0 / 3) * E_eff * sqrt(eff_radius[index]);
	real forceN_elastic = kn * delta * sqrt(delta);
	real forceN_dissipation = 1.5 * alpha_eff * forceN_elastic * relvel_n_mag;
	real forceN = forceN_elastic - forceN_dissipation;

	// Cohesion force
	forceN -= cohesion_eff;

	real3 force = forceN * normal[index];

	// Tangential force: Simple Coulomb Sliding
	if (relvel_t_mag > 1e-4) {
		real forceT = mu_eff * abs(forceN);

		force -= (forceT / relvel_t_mag) * relvel_t;
	}

	// Body forces (in global frame) & torques (in local frame)
	// --------------------------------------------------------

	// Convert force into the local body frames and calculate induced torques
	//    n' = s' x F' = s' x (A*F)
	real3 torque1_loc = cross(pt1_loc, quatRotateMatT(force, rot[body1]));
	real3 torque2_loc = cross(pt2_loc, quatRotateMatT(force, rot[body2]));

	// Store body forces and torques
	ext_body_id[2*index]   = body1;
	ext_body_id[2*index+1] = body2;
	ext_body_force[2*index]   = -force;
	ext_body_force[2*index+1] =  force;
	ext_body_torque[2*index]   = -torque1_loc;
	ext_body_torque[2*index+1] =  torque2_loc;
}

void ChLcpSolverParallelDEM::host_CalcContactForces(custom_vector<int>&   ext_body_id,
                                                    custom_vector<real3>& ext_body_force,
                                                    custom_vector<real3>& ext_body_torque)
{
#pragma omp parallel for
	for (int index = 0; index < data_container->number_of_rigid_rigid; index++) {
		function_CalcContactForces(
			index,
			step_size,
			data_container->host_data.pos_data.data(),
			data_container->host_data.rot_data.data(),
			data_container->host_data.vel_data.data(),
			data_container->host_data.omg_data.data(),
			data_container->host_data.elastic_moduli.data(),
			data_container->host_data.mu.data(),
			data_container->host_data.alpha.data(),
			data_container->host_data.cr.data(),
			data_container->host_data.cohesion_data.data(),
			data_container->host_data.bids_rigid_rigid.data(),
			data_container->host_data.cpta_rigid_rigid.data(),
			data_container->host_data.cptb_rigid_rigid.data(),
			data_container->host_data.norm_rigid_rigid.data(),
			data_container->host_data.dpth_rigid_rigid.data(),
			data_container->host_data.erad_rigid_rigid.data(),
			ext_body_id.data(),
			ext_body_force.data(),
			ext_body_torque.data());
	}
}

void ChLcpSolverParallelDEM::host_AddContactForces(uint                        ct_body_count,
                                                   const custom_vector<int>&   ct_body_id,
                                                   const custom_vector<real3>& ct_body_force,
                                                   const custom_vector<real3>& ct_body_torque)
{
#pragma omp parallel for
	for (int index = 0; index < ct_body_count; index++) {
		data_container->host_data.frc_data[ct_body_id[index]] += step_size * ct_body_force[index];
		data_container->host_data.trq_data[ct_body_id[index]] += step_size * ct_body_torque[index];
	}
}

void ChLcpSolverParallelDEM::ProcessContacts()
{
	// 0. If the narrowphase collision detection does not set the effective contact
	//    radius, fill it with the value 1.
	if (!data_container->erad_is_set)
		data_container->host_data.erad_rigid_rigid.resize(data_container->number_of_rigid_rigid, 1.0);

	// 1. Calculate contact forces and torques - per contact basis
	//    For each pair of contact shapes that overlap, we calculate and store
	//    the IDs of the two corresponding bodies and the resulting contact
	//    forces and torques on the two bodies.
	custom_vector<int>   ext_body_id(2 * data_container->number_of_rigid_rigid);
	custom_vector<real3> ext_body_force(2 * data_container->number_of_rigid_rigid);
	custom_vector<real3> ext_body_torque(2 * data_container->number_of_rigid_rigid);

	host_CalcContactForces(ext_body_id, ext_body_force, ext_body_torque);

	// 2. Calculate contact forces and torques - per body basis
	//    Accumulate the contact forces and torques for all bodies that are involved
	//    in at least one contact, by reducing the contact forces and torques from
	//    all contacts these bodies are involved in. The number of bodies that
	//    experience at least one contact is calculated in 'ct_body_count'.
	thrust::sort_by_key(
		ext_body_id.begin(), ext_body_id.end(),
		thrust::make_zip_iterator(thrust::make_tuple(ext_body_force.begin(), ext_body_torque.begin())));

	custom_vector<int>   ct_body_id(data_container->number_of_rigid);
	custom_vector<real3> ct_body_force(data_container->number_of_rigid);
	custom_vector<real3> ct_body_torque(data_container->number_of_rigid);

	// Reduce contact forces from all contacts and count bodies currently involved in contact
	uint ct_body_count = thrust::reduce_by_key(
		ext_body_id.begin(),
		ext_body_id.end(),
		thrust::make_zip_iterator(thrust::make_tuple(ext_body_force.begin(), ext_body_torque.begin())),
		ct_body_id.begin(),
		thrust::make_zip_iterator(thrust::make_tuple(ct_body_force.begin(), ct_body_torque.begin())),
		thrust::equal_to<int>(),
		sum_tuples()
		).first - ct_body_id.begin();

	// 3. Add contact forces and torques to existing forces (impulses)
	//    For all bodies involved in a contact, update the body forces and torques,
	//    scaled by the integration time step.
	host_AddContactForces(ct_body_count, ct_body_id, ct_body_force, ct_body_torque);
}

void ChLcpSolverParallelDEM::RunTimeStep(real step)
{
	step_size = step;
	data_container->step_size = step;

	number_of_constraints = data_container->number_of_bilaterals;
	number_of_objects = data_container->number_of_rigid;

	// Calculate contact forces (impulses) and append them to the body forces
	if (data_container->number_of_rigid_rigid)
		ProcessContacts();

	// Include forces and torques (update derivatives: v += m_inv * h * f)
	Preprocess();

	// Return now if there are no (bilateral) constraints
	if (number_of_constraints == 0)
		return;

	data_container->system_timer.start("ChLcpSolverParallel_Setup");

	data_container->host_data.rhs_data.resize(number_of_constraints);
	data_container->host_data.diag.resize(number_of_constraints);
	data_container->host_data.gamma_data.resize(number_of_constraints);

	//// TODO: Is this needed?  If yes, we should initialize gamma_bilateral anyway...
#pragma omp parallel for
	for (int i = 0; i < number_of_constraints; i++) {
		data_container->host_data.gamma_data[i] = 0;
	}

	bilateral.Setup(data_container);

	solver.current_iteration = 0;
	solver.total_iteration = 0;
	solver.maxd_hist.clear();               ////
	solver.maxdeltalambda_hist.clear();     ////  currently not used
	solver.iter_hist.clear();               ////

	solver.SetTolerance(tolerance);

	////solver.lcp_omega_bilateral = lcp_omega_bilateral;  //// not used anywhere?
	solver.bilateral = &bilateral;
	solver.Initial(step, data_container);

	////bilateral.ComputeJacobians();    //// no-op
	data_container->system_timer.start("ChLcpSolverParallel_RHS");
	bilateral.ComputeRHS();
	data_container->system_timer.stop("ChLcpSolverParallel_RHS");

	data_container->system_timer.stop("ChLcpSolverParallel_Setup");

	data_container->system_timer.start("ChLcpSolverParallel_Stab");
	solver.SolveStab(data_container->host_data.gamma_bilateral, data_container->host_data.rhs_data, max_iter_bilateral);
	data_container->system_timer.stop("ChLcpSolverParallel_Stab");

	thrust::copy_n(data_container->host_data.gamma_bilateral.begin(), data_container->number_of_bilaterals, data_container->host_data.gamma_data.begin());

	solver.ComputeImpulses();

	tot_iterations = solver.GetIteration();
	residual = solver.GetResidual();

	////for (int i = 0; i < solver.iter_hist.size(); i++) {
	////	AtIterationEnd(solver.maxd_hist[i], solver.maxdeltalambda_hist[i], solver.iter_hist[i]);
	////}

}

<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/options/wifi_config_view.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
#include "views/controls/button/image_button.h"
#include "views/controls/button/native_button.h"
#include "views/controls/label.h"
#include "views/grid_layout.h"
#include "views/standard_layout.h"
#include "views/window/window.h"

namespace chromeos {

// The width of the password field.
const int kPasswordWidth = 150;

WifiConfigView::WifiConfigView(NetworkConfigView* parent,
                               const WifiNetwork* wifi)
    : parent_(parent),
      other_network_(false),
      can_login_(false),
      wifi_(new WifiNetwork(*wifi)),
      ssid_textfield_(NULL),
      identity_textfield_(NULL),
      certificate_browse_button_(NULL),
      certificate_path_(),
      passphrase_textfield_(NULL),
      passphrase_visible_button_(NULL),
      autoconnect_checkbox_(NULL) {
  Init();
}

WifiConfigView::WifiConfigView(NetworkConfigView* parent)
    : parent_(parent),
      other_network_(true),
      can_login_(false),
      wifi_(NULL),
      ssid_textfield_(NULL),
      identity_textfield_(NULL),
      certificate_browse_button_(NULL),
      certificate_path_(),
      passphrase_textfield_(NULL),
      passphrase_visible_button_(NULL),
      autoconnect_checkbox_(NULL) {
  Init();
}

WifiConfigView::~WifiConfigView() {
}

void WifiConfigView::UpdateCanLogin(void) {
  bool can_login = true;
  if (other_network_) {
    // Since the user can try to connect to a non-encrypted hidden network,
    // only enforce ssid is non-empty.
    can_login = !ssid_textfield_->text().empty();
  } else {
    // Connecting to an encrypted network
    if (passphrase_textfield_ != NULL) {
      // if the network requires a passphrase, make sure it is non empty.
      can_login &= !passphrase_textfield_->text().empty();
    }
    if (identity_textfield_ != NULL) {
      // If we have an identity field, we can login if we have a non empty
      // identity and a certificate path
      can_login &= !identity_textfield_->text().empty() &&
          !certificate_path_.empty();
    }
  }

  // Update the login button enable/disable state if can_login_ changes.
  if (can_login != can_login_) {
    can_login_ = can_login;
    parent_->GetDialogClientView()->UpdateDialogButtons();
  }
}

void WifiConfigView::UpdateCanViewPassword() {
  if (passphrase_visible_button_ &&
      !passphrase_visible_button_->IsVisible() &&
      passphrase_textfield_->text().empty()) {
    // Once initial password has been deleted, it's safe to show field content.
    passphrase_visible_button_->SetVisible(true);
  }
}

void WifiConfigView::ContentsChanged(views::Textfield* sender,
                                     const string16& new_contents) {
  UpdateCanLogin();
  UpdateCanViewPassword();
}

bool WifiConfigView::HandleKeystroke(
    views::Textfield* sender,
    const views::Textfield::Keystroke& keystroke) {
  if (sender == passphrase_textfield_ &&
      keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
    parent_->GetDialogClientView()->AcceptWindow();
  }
  return false;
}

void WifiConfigView::ButtonPressed(views::Button* sender,
                                   const views::Event& event) {
  if (sender == passphrase_visible_button_) {
    if (passphrase_textfield_)
      passphrase_textfield_->SetPassword(!passphrase_textfield_->IsPassword());
  } else if (sender == certificate_browse_button_) {
    select_file_dialog_ = SelectFileDialog::Create(this);
    select_file_dialog_->set_browser_mode(parent_->is_browser_mode());
    select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
                                    string16(), FilePath(), NULL, 0,
                                    std::string(),
                                    parent_->is_browser_mode() ?
                                        NULL :
                                        parent_->GetNativeWindow(),
                                    NULL);
  } else {
    NOTREACHED();
  }
}

void WifiConfigView::FileSelected(const FilePath& path,
                                   int index, void* params) {
  certificate_path_ = path.value();
  if (certificate_browse_button_)
    certificate_browse_button_->SetLabel(path.BaseName().ToWStringHack());
  UpdateCanLogin();  // TODO(njw) Check if the passphrase decrypts the key.
}

bool WifiConfigView::Login() {
  std::string identity_string;
  if (identity_textfield_ != NULL) {
    identity_string = UTF16ToUTF8(identity_textfield_->text());
  }
  if (other_network_) {
    CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork(
        GetSSID(), GetPassphrase(),
        identity_string, certificate_path_,
        autoconnect_checkbox_ ? autoconnect_checkbox_->checked() : true);
  } else {
    Save();
    CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork(
        wifi_.get(), GetPassphrase(),
        identity_string, certificate_path_);
  }
  return true;
}

bool WifiConfigView::Save() {
  // Save password and auto-connect here.
  if (!other_network_) {
    bool changed = false;

    if (autoconnect_checkbox_) {
      bool auto_connect = autoconnect_checkbox_->checked();
      if (auto_connect != wifi_->auto_connect()) {
        wifi_->set_auto_connect(auto_connect);
        changed = true;
      }
    }

    if (passphrase_textfield_) {
      const std::string& passphrase =
          UTF16ToUTF8(passphrase_textfield_->text());
      if (passphrase != wifi_->passphrase()) {
        wifi_->set_passphrase(passphrase);
        changed = true;
      }
    }

    if (changed)
      CrosLibrary::Get()->GetNetworkLibrary()->SaveWifiNetwork(wifi_.get());
  }
  return true;
}

const std::string WifiConfigView::GetSSID() const {
  std::string result;
  if (ssid_textfield_ != NULL)
    result = UTF16ToUTF8(ssid_textfield_->text());
  return result;
}

const std::string WifiConfigView::GetPassphrase() const {
  std::string result;
  if (passphrase_textfield_ != NULL)
    result = UTF16ToUTF8(passphrase_textfield_->text());
  return result;
}

void WifiConfigView::FocusFirstField() {
  if (ssid_textfield_)
    ssid_textfield_->RequestFocus();
  else if (identity_textfield_)
    identity_textfield_->RequestFocus();
  else if (passphrase_textfield_)
    passphrase_textfield_->RequestFocus();
}

void WifiConfigView::Init() {
  views::GridLayout* layout = CreatePanelGridLayout(this);
  SetLayoutManager(layout);

  int column_view_set_id = 0;
  views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
  // Label
  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, 0);
  // Textfield
  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, kPasswordWidth);
  // Password visible button
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, 0);

  layout->StartRow(0, column_view_set_id);
  layout->AddView(new views::Label(l10n_util::GetString(
      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID)));
  if (other_network_) {
    ssid_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
    ssid_textfield_->SetController(this);
    layout->AddView(ssid_textfield_);
  } else {
    views::Label* label = new views::Label(ASCIIToWide(wifi_->name()));
    label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    layout->AddView(label);
  }
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Loaded certificates (i.e. stored in a pkcs11 device) do not require
  // a passphrase.
  bool certificate_loaded = false;

  // Add ID and cert password if we're using 802.1x
  // XXX we're cheating and assuming 802.1x means EAP-TLS - not true
  // in general, but very common. WPA Supplicant doesn't report the
  // EAP type because it's unknown until the process begins, and we'd
  // need some kind of callback.
  if (wifi_->encrypted() && wifi_->encryption() == SECURITY_8021X) {
    layout->StartRow(0, column_view_set_id);
    layout->AddView(new views::Label(l10n_util::GetString(
        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_IDENTITY)));
    identity_textfield_ = new views::Textfield(
        views::Textfield::STYLE_DEFAULT);
    identity_textfield_->SetController(this);
    if (!wifi_->identity().empty())
      identity_textfield_->SetText(UTF8ToUTF16(wifi_->identity()));
    layout->AddView(identity_textfield_);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
    layout->StartRow(0, column_view_set_id);
    layout->AddView(new views::Label(l10n_util::GetString(
        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT)));
    if (!wifi_->cert_path().empty()) {
      certificate_path_ = wifi_->cert_path();
      certificate_loaded = wifi_->IsCertificateLoaded();
    }
    if (certificate_loaded) {
      std::wstring label = l10n_util::GetString(
          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_INSTALLED);
      views::Label* cert_text = new views::Label(label);
      cert_text->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
      layout->AddView(cert_text);
    } else {
      std::wstring label;
      if (!certificate_path_.empty())
        label = UTF8ToWide(certificate_path_);
      else
        label = l10n_util::GetString(
            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_BUTTON);
      certificate_browse_button_ = new views::NativeButton(this, label);
      layout->AddView(certificate_browse_button_);
    }
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }

  // Add passphrase if other_network or wifi is encrypted.
  if (other_network_ || (wifi_->encrypted() && !certificate_loaded)) {
    layout->StartRow(0, column_view_set_id);
    int label_text_id;
    if (wifi_->encryption() == SECURITY_8021X)
      label_text_id =
          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PRIVATE_KEY_PASSWORD;
    else
      label_text_id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE;
    layout->AddView(new views::Label(l10n_util::GetString(label_text_id)));
    passphrase_textfield_ = new views::Textfield(
        views::Textfield::STYLE_PASSWORD);
    passphrase_textfield_->SetController(this);
    if (!wifi_->passphrase().empty())
      passphrase_textfield_->SetText(UTF8ToUTF16(wifi_->passphrase()));
    layout->AddView(passphrase_textfield_);
    // Password visible button.
    passphrase_visible_button_ = new views::ImageButton(this);
    passphrase_visible_button_->SetImage(views::ImageButton::BS_NORMAL,
        ResourceBundle::GetSharedInstance().
        GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
    passphrase_visible_button_->SetImageAlignment(
        views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE);
    // Disable viewing password by unauthenticated user.
    if (!wifi_->passphrase().empty() &&
        chromeos::UserManager::Get()->logged_in_user().email().empty()) {
      passphrase_visible_button_->SetVisible(false);
    }
    layout->AddView(passphrase_visible_button_);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }

  // If there's an error, add an error message label.
  // Right now, only displaying bad_passphrase and bad_wepkey errors.
  if (wifi_->error() == ERROR_BAD_PASSPHRASE ||
      wifi_->error() == ERROR_BAD_WEPKEY) {
    layout->StartRow(0, column_view_set_id);
    layout->SkipColumns(1);
    int id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE;
    if (wifi_->error() == ERROR_BAD_WEPKEY)
      id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY;
    views::Label* label_error = new views::Label(l10n_util::GetString(id));
    label_error->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    label_error->SetColor(SK_ColorRED);
    layout->AddView(label_error);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }

  // Autoconnect checkbox
  // Only show if this network is already remembered (a favorite).
  if (wifi_->favorite()) {
    autoconnect_checkbox_ = new views::Checkbox(l10n_util::GetString(
        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
    // For other network, default to autoconnect.
    bool autoconnect = other_network_ || wifi_->auto_connect();
    autoconnect_checkbox_->SetChecked(autoconnect);
    layout->StartRow(0, column_view_set_id);
    layout->AddView(autoconnect_checkbox_, 3, 1);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }
}

}  // namespace chromeos
<commit_msg>Fixed crash in Add Network dialog.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/options/wifi_config_view.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
#include "views/controls/button/image_button.h"
#include "views/controls/button/native_button.h"
#include "views/controls/label.h"
#include "views/grid_layout.h"
#include "views/standard_layout.h"
#include "views/window/window.h"

namespace chromeos {

// The width of the password field.
const int kPasswordWidth = 150;

WifiConfigView::WifiConfigView(NetworkConfigView* parent,
                               const WifiNetwork* wifi)
    : parent_(parent),
      other_network_(false),
      can_login_(false),
      wifi_(new WifiNetwork(*wifi)),
      ssid_textfield_(NULL),
      identity_textfield_(NULL),
      certificate_browse_button_(NULL),
      certificate_path_(),
      passphrase_textfield_(NULL),
      passphrase_visible_button_(NULL),
      autoconnect_checkbox_(NULL) {
  Init();
}

WifiConfigView::WifiConfigView(NetworkConfigView* parent)
    : parent_(parent),
      other_network_(true),
      can_login_(false),
      ssid_textfield_(NULL),
      identity_textfield_(NULL),
      certificate_browse_button_(NULL),
      certificate_path_(),
      passphrase_textfield_(NULL),
      passphrase_visible_button_(NULL),
      autoconnect_checkbox_(NULL) {
  Init();
}

WifiConfigView::~WifiConfigView() {
}

void WifiConfigView::UpdateCanLogin(void) {
  bool can_login = true;
  if (other_network_) {
    // Since the user can try to connect to a non-encrypted hidden network,
    // only enforce ssid is non-empty.
    can_login = !ssid_textfield_->text().empty();
  } else {
    // Connecting to an encrypted network
    if (passphrase_textfield_ != NULL) {
      // if the network requires a passphrase, make sure it is non empty.
      can_login &= !passphrase_textfield_->text().empty();
    }
    if (identity_textfield_ != NULL) {
      // If we have an identity field, we can login if we have a non empty
      // identity and a certificate path
      can_login &= !identity_textfield_->text().empty() &&
          !certificate_path_.empty();
    }
  }

  // Update the login button enable/disable state if can_login_ changes.
  if (can_login != can_login_) {
    can_login_ = can_login;
    parent_->GetDialogClientView()->UpdateDialogButtons();
  }
}

void WifiConfigView::UpdateCanViewPassword() {
  if (passphrase_visible_button_ &&
      !passphrase_visible_button_->IsVisible() &&
      passphrase_textfield_->text().empty()) {
    // Once initial password has been deleted, it's safe to show field content.
    passphrase_visible_button_->SetVisible(true);
  }
}

void WifiConfigView::ContentsChanged(views::Textfield* sender,
                                     const string16& new_contents) {
  UpdateCanLogin();
  UpdateCanViewPassword();
}

bool WifiConfigView::HandleKeystroke(
    views::Textfield* sender,
    const views::Textfield::Keystroke& keystroke) {
  if (sender == passphrase_textfield_ &&
      keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
    parent_->GetDialogClientView()->AcceptWindow();
  }
  return false;
}

void WifiConfigView::ButtonPressed(views::Button* sender,
                                   const views::Event& event) {
  if (sender == passphrase_visible_button_) {
    if (passphrase_textfield_)
      passphrase_textfield_->SetPassword(!passphrase_textfield_->IsPassword());
  } else if (sender == certificate_browse_button_) {
    select_file_dialog_ = SelectFileDialog::Create(this);
    select_file_dialog_->set_browser_mode(parent_->is_browser_mode());
    select_file_dialog_->SelectFile(SelectFileDialog::SELECT_OPEN_FILE,
                                    string16(), FilePath(), NULL, 0,
                                    std::string(),
                                    parent_->is_browser_mode() ?
                                        NULL :
                                        parent_->GetNativeWindow(),
                                    NULL);
  } else {
    NOTREACHED();
  }
}

void WifiConfigView::FileSelected(const FilePath& path,
                                   int index, void* params) {
  certificate_path_ = path.value();
  if (certificate_browse_button_)
    certificate_browse_button_->SetLabel(path.BaseName().ToWStringHack());
  UpdateCanLogin();  // TODO(njw) Check if the passphrase decrypts the key.
}

bool WifiConfigView::Login() {
  std::string identity_string;
  if (identity_textfield_ != NULL) {
    identity_string = UTF16ToUTF8(identity_textfield_->text());
  }
  if (other_network_) {
    CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork(
        GetSSID(), GetPassphrase(),
        identity_string, certificate_path_,
        autoconnect_checkbox_ ? autoconnect_checkbox_->checked() : true);
  } else {
    Save();
    CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork(
        wifi_.get(), GetPassphrase(),
        identity_string, certificate_path_);
  }
  return true;
}

bool WifiConfigView::Save() {
  // Save password and auto-connect here.
  if (!other_network_) {
    bool changed = false;

    if (autoconnect_checkbox_) {
      bool auto_connect = autoconnect_checkbox_->checked();
      if (auto_connect != wifi_->auto_connect()) {
        wifi_->set_auto_connect(auto_connect);
        changed = true;
      }
    }

    if (passphrase_textfield_) {
      const std::string& passphrase =
          UTF16ToUTF8(passphrase_textfield_->text());
      if (passphrase != wifi_->passphrase()) {
        wifi_->set_passphrase(passphrase);
        changed = true;
      }
    }

    if (changed)
      CrosLibrary::Get()->GetNetworkLibrary()->SaveWifiNetwork(wifi_.get());
  }
  return true;
}

const std::string WifiConfigView::GetSSID() const {
  std::string result;
  if (ssid_textfield_ != NULL)
    result = UTF16ToUTF8(ssid_textfield_->text());
  return result;
}

const std::string WifiConfigView::GetPassphrase() const {
  std::string result;
  if (passphrase_textfield_ != NULL)
    result = UTF16ToUTF8(passphrase_textfield_->text());
  return result;
}

void WifiConfigView::FocusFirstField() {
  if (ssid_textfield_)
    ssid_textfield_->RequestFocus();
  else if (identity_textfield_)
    identity_textfield_->RequestFocus();
  else if (passphrase_textfield_)
    passphrase_textfield_->RequestFocus();
}

void WifiConfigView::Init() {
  views::GridLayout* layout = CreatePanelGridLayout(this);
  SetLayoutManager(layout);

  int column_view_set_id = 0;
  views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
  // Label
  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, 0);
  // Textfield
  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, kPasswordWidth);
  // Password visible button
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL, 1,
                        views::GridLayout::USE_PREF, 0, 0);

  layout->StartRow(0, column_view_set_id);
  layout->AddView(new views::Label(l10n_util::GetString(
      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID)));
  if (other_network_) {
    ssid_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
    ssid_textfield_->SetController(this);
    layout->AddView(ssid_textfield_);
  } else {
    views::Label* label = new views::Label(ASCIIToWide(wifi_->name()));
    label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    layout->AddView(label);
  }
  layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);

  // Loaded certificates (i.e. stored in a pkcs11 device) do not require
  // a passphrase.
  bool certificate_loaded = false;

  // Add ID and cert password if we're using 802.1x
  // XXX we're cheating and assuming 802.1x means EAP-TLS - not true
  // in general, but very common. WPA Supplicant doesn't report the
  // EAP type because it's unknown until the process begins, and we'd
  // need some kind of callback.
  if (wifi_.get() && wifi_->encrypted() &&
      wifi_->encryption() == SECURITY_8021X) {
    layout->StartRow(0, column_view_set_id);
    layout->AddView(new views::Label(l10n_util::GetString(
        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_IDENTITY)));
    identity_textfield_ = new views::Textfield(
        views::Textfield::STYLE_DEFAULT);
    identity_textfield_->SetController(this);
    if (!wifi_->identity().empty())
      identity_textfield_->SetText(UTF8ToUTF16(wifi_->identity()));
    layout->AddView(identity_textfield_);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
    layout->StartRow(0, column_view_set_id);
    layout->AddView(new views::Label(l10n_util::GetString(
        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT)));
    if (!wifi_->cert_path().empty()) {
      certificate_path_ = wifi_->cert_path();
      certificate_loaded = wifi_->IsCertificateLoaded();
    }
    if (certificate_loaded) {
      std::wstring label = l10n_util::GetString(
          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_INSTALLED);
      views::Label* cert_text = new views::Label(label);
      cert_text->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
      layout->AddView(cert_text);
    } else {
      std::wstring label;
      if (!certificate_path_.empty())
        label = UTF8ToWide(certificate_path_);
      else
        label = l10n_util::GetString(
            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_BUTTON);
      certificate_browse_button_ = new views::NativeButton(this, label);
      layout->AddView(certificate_browse_button_);
    }
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }

  // Add passphrase if other_network or wifi is encrypted.
  if (other_network_ || (wifi_.get() && wifi_->encrypted() &&
                         !certificate_loaded)) {
    layout->StartRow(0, column_view_set_id);
    int label_text_id;
    if (wifi_.get() && wifi_->encryption() == SECURITY_8021X)
      label_text_id =
          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PRIVATE_KEY_PASSWORD;
    else
      label_text_id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE;
    layout->AddView(new views::Label(l10n_util::GetString(label_text_id)));
    passphrase_textfield_ = new views::Textfield(
        views::Textfield::STYLE_PASSWORD);
    passphrase_textfield_->SetController(this);
    if (wifi_.get() && !wifi_->passphrase().empty())
      passphrase_textfield_->SetText(UTF8ToUTF16(wifi_->passphrase()));
    layout->AddView(passphrase_textfield_);
    // Password visible button.
    passphrase_visible_button_ = new views::ImageButton(this);
    passphrase_visible_button_->SetImage(views::ImageButton::BS_NORMAL,
        ResourceBundle::GetSharedInstance().
        GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE));
    passphrase_visible_button_->SetImageAlignment(
        views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE);
    // Disable viewing password by unauthenticated user.
    if (wifi_.get() && !wifi_->passphrase().empty() &&
        chromeos::UserManager::Get()->logged_in_user().email().empty()) {
      passphrase_visible_button_->SetVisible(false);
    }
    layout->AddView(passphrase_visible_button_);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }

  // If there's an error, add an error message label.
  // Right now, only displaying bad_passphrase and bad_wepkey errors.
  if (wifi_.get() && (wifi_->error() == ERROR_BAD_PASSPHRASE ||
      wifi_->error() == ERROR_BAD_WEPKEY)) {
    layout->StartRow(0, column_view_set_id);
    layout->SkipColumns(1);
    int id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE;
    if (wifi_->error() == ERROR_BAD_WEPKEY)
      id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY;
    views::Label* label_error = new views::Label(l10n_util::GetString(id));
    label_error->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    label_error->SetColor(SK_ColorRED);
    layout->AddView(label_error);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }

  // Autoconnect checkbox
  // Only show if this network is already remembered (a favorite).
  if (wifi_.get() && wifi_->favorite()) {
    autoconnect_checkbox_ = new views::Checkbox(l10n_util::GetString(
        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT));
    // For other network, default to autoconnect.
    bool autoconnect = other_network_ || wifi_->auto_connect();
    autoconnect_checkbox_->SetChecked(autoconnect);
    layout->StartRow(0, column_view_set_id);
    layout->AddView(autoconnect_checkbox_, 3, 1);
    layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
  }
}

}  // namespace chromeos
<|endoftext|>


<commit_before>//! \file
//! ClientConnectedState class implementation

#include "MainState.h"
#include <sstream>

MainStateEnum ClientConnectedState::LocalUpdate()
{
	if (InputHandler::InputTime == 0)
	{
		if (Index == 0)
		{
			if (InputHandler::LastInput == Down)
			{
				Index = 1;
			}
			else if (InputHandler::LastInput == Left
					|| InputHandler::LastInput == Right)
			{
				if (SelectedCharacter == Pacman_c)
				{
					SelectedCharacter = Ghost_c;
				}
				else
				{
					SelectedCharacter = Pacman_c;
				}
			}
		}
		else
		{
			if (InputHandler::LastInput == Up)
			{
				Ready = false;
				Index = 0;
			}
			else if (InputHandler::LastInput == Right)
			{
				Ready = true;
				std::vector<char> data_s(PlayerReady_size);
				data_s[PlayerReady_Character] = SelectedCharacter;
				NetworkManager::Send(
						NetworkManager::PlayerReady, data_s, 0);
			}
			else if (InputHandler::LastInput == Left)
			{
				Ready = false;
				std::vector<char> data_s(PlayerNotReady_size);
				NetworkManager::Send(NetworkManager::PlayerNotReady, data_s, 0);
			}
		}
	}

	if (NetworkManager::CurrentConnections[0].Lag > NetworkTimeout)
	{
		return Join;
	}

	// ping server
	std::vector<char> data_s(PingServer_size);
	NetworkManager::Send(NetworkManager::PingServer, data_s, 0);

	return ClientConnected;
}

MainStateEnum ClientConnectedState::ProcessPacket(NetworkManager::MessageType mtype,
		std::vector<char> &data_r, unsigned int id)
{
	if (id == 0)
	{
		NetworkManager::CurrentConnections[0].Lag = 0;
		if (mtype == NetworkManager::PingClient)
		{
			// No action needed
		}
		else if (mtype == NetworkManager::ConfirmClient)
		{
			PlayerNumber =
				data_r[ConfirmClient_PlayerNumber];
		}
		else if (mtype == NetworkManager::DisconnectClient)
		{
			return Join;
		}
		else if (mtype == NetworkManager::StartGame)
		{
			unsigned char count = data_r[StartGame_PlayerCount];
			unsigned char field = data_r[StartGame_Field];

			/// \TODO Add field selection
			Field gameField("../stage1.txt");
			Renderer::LoadField(&gameField, "../spritesheet.png");

			std::vector<Player *> players;
			for (unsigned int i = 0; i < count; i++)
			{
				Character c = (Character)data_r[StartGame_Character + i];
				if (c == Pacman_c)
				{
					players.push_back(new Pacman());
				}
				else if (c == Ghost_c)
				{
					players.push_back(new Ghost());
				}
			}
			StartingGame = new Game(gameField, players);
			return Gameplay;
		}
	}

	return ClientConnected;
}

void ClientConnectedState::Render() const
{
	std::ostringstream ss;
	ss << "You are Player ";
	ss << PlayerNumber + 1;
	std::string str = ss.str();
	Renderer::DrawText(0, str, 24, 60, 100);
	Character c = SelectedCharacter;
	bool ready = Ready;
	unsigned int index = Index;
	if (c == Pacman_c)
	{
		Renderer::DrawText(0, "< Pac-Man >", 18, 60, 140);
	}
	else
	{
		Renderer::DrawText(0, "<  Ghost  >", 18, 60, 140);
	}
	if (ready)
	{
		Renderer::DrawText(0, "< Ready!", 18, 60, 180);
	}
	else
	{
		Renderer::DrawText(0, "  Ready? >", 18, 60, 180);
	}
	Renderer::DrawText(0, ">", 18, 20, 140 + 40 * index);
}
<commit_msg>Client sends not ready signal when moving cursor<commit_after>//! \file
//! ClientConnectedState class implementation

#include "MainState.h"
#include <sstream>

MainStateEnum ClientConnectedState::LocalUpdate()
{
	if (InputHandler::InputTime == 0)
	{
		if (Index == 0)
		{
			if (InputHandler::LastInput == Down)
			{
				Index = 1;
			}
			else if (InputHandler::LastInput == Left
					|| InputHandler::LastInput == Right)
			{
				if (SelectedCharacter == Pacman_c)
				{
					SelectedCharacter = Ghost_c;
				}
				else
				{
					SelectedCharacter = Pacman_c;
				}
			}
		}
		else
		{
			if (InputHandler::LastInput == Up)
			{
				Ready = false;
				std::vector<char> data_s(PlayerNotReady_size);
				NetworkManager::Send(NetworkManager::PlayerNotReady, data_s, 0);
				Index = 0;
			}
			else if (InputHandler::LastInput == Right)
			{
				Ready = true;
				std::vector<char> data_s(PlayerReady_size);
				data_s[PlayerReady_Character] = SelectedCharacter;
				NetworkManager::Send(
						NetworkManager::PlayerReady, data_s, 0);
			}
			else if (InputHandler::LastInput == Left)
			{
				Ready = false;
				std::vector<char> data_s(PlayerNotReady_size);
				NetworkManager::Send(NetworkManager::PlayerNotReady, data_s, 0);
			}
		}
	}

	if (NetworkManager::CurrentConnections[0].Lag > NetworkTimeout)
	{
		return Join;
	}

	// ping server
	std::vector<char> data_s(PingServer_size);
	NetworkManager::Send(NetworkManager::PingServer, data_s, 0);

	return ClientConnected;
}

MainStateEnum ClientConnectedState::ProcessPacket(NetworkManager::MessageType mtype,
		std::vector<char> &data_r, unsigned int id)
{
	if (id == 0)
	{
		NetworkManager::CurrentConnections[0].Lag = 0;
		if (mtype == NetworkManager::PingClient)
		{
			// No action needed
		}
		else if (mtype == NetworkManager::ConfirmClient)
		{
			PlayerNumber =
				data_r[ConfirmClient_PlayerNumber];
		}
		else if (mtype == NetworkManager::DisconnectClient)
		{
			return Join;
		}
		else if (mtype == NetworkManager::StartGame)
		{
			unsigned char count = data_r[StartGame_PlayerCount];
			unsigned char field = data_r[StartGame_Field];

			/// \TODO Add field selection
			Field gameField("../stage1.txt");
			Renderer::LoadField(&gameField, "../spritesheet.png");

			std::vector<Player *> players;
			for (unsigned int i = 0; i < count; i++)
			{
				Character c = (Character)data_r[StartGame_Character + i];
				if (c == Pacman_c)
				{
					players.push_back(new Pacman());
				}
				else if (c == Ghost_c)
				{
					players.push_back(new Ghost());
				}
			}
			StartingGame = new Game(gameField, players);
			return Gameplay;
		}
	}

	return ClientConnected;
}

void ClientConnectedState::Render() const
{
	std::ostringstream ss;
	ss << "You are Player ";
	ss << PlayerNumber + 1;
	std::string str = ss.str();
	Renderer::DrawText(0, str, 24, 60, 100);
	Character c = SelectedCharacter;
	bool ready = Ready;
	unsigned int index = Index;
	if (c == Pacman_c)
	{
		Renderer::DrawText(0, "< Pac-Man >", 18, 60, 140);
	}
	else
	{
		Renderer::DrawText(0, "<  Ghost  >", 18, 60, 140);
	}
	if (ready)
	{
		Renderer::DrawText(0, "< Ready!", 18, 60, 180);
	}
	else
	{
		Renderer::DrawText(0, "  Ready? >", 18, 60, 180);
	}
	Renderer::DrawText(0, ">", 18, 20, 140 + 40 * index);
}
<|endoftext|>