#include "GtpDissector.h"
#include "Logger/Logger.h"


GtpDissector::GtpDissector() 
{
	nUpperIPv = 0;
}

GtpDissector::~GtpDissector() {
  delete m_gtpHdr;
}

GtpDissector * GtpDissector::Clone() const {
  return new GtpDissector();
}

bool GtpDissector::IsPacketValid() const
{
  return m_nMessageLength != PARSING_ERROR;
}

bool GtpDissector::Dissect(const unsigned char * pData, const ssize_t nLen)
{
	std::clog << ">>> GtpDissector::Dissect: " << pData << std::endl;
	m_gtpHdr = new GtpHeader;
	int nHdrLen = 8;
	memcpy(m_gtpHdr, pData, nHdrLen);//8 bytes always mandatory for GTP
	
	if(m_gtpHdr->version != 1)
	{
		Logger::Instance().LogError("Invalid GTP message, bad version number");
		m_nMessageLength = PARSING_ERROR;
	}
	else
	{
		if(m_gtpHdr->s_flag)
		{
			memcpy(&m_gtpHdr->seqNum, &pData[nHdrLen], 2);
			nHdrLen += 2;
		}
		if(m_gtpHdr->pn_flag)
			m_gtpHdr->npduNum = pData[nHdrLen++];
		if(m_gtpHdr->e_flag)
			m_gtpHdr->extensionHeader = pData[nHdrLen++];

		m_nMessageLength = nLen - nHdrLen;
		SavePayload(&pData[nHdrLen], m_nMessageLength);
		//determine if the payload is IPv4 or IPv6
		if(m_nMessageLength && m_gtpHdr->messageType == 0xFF)
		{
			nUpperIPv = pData[nHdrLen];
#if BYTE_ORDER == LITTLE_ENDIAN
			nUpperIPv = nUpperIPv >> 4;
#else
#if BYTE_ORDER == BIG_ENDIAN
			nUpperIPv = nUpperIPv & 0x0F;
#endif
#endif
		}
	}
	return m_nMessageLength >= 0;
}

bool GtpDissector::NeedReassembly() const {
  return false;
}

const EProtocolType GtpDissector::GetUpperLayerType() const 
{
	EProtocolType res = EProtocolType_Unknown;
	switch(m_gtpHdr->messageType)
	{
		case 0xFF:
			if(nUpperIPv == 4)
				res = EProtocolType_IPv4;
			else if(nUpperIPv == 6)
				res = EProtocolType_IPv6;
			break;
		default:
			break;
	}
	std::clog << ">>> EProtocolType GtpDissector::GetUpperLayerType: " << res << std::endl;
	return res;
}


ProtocolInfoElement * GtpDissector::CreateLayerInfo()
{
	return 0;
}

