/*********************************************************************
 *
 * AUTHORIZATION TO USE AND DISTRIBUTE
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that: 
 *
 * (1) source code distributions retain this paragraph in its entirety, 
 *  
 * (2) distributions including binary code include this paragraph in
 *     its entirety in the documentation or other materials provided 
 *     with the distribution, and 
 *
 * (3) all advertising materials mentioning features or use of this 
 *     software display the following acknowledgment:
 * 
 *      "This product includes software written and developed 
 *       by Brian Adamson and Joe Macker of the Naval Research 
 *       Laboratory (NRL)." 
 *         
 *  The name of NRL, the name(s) of NRL  employee(s), or any entity
 *  of the United States Government may not be used to endorse or
 *  promote  products derived from this software, nor does the 
 *  inclusion of the NRL written and developed software  directly or
 *  indirectly suggest NRL or United States  Government endorsement
 *  of this product.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ********************************************************************/
 
#ifndef _MGEN_MESSAGE
#define _MGEN_MESSAGE
      
#include "protokit.h"

#include <stdio.h>  // for FILE*

// (TBD) rework MgenMsg class into more optimized form
        
class MgenMsg
{
    public:
        enum {VERSION = 2};
    
        enum Error
        {
            ERROR_NONE = 0,
            ERROR_VERSION,
            ERROR_CHECKSUM,
            ERROR_LENGTH,
            ERROR_DSTADDR
        };
    
        enum 
        {
            MIN_SIZE = 28,
            MAX_SIZE = 8192
        };
            
        enum AddressType 
        {
            INVALID_ADDRESS = 0, 
            IPv4            = 1, 
            IPv6            = 2
#ifdef SIMULATE
            ,SIM             = 3
#endif // SIMULATE
        };
        
        enum GPSStatus 
        {
            INVALID_GPS     = 0,
            STALE           = 1, 
            CURRENT         = 2
        };
            
        enum Flag 
        {
            CHECKSUM  = 0x01,  // message includes checksum
            CONTINUES = 0x02   // message is a fragment
        };
            
        MgenMsg();
    
        unsigned int Pack(char* buffer, bool includeChecksum);  // bufferLen >= MAX_SIZE
        bool Unpack(const char* buffer, UINT16 bufferLen, bool forceChecksum);       
        
        unsigned char GetVersion() const {return version;}   
        bool FlagIsSet(MgenMsg::Flag theFlag) {return (0 != (flags & theFlag));}  
        unsigned short GetMsgLen() const {return msg_len;}
        unsigned int GetFlowId() const {return flow_id;}
        unsigned int GetSeqNum() const {return seq_num;}
        const struct timeval& GetTxTime() {return tx_time;}
        const ProtoAddress& GetDstAddr() {return dst_addr;}
        const ProtoAddress& GetHostAddr() {return host_addr;}
        MgenMsg::Error GetError() {return msg_error;};
        
        // (TBD) enforce minimum message len
        void SetVersion(unsigned char value) {version = value;}
        void SetFlag(MgenMsg::Flag theFlag) {flags |= theFlag;}
        void SetMsgLen(unsigned short msgLen) {msg_len = msgLen;}       
        void SetFlowId(unsigned int flowId) {flow_id = flowId;}
        void SetSeqNum(unsigned long seqNum) {seq_num = seqNum;}
        void SetTxTime(const struct timeval& txTime) {tx_time = txTime;}
        void SetDstAddr(const ProtoAddress& dstAddr) {dst_addr = dstAddr;}
        void SetHostAddr(const ProtoAddress& hostAddr) {host_addr = hostAddr;}
        void SetGPSLatitude(double value) {latitude = value;}
        void SetGPSLongitude(double value) {longitude = value;}
        void SetGPSAltitude(long value) {altitude = value;}
        void SetGPSStatus(GPSStatus status) {gps_status = status;}
        void SetPayload(const char* buffer, unsigned short len)
            {payload = buffer; payload_len = len;}
        
        // For these, "msgBuffer" is a packed message buffer
        bool LogRecvEvent(FILE*                 logFile, 
                          const struct timeval& eventTime,
                          const ProtoAddress&   srcAddr, 
                          bool                  logBinary,
                          char*                 msgBuffer,
                          bool                  flush);
        
	    bool LogSendEvent(FILE*                 logFile, 
                          bool                  logBinary, 
                          char*                 msgBuffer,
                          bool                  flush);
        
        bool LogRecvError(FILE*                    logFile,
                          const struct timeval&    theTime,
                          const ProtoAddress&      srcAddr, 
                          bool                     logBinary, 
                          MgenMsg::Error           errorType,
                          bool                     flush);

    private:
        static UINT32 ComputeCRC32(const unsigned char* buffer, 
                                   UINT32               buflen);
        static const UINT32 CRC32_XINIT;
        static const UINT32 CRC32_XOROT;
        static const UINT32 CRC32_TABLE[256];
            
        unsigned char   version;
        unsigned char   flags; 
        unsigned short  msg_len;
        unsigned short  packet_header_len;
        unsigned long   flow_id; 
        unsigned long   seq_num; 
        struct timeval  tx_time;
        ProtoAddress  dst_addr;   
        ProtoAddress  host_addr;
                
        double          latitude;
        double          longitude;
        long            altitude;
        GPSStatus       gps_status;
        unsigned short  reserved;
        unsigned short  payload_len;
        const char*     payload;
        
        Error           msg_error;
        
        enum {FLAGS_OFFSET = 3};
};  // end class MgenMsg    

#endif // _MGEN_MESSAGE


syntax highlighted by Code2HTML, v. 0.9.1