/*!**************************************************************************

  module      : RTEComm_PacketHeader.h

  -------------------------------------------------------------------------

  responsible : RaymondR

  special area: communication base classes
  description : This module contains the common communication (base) classes.


  last changed: 2002-11-15  16:20
  see also    : 

  -------------------------------------------------------------------------



    ========== licence begin  GPL
    Copyright (c) 2002-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end




*****************************************************************************/


#ifndef RTECOMM_PACKETHEADER_H
#define RTECOMM_PACKETHEADER_H



/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#include "RunTime/RTE_Types.h"
#include "RunTime/RTE_MessageList.hpp"
#include "RunTime/Communication/RTEComm_Swapping.h"

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/
#define     RTE_COMM_UNDEF_REF  SAPDB_MAX_UINT4

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/


/*===========================================================================*
 *  CLASSES, STRUCTURES, TYPES, UNIONS ...                                   *
 *===========================================================================*/

/*---------------------------------------------------------------------------
   Declaration:  RTEComm_ProtocolID
   Description:  Some type need be the following interfaces
*/
typedef enum { Prot_Undefined = 0,
               Prot_DBManager,
               Prot_ConsoleSM,
               Prot_ConsoleFIFO,
               Prot_DiagPipe
} RTEComm_ProtocolID;


# if defined (__cplusplus)

/*!---------------------------------------------------------------------------
  Class:        RTEComm_PacketHeader  
  Description:  Interface class to create, read and modify the 
                packet header.

                The 'PacketHeader is the first part of each packet indicating
                the kind of packet data. It also contains length information
                to reduce the chance of data truncation going undetected.

                Each transfered packet should look like this:                   
                                                                                <code><pre>
                 PacketBuffer/      ->+----------------+
                 PacketHeaderBuffer   |                |
                                      |  PacketHeader  |
                                      |                |
                 PacketDataBuffer   ->+----------------+
                                      .                .
                                      .                .
                                      |   PacketData   |
                                      .                .
                                      .                .
                                      +----------------+
                                                                                <br>
                                                                                </code></pre>
                The PacketHeader class hides the local and peer swap type. 
                To swap values outside of this header class use the method 
                'SwapObj'. 

                The PacketBuffer/PacketHeaderBuffer should have at least 
                a 16 Byte alignment!

                RTEComm_PacketHeader does not have a base class.
*/
class RTEComm_PacketHeader
{
private:
  typedef struct 
  {
    SAPDB_UInt4                           CurrPacketSegLen;
    SAPDB_UInt1                           ProtocolID;
    SAPDB_UInt1                           ReqRespType; 
    SAPDB_UInt1                           ProtocolVersion;
    SAPDB_UInt1                           ResidualPacketSegs;
    SAPDB_UInt4                           SenderRef;
    SAPDB_UInt4                           ReceiverRef;
    SAPDB_UInt2                           CommState; // - obsolete, old comm. only
    SAPDB_UInt1                           SwapType;
    SAPDB_UInt1                           Filler;
    SAPDB_UInt4                           MaxSendLen;

    // - Use the following define only for static buffer allocations,
    //   otherwise use the 'PacketHeaderBufferSize' methode.
#   define PACKET_HEADER_BUFFER_SIZE     24

    // Should be 8-byte aligned to avoid alignment computations.
    //
    // CurrPacketSegLen    Current packet segment length includes the PacketHeader.
    // MaxSendLen          Includes one PacketHeader regardless of the number
    //                     of packet segments. This means, that the sum of all
    //                     segment's CurrPacketSegLen is greater than
    //                     MaxSendLen unless the number of segments is 1.
    // ProtocolID          Type of protocol ( e.g. TCP/IP, Pipe ... )
    // ReqRespType         This Identifier specifies the packet contents.
    //                     ( e.g. connect, connect response, cancel, release, data, data response ...)
    // ResidualPacketSegs  Number of packet segments  remaining.
    // SenderRef           Sender reference 
    // ReceiverRef         Receiver reference
    // CommState           Communication state
    
  } RTEComm_PacketHeaderRecord; 

public:
  /*!---------------------------------------------------------------------------
     Function:     RTEComm_PacketHeader
     Description:  Create a PacketHeader interface object.

     Arguments:    PacketHeaderBuffer [in] - Pointer to a buffer receiving the PacketHeader.

     Return value: none
  */
                    RTEComm_PacketHeader ( void * const                  PacketHeaderBuffer = NULL )
                                         : m_PacketHeaderBuffer((RTEComm_PacketHeaderRecord *)PacketHeaderBuffer),
                                           m_MaxDataLen   (0),
                                           m_DataRemaining(0) { ; };

  /*!---------------------------------------------------------------------------
     Function:     SetPacketHeaderBuffer
     Description:  Set the PacketHeader buffer.

     Arguments:    PacketHeaderBuffer [in] - Pointer to a buffer receiving the PacketHeader.

     Return value: none
  */
  void              SetPacketHeaderBuffer( void * const                  PacketHeaderBuffer )
                                         { m_PacketHeaderBuffer = (RTEComm_PacketHeaderRecord *)PacketHeaderBuffer; }

  /*!---------------------------------------------------------------------------
     Function:     CopyPacketHeader
     Description:  Copy the PacketHeader buffer.

     Arguments:    PacketHeader [in]     - Source PacketHeader


     Return value: none
  */
  void              CopyPacketHeader     ( RTEComm_PacketHeader const         &PacketHeader );
                                            


  /*!---------------------------------------------------------------------------
     Function:     PacketHeaderBufferSize
     Description:  Returns the buffer size needed to hold the PacketHeader.

     Arguments:    none

     Return value: The buffer size needed to hold the PacketHeader.

  */
  static SAPDB_UInt4 const  PacketHeaderBufferSize();


  /*!---------------------------------------------------------------------------
     Function:     Set
     Description:  Build a new PacketHeader.

                   If a packet must be transfered with more than one send 
                   operation you have to set the header values with 'Set'
                   only once. After each send you must call 'NextSendPacketSeg'
                   which decreases the number of residual packet segments and 
                   calculates the send length for the next packet segment.
                   The 'ResidualPacketSegs' methode can be used to get the
                   number of residual packet segments.


     Arguments:    ReqRespType         [in] - This Identifier specifies the packet contents.
                                              ( e.g. connect, connect response, cancel, release, data, data response ...)
                   SenderRef           [in] - Sender reference.
                   ReceiverRef         [in] - Receiver reference.
                   DataLen             [in] - Total length of data.
                   MaxPacketLen        [in] - Maximum packet length per send/receive  (including PacketHeader).
                   CommState           [in] - Communication state.
                   ProtocolID          [in] - Type of protocol ( e.g. TCP/IP, Pipe ... )
                   ProtocolVersion     [in] - Version of Protocol

     Return value: The send length for the next packet segment ( including PacketHeader space )
  */
  SAPDB_UInt4 const Set                   ( SAPDB_UInt1  const                          ReqRespType,
                                            SAPDB_UInt4  const                          SenderRef,
                                            SAPDB_UInt4  const                          ReceiverRef,
                                            SAPDB_UInt4  const                          DataLen,
                                            RTEComm_ProtocolID const                    ProtocolID,
                                            SAPDB_UInt1 const                           ProtocolVersion,
                                            SAPDB_UInt4 const                           MaxPacketLen  = (SAPDB_UInt4)-1,
                                            SAPDB_UInt2 const                           CommState     = 0 );   // - obsolete, old comm. only

  /*!---------------------------------------------------------------------------
     Function:     Get
     Description:  Get current PacketHeader information.

     Arguments:    ReqRespType      [out]   - This Identifier specifies the packet contents.
                                              ( e.g. connect, connect response, cancel, release, data, data response ...)
                   SenderRef        [out]   - Sender reference.
                   ReceiverRef      [out]   - Receiver reference.
                   DataLen          [out]   - Total length of data.
                   ActDataLen       [out]   - Data length of the current packet.
                   CommState        [out]   - Communication state.
                   ProtocolID       [out]   - Type of protocol ( e.g. TCP/IP, Pipe ... )
                   ProtocolVersion  [out]   - Protocol Version
                   MessageList    [inout]   - The message list to be used

     Return value: true if ok
  */
  bool               Get                  ( SAPDB_UInt1 * const                           pReqRespType,
                                            SAPDB_UInt4 * const                           pSenderRef,
                                            SAPDB_UInt4 * const                           pReceiverRef,
                                            SAPDB_UInt4 * const                           pDataLen,
                                            SAPDB_UInt4 * const                           pActDataLen,
                                            SAPDB_UInt2 * const                           pCommState,  // - obsolete, old comm. only
                                            RTEComm_ProtocolID * const                    pProtocolID,
                                            SAPDB_UInt1 * const                           pProtocolVersion,
                                            SAPDBErr_MessageList                          &MessageList );

  /*!---------------------------------------------------------------------------
     Function:     Get
     Description:  Get current PacketHeader information.

     Arguments:    ReqRespType      [out]   - This Identifier specifies the packet contents.
                                              ( e.g. connect, connect response, cancel, release, data, data response ...)
                   SenderRef        [out]   - Sender reference.
                   ReceiverRef      [out]   - Receiver reference.
                   DataLen          [out]   - Total length of data.
                   ActDataLen       [out]   - Data length of the current packet.
                   ProtocolID       [out]   - Type of protocol ( e.g. TCP/IP, Pipe ... )
                   ProtocolVersion  [out]   - Protocol Version
                   MessageList    [inout]   - The message list to be used

     Return value: true if ok
  */
  bool               Get                  ( SAPDB_UInt1 * const                           pReqRespType,
                                            SAPDB_UInt4 * const                           pSenderRef,
                                            SAPDB_UInt4 * const                           pReceiverRef,
                                            SAPDB_UInt4 * const                           pDataLen,
                                            SAPDB_UInt4 * const                           pActDataLen,
                                            RTEComm_ProtocolID * const                    pProtocolID,
                                            SAPDB_UInt1 * const                           pProtocolVersion,
                                            SAPDBErr_MessageList                          &MessageList )
                                          {
                                           SAPDB_UInt2 DummyCommState;  // - obsolete, old comm. only
                                           return  Get ( pReqRespType, pSenderRef, pReceiverRef,
                                                         pDataLen, pActDataLen, &DummyCommState, pProtocolID,
                                                         pProtocolVersion, MessageList );
                                          }

  /*!---------------------------------------------------------------------------
     Function:     ResidualPacketSegs
     Description:  Get number of remainig packet segments.

     Arguments:    none

     Return value: Number of packet segments remaining.
  */
  SAPDB_UInt1 const ResidualPacketSegs    () const
                                          { return m_PacketHeaderBuffer->ResidualPacketSegs; } ;

  /*!---------------------------------------------------------------------------
     Function:     CurrPacketSegLen
     Description:  Get the total length of the current packet segment ( including PacketHeader space ).

     Arguments:    PacketSegLength  [out]   - The total length of the current 
                                              packet segment ( including PacketHeader ).
                   MessageList      [inout] - The event list to be used,

     Return value: true if ok
  */
  bool             CurrPacketSegLen       ( SAPDB_UInt4                    &PacketSegLength,
                                            SAPDBErr_MessageList           &MessageList );

  /*!---------------------------------------------------------------------------
     Function:     NextSendPacketSeg
     Description:  Update header for the next send operation.

                   If a packet must be transfered with more than one send 
                   operation you have to set the header values with 'Set'
                   only once. After each send you must call 'NextSendPacketSeg'
                   which decreases the number of residual packet segments and 
                   calculates the actual send length for the next packet.
                   The 'ResidualPacketSegs' methode can be used to get the
                   number of residual packet segments.


     Arguments:    none

     Return value: The send length for the next packet ( including PacketHeader space ).
  */
  SAPDB_UInt4 const NextSendPacketSeg     ();

  /*!---------------------------------------------------------------------------
     Function:     SavePacketHeaderBuffer
     Description:  Save the content of the current PacketHeader buffer.

     Arguments:    none
     Return value: none.
  */
  void              SavePacketHeaderBuffer() 
                                          { memcpy(m_SaveRestoreBuffer, m_PacketHeaderBuffer, sizeof(m_SaveRestoreBuffer)); };

  /*!---------------------------------------------------------------------------
     Function:     RestorePacketHeaderBuffer
     Description:  Restore the old content of the PacketHeader buffer.

     Arguments:    none
     Return value: none.
  */
  void              RestorePacketHeaderBuffer() const
                                             { memcpy(m_PacketHeaderBuffer, m_SaveRestoreBuffer, sizeof(m_SaveRestoreBuffer)); };

  /*!---------------------------------------------------------------------------
     Function:     SwapObj
     Description:  Get a 'RTEComm_Swapping' object to swap values outside of this class.

                   The PacketHeader class hides the local and peer swap type. 
                   To swap values outside of this header class use this method.
                   which returns a 'RTEComm_Swapping' object ('swap_object'). 

                   A swap can be done by calling:                       <br>
                                                                        <br>
                    'swap_object' = 'header_object'.SwapObj();          <br>
                                                                        <br>
                    'swap_object'.SwapValue('my_value1');               <br>
                    'swap_object'.SwapValue('my_value2');               <br>
                    'swap_object'.SwapValue('my_value3');               <br>
                                                                        <br>

     Arguments:    none

     Return value: A 'RTEComm_Swapping' object (<swap_object>). 
  */
  RTEComm_Swapping const & SwapObj        () const
                                          { return m_Swap; };
private:
  bool                     SwapHeader     ( SAPDBErr_MessageList   &MessageList );

private:
  RTEComm_PacketHeaderRecord *   m_PacketHeaderBuffer;

  SAPDB_UInt4                    m_MaxDataLen;
  SAPDB_UInt4                    m_DataRemaining;

  char                           m_SaveRestoreBuffer[PACKET_HEADER_BUFFER_SIZE];
  RTEComm_Swapping               m_Swap;

};

/*! EndClass: RTEComm_PacketHeader */


# endif /* __cplusplus */

#endif  /* RTECOMM_PACKETHEADER_H */
