//
//  Copyright © 2001 - 2002, RESON Inc. All Rights Reserved.
//
//  No part of this file may be reproduced or transmitted in any form or by
//  any means, electronic or mechanical, including photocopy, recording, or
//  information storage or retrieval system, without permission in writing
//  from RESON Inc.
//
//  Filename:   C7kSocketProtocol.h
//
//  Project:    6046.
//
//  Author(s):  W. Arcus
//
//  Purpose:    Class definition file for the socket protocol.
//
//  Notes:
//

#if !defined(AFX_7KSOCKETPROTOCOL_H__865CE377_0B57_412C_8568_5BCDD94C2019__INCLUDED_)
#define AFX_7KSOCKETPROTOCOL_H__865CE377_0B57_412C_8568_5BCDD94C2019__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "7kProtocolVersion.h"
#include "DynamicBuffer.h"

#pragma warning( push, 3 )                      // Microsoft's STL vector implementation is dirty at warning level 4.
#pragma warning( disable: 4018 )
#include <vector>
#pragma warning( default: 4018 )
#pragma warning( pop )

const unsigned long ulMaxPacketSizeInBytes_c = 64UL * 1024UL;         // 7k network packet (UDP and TCP) are to be <= 64k

class EXPORT_DLL C7kSocketProtocol
{
public:

    // Construction and destruction.

                            C7kSocketProtocol         (   const unsigned long rulMaxPacketBytes = ulMaxPacketSizeInBytes_c );
    virtual                ~C7kSocketProtocol         (   void );

    // Services for decoding.

    // Decoding.

    unsigned long           BytesFollowingHeader        (   void ) const;

    bool                    IsRecordComplete            (   void ) const;

    bool                    ResetDecoder                (   void );

    bool                    Add                         (   const BYTE          *pbyStream,
                                                            const unsigned long &rulBytes,
                                                            const bool          &rbIsHeader );

    BYTE *                  DecodedRecord               (   void );

    unsigned long           DecodedRecordBytes          (   void );

    static bool             IsValidHeader               (   const BYTE          *pbyStream,
                                                            const unsigned long &rulNumBytes );

    static unsigned long    GetHeaderSize               (   void );

    // Encoding.
                                                    
    bool                    EncodePackets               (   BYTE               *pbyStream,
                                                            unsigned long       ulNumBytes,
                                                            unsigned short      unTotalRecords   = 1,
                                                            unsigned short      unTransmissionId = 0 );

    unsigned long           GetNumberOfPackets          (   void );
                                                    
    BYTE *                  GetNextPacket               (   unsigned long      &rulBytesInPacket );
 
private:

    ///////////////
    // Defintions.

    class CEncode : public CDynamicBuffer<BYTE>
    {
    private:

        typedef struct tagPACKETINDEX
        {
            unsigned long   m_ulPacketSizeInBytes;
            unsigned long   m_ulBufferOffset;

            tagPACKETINDEX( const unsigned long &rulPacketSize   = 0UL,
                            const unsigned long &rulBufferOffset = 0UL )
            {
                m_ulPacketSizeInBytes = rulPacketSize;
                m_ulBufferOffset      = rulBufferOffset;
            }
        }
        PACKETINDEX;

        typedef std::vector<PACKETINDEX>    PacketIndex_t;
        typedef PacketIndex_t::iterator     PacketIndexIterator_t;

        const unsigned long                 m_ulMaxPacketSize;
     
        unsigned long                       m_ulNumberOfPackets;

        PacketIndex_t                       m_PacketIndex;
        PacketIndexIterator_t               m_pLastRetrievedPacket;

        NETWORKFRAMEHEADER                  m_sPacketHeader;

        void                    ResetEncoder        (   void );

        bool                    EncodeNextPacket    (   BYTE          *&rpbyPacket,
                                                        unsigned long  *pulBytesLeft,
                                                        unsigned long   ulPacket,
                                                        unsigned long   ulMaxPacketSize,
                                                        unsigned short  unProtocolVersion,
                                                        unsigned long   ulTotalEmbeddedBytes,
                                                        unsigned short  unTotalRecords,
                                                        unsigned short  unTransmissionId,
                                                        unsigned long   ulDestinationDeviceIdentifier   = 0,
                                                        unsigned short  unDestinationEnumerator         = 0,
                                                        unsigned short  unSourceEnumerator              = 0,
                                                        unsigned long   ulSourceDeviceIdentifier        = 0 );

    public:

                                CEncode             (   const unsigned long rulMaxPacketBytes           = ulMaxPacketSizeInBytes_c );
        virtual                ~CEncode             (   void );

        bool                    EncodePackets       (   BYTE           *pbyStream,
                                                        unsigned long   ulNumBytes,
                                                        unsigned long   ulMaxPacketDataSize,
                                                        unsigned short  unProtocolVersion,
                                                        unsigned short  unTotalRecords,
                                                        unsigned short  unTransmissionId );

        unsigned long           NumberOfPackets     (   void ) const;

        BYTE *                  GetNextPacket       (   unsigned long  &rulBytesInPacket );

    };

    class CDecode : public CDynamicBuffer<BYTE>
    {
    public:                 
                                CDecode                 (   void );
        virtual                ~CDecode                 (   void );

        bool                    ProcessFrame            (   const BYTE          *pbyFrame,
                                                            const unsigned long &rulBytes,
                                                            const bool          &rbIsHeader );

        unsigned long           DynamicBytesThisFrame   (   void ) const;

        bool                    IsRecordComplete        (   void ) const;

        void                    Reset                   (   void );

    private:

        typedef enum tagSTATE                                               // States of the packet sequencer (state machine).
        {
            stateIdle,
            stateAccumulate,
            stateDone,
            stateReset
        }
        ESTATE;

        bool                    m_bRecordIsReady;
        ESTATE                  m_eCurrentState;
        unsigned long           m_ulLastSequenceNumber;
        unsigned long           m_ulDynamicBytesThisFrame;

    };

    ///////////////
    // Attributes.

    const unsigned long         m_ulMaxPacketSize;
    const unsigned long         m_ulHeaderSize;
    const unsigned short        m_unProtocolVersion;

    std::auto_ptr<CEncode>      m_pEncoder;
    std::auto_ptr<CDecode>      m_pDecoder;

};

#endif // !defined(AFX_7KSOCKETPROTOCOL_H__865CE377_0B57_412C_8568_5BCDD94C2019__INCLUDED_)
