//------------------------------------------------------------------------------
//	Copyright (C) 2009, 2010 Humboldt-Universitaet zu Berlin
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 of the License, or (at your option) any later version.
//
//	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
//------------------------------------------------------------------------------

/**
 * @file Pdu.h
 * @author Ronald Kluth
 * @date created at 2009/10/31
 * @brief Declaration of interface odemx::protocol::Pdu
 * @since 3.0
 */

#ifndef ODEMX_PROTOCOL_PDU_INCLUDED
#define ODEMX_PROTOCOL_PDU_INCLUDED

#include <cstddef>
#ifdef _MSC_VER
#include <memory>
#else
#include <tr1/memory>
#endif

namespace odemx {
namespace protocol {

class Pdu;

/// Smart pointer type to manage the lifetime of PDUs
typedef std::tr1::shared_ptr< Pdu > PduPtr;

/**
 * @brief Base class for all protocol data unit types
 * @ingroup protocol
 * @author Ronald Kluth
 * @since 3.0
 * @see odemx::protocol::Sap odemx::protocol::ServiceProvider
 *
 * All message queues in ODEMx requires the same polymorphic base type
 * in order to forward arbitrary messages. Therefore, protocol data units
 * (PDUs) are represented by this class. The data buffers are held by SAPs
 * and read by service providers or service users.
 * 
 * The interface defined for PDU types is simple. ODEMx needs to know the
 * size of the data unit when it is transmitted via medium, and the PDUs
 * must be cloneable in order to avoid side effect when the same PDU
 * is forwarded to multiple receivers at once.
 */
class Pdu
{
public:
	/// Destruction
	virtual ~Pdu() {}

	/**
	 * @brief Create a copy of a PDU object
	 * @return Pointer to a copy of the PDU object
	 * @see odemx::protocol::Medium
	 *
	 * All message types to be used in ODEMx protocol simulations must
	 * implement a clone method. Sending the same message to a number
	 * of different receivers requires that each of them work with their
	 * own copy of the message because it may be altered on its way through
	 * a network. Merely copying the pointer would likely result in unintended
	 * changes leading to subtle errors. This method is thus used by the medium
	 * whenever PDUs are sent to receivers.
	 */
	virtual PduPtr clone() const = 0;

	/**
	 * @brief Get the size of a PDU
	 * @return Size of the PDU
	 * @see odemx::protocol::Device
	 * 
	 * Determining the time it takes to transmit a message via a medium
	 * requires knowledge of the message size and the bitrate at which a
	 * device can send. The latter factor may vary depending on quality of
	 * service parameters and external influences. Therefore, devices require
	 * the message size instead of a fixed time duration value in order to
	 * compute the amount of time it takes to transmit a given message.
	 * 
	 * @note The default implementation returns 0
	 */
	virtual std::size_t getSize() const = 0;
};

} } // namespace odemx::protocol

#endif /* ODEMX_PROTOCOL_PDU_INCLUDED */
