
#include "..\Include\sys.h"
#include "header.txt"



#define PROTOCOL_ROOT msg

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
//pre define struct header

struct tIP;
struct tUDP;
struct tTCP;

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
// ROOT

struct msg
{
    tETHERNET   ETHERNET;
    
    Choice      {
                    DeclareMap(ImplicitItem,EthernetData)  // DeclareMap
                    {
                        IP   [0x0800]  tIP
                    };
                    ChoiceMap EthernetData
                      
                    void Translate(String strCurIdent,dynamic& curItem,long nIdxInArr)
                    {
                         sysTranChoiceItem(strCurIdent,curItem,this.ETHERNET.Protocol);                     
                    }
                };
};

struct tIP
{
    tIPHeader IP;    
    Choice    {
                  DeclareMap(Item,IpData)  // DeclareMap
                  {
                      UDP   [0x11]  tUDP
                      TCP   [0x06]  tTCP
                  };
                  ChoiceMap IpData
                    
                  void Translate(String strCurIdent,dynamic& curItem,long nIdxInArr)
                  {
                       sysTranChoiceItem(strCurIdent,curItem,this.IP.Protocol);                     
                  }
              };
};

///////////////////////////////////////////////
struct tUDP
{
    UINT2   SourcePort;
    UINT2   DestinationPort;
    UINT2   Length;     // Total Length of the UDP packet
    WORD    Checksum;
    MEMO    Data {
                void Translate(String strCurIdent,dynamic& curItem,long nIdxInArr)
                {
                    if (this.Length-8<0)
                        SysAbort("","UDP Length error");
                        
                    sysFetchValue(strCurIdent,curItem,now(),this.Length-8, true);
                }
            };
};

///////////////////////////////////////////////
struct tTCPFlag
{
    UINT2   TCPOffset:4 {   // Offset from the TCP packet head
                String Dump(dynamic& curItem)
                {
                    return strFormat("%d (=%d*4)",curItem*4,curItem);
                }
            };
    UINT2   Reserved:6;
    UINT2   Flag_Urgent:1;          
    UINT2   Flag_Acknowledgment:1;  
    UINT2   Flag_Push:1;            
    UINT2   Flag_Reset:1;           
    UINT2   Flag_Syn:1;             
    UINT2   Flag_Fin:1;             
};

struct tTCP
{
    UINT2    SourcePort;
    UINT2    DestinationPort;
    UINT4    SequenceNumber;
    UINT4    AcknowledgementNumber;
    tTCPFlag Flag;
    UINT2    WindowSize;
    WORD     Checksum;
    UINT2    UrgentPointer;
/*                
    MEMO     TCPOption {
                void Translate(String strCurIdent,dynamic& curItem,long nIdxInArr)
                {
                    sysFetchValue(strCurIdent,curItem,now(),this.Flag.TCPOffset*4-20, true);
                }
             };
*/             
    OCTET    FramePadding { // Option/Padding
                void Translate(String strCurIdent,dynamic& curItem,long nIdxInArr)
                {
                    sysFetchValue(strCurIdent,curItem,now(), this.Flag.TCPOffset*4-20, true); 
                }
             };        
    MEMO     Data {
                void Translate(String strCurIdent,dynamic& curItem,long nIdxInArr)
                {
                    sysFetchValue(strCurIdent,curItem,now(),TotalLength()-now(), true);
                }
             };
};
