Commit 5c4a6b8a authored by nikolajev's avatar nikolajev
Browse files

GTP codec source update

parent 9b266eb8
Loading
Loading
Loading
Loading
+142 −162
Original line number Diff line number Diff line
@@ -4,41 +4,67 @@
#include <fstream>
#include <math.h>

int oct2int(std::string ov) {
// #ifdef DEBUG_LOG
	// std::ofstream logfile("C:\\Temp\\LibGtp.log", std::ios::app);
	// logfile << ">>> oct2int: " << ov << std::endl;
// #endif
	std::string hexa("0123456789ABCDEF");
	int len = ov.length() - 3;
	int v = 0;
	for (int i = 1; i <= len; i += 1) {
// #ifdef DEBUG_LOG
		// logfile << "oct2int: ov[" << i << "]=" << ov[i] << std::endl;
// #endif
		if (ov[i] != 0x30) {
			v += hexa.find(ov[i]) * (int)pow(16, len - i);
// #ifdef DEBUG_LOG
			// logfile << "oct2int: v=" << v << std::endl;
// #endif
		}

//compiler switches:
//#define DEBUG_LOG 1
//#define DIAMETER_ONLY 1

int hex2int(const std::string &hexStr)
{
#ifdef DEBUG_LOG
	 std::ofstream logfile("C:\\Temp\\LibGtp.log", std::ios::app);
	 logfile << "hex2int string input: " << hexStr << std::endl;
#endif
	int nRes = 0;
	for (int i = 0; i < hexStr.size(); i ++)
	{
		unsigned char hex = hexStr.at(i);
		hex -= 0x30;//digits 0-9
		if(hex > 9)//Uppercase or lowercase letter
			hex -= 0x07;//'A' - '0' + 10
		if(hex > 15)//lowercase letter
			hex -= 0x20;//'a' - 'A' - '0' + 10
		nRes = (nRes << 4 ) | hex;
	} // End of 'while' statement
	
// #ifdef DEBUG_LOG
	// logfile << "o<<< ct2int: " << v << std::endl;
	// logfile.close();
// #endif
	return v;
#ifdef DEBUG_LOG
	 logfile << "hex2int int result: " << nRes << std::endl;
	 logfile.close();
#endif
	return nRes;
} // End of function oct2int

namespace t3devlib { namespace gen {
namespace t3devlib { 

#ifdef DIAMETER_ONLY

void PAInit()
{
}

void SAInit()
{
}

void CDInit()
{
}

void PAReset()
{
}

void SAReset()
{
}
#endif

	namespace gen {

//------------------------------------------------------------
/*
type record GTPv1_MSG {
/*type record GTPv1_MSG {
	GTPv1_Header  header,
	octetstring	  body optional
}    
}*/
//============================================================
void GTPv1_MSG::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
@@ -47,61 +73,36 @@ void GTPv1_MSG::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
	std::ofstream logfile("C:\\Temp\\LibGtp.log", std::ios::app);
	logfile << "GTPv1_MSG::PreDecodeField: " << id << std::endl;
#endif
	switch(id) {
	case id_header: // header field
		SetHypFieldIsPresent(id_body, 1);
		break;
	case id_body: // body field
#ifdef DEBUG_LOG
		logfile << "GTPv1_MSG::PreDecodeField: len=" << Get_header().Get_len().GetValueTCIString() << std::endl;
#endif
		if (Get_header().Get_len().GetValueTCIString() == "'0000'O")

	if(id == id_body)// body field
	{
			SetHypFieldIsPresent(id_body, 0); // Omitted
		const std::string hexLen = Get_header().Get_len().GetValueHexa();
#ifdef DEBUG_LOG
			logfile << "GTPv1_MSG::PreDecodeField: id_body is omitted" << std::endl;
		logfile << "GTPv1_MSG::PreDecodeField: len= " << hexLen << std::endl;
#endif
		}
		if (!hexLen.compare("0000"))
			SetHypFieldIsPresent(id, 0); // Omitted
		else 
		{
			int len = 8 * oct2int(Get_header().Get_len().GetValueTCIString());
			if (Get_header().IsPresent(Get_header().id_seqnum)) {
			int len = 8 * hex2int(hexLen);
			if (Get_header().IsPresent(Get_header().id_seqnum))
				len -= 16; // Remove two bytes
			}
			if (Get_header().IsPresent(Get_header().id_npdu_num)) {
			if (Get_header().IsPresent(Get_header().id_npdu_num))
				len -= 8; // Remove one byte
			}
			if (Get_header().IsPresent(Get_header().id_extensionheader)) {
			if (Get_header().IsPresent(Get_header().id_extensionheader))
				len -= 8; // Remove one byte
			}
			SetHypFieldLength(id_body, len); // Final length
			SetHypFieldIsPresent(id, 1);
			SetHypFieldLength(id, len);
#ifdef DEBUG_LOG
			logfile << "GTPv1_MSG::PreDecodeField: id_body length: '" << buffer.GetLength() - buffer.GetPosition() << "' - '" << len << "'" << std::endl;
#endif
		}
		break;
	default:
#ifdef DEBUG_LOG
		logfile << "GTPv1_MSG::PreDecodeField: id# " << id << " is catched by default" << std::endl;
#endif
		break;
	} // End of 'switch' statement
#ifdef DEBUG_LOG
	logfile.close();
#endif
} // End of method GTPv1_MSG::PreDecodeField
	}

void GTPv1_MSG::PostDecode (Buffer& buffer) throw (DecodeError)
{
#ifdef DEBUG_LOG
	std::ofstream logfile("C:\\Temp\\LibGtp.log", std::ios::app);
	logfile << "GTPv1_MSG::PostDecode" << std::endl;
	logfile << "GTPv1_MSG::PreDecodeField: id_header: " << Get_header() << std::endl;
	logfile << "GTPv1_MSG::PreDecodeField: id_body: " << Get_body() << std::endl;
	DumpSource(logfile);
	logfile.close();
#endif
}
} // End of method GTPv1_MSG::PreDecodeField

void GTPv1_MSG::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError)
{
@@ -110,26 +111,19 @@ void GTPv1_MSG::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError
	logfile << "GTPv1_MSG::PreEncodeField: " << field_id << std::endl;
#endif

	switch(field_id) {
	case id_header: // header field
		SetHypFieldIsPresent(field_id, 1);
		break;
	case id_body: // body field
	if(field_id == id_body)// body field
	{
		const std::string hexStr = Get_header().Get_len().GetValueHexa();
#ifdef DEBUG_LOG
		logfile << "GTPv1_MSG::PreEncodeField: Header len: '" << Get_header().Get_len().GetValueTCIString() << "'" << std::endl;
		logfile << "GTPv1_MSG::PreEncodeField: Header len: '" << hexStr << "'" << std::endl;
#endif
		if (Get_header().Get_len().GetValueTCIString() == "'0000'O")
		{
			SetHypFieldIsPresent(id_body, 0); // Omitted
		}
		if (!hexStr.compare("0000"))
			SetHypFieldIsPresent(field_id, 0); // Omitted
		else 
		{
			SetHypFieldIsPresent(id_body, 1);
			SetHypFieldLength(id_body, 8 * oct2int(Get_header().Get_len().GetValueTCIString()));
			SetHypFieldIsPresent(field_id, 1);
			SetHypFieldLength(field_id, 8 * hex2int(hexStr));
		}
		break;
	default:
		break;
	} // End of 'switch' statement
#ifdef DEBUG_LOG
	logfile.close();
@@ -139,13 +133,18 @@ void GTPv1_MSG::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeError
//------------------------------------------------------------
/*
type record GTPv1_Header {
    bitstring version,
    octetstring messagetype,
    octetstring len,
    octetstring teid,
    octetstring seqnum optional,
    octetstring npdu_num optional,
    octetstring extensionheader optional
	Bit3 version,
	Bit1 PT,
	Bit1 spare,
	Bit1 E_flag,
	Bit1 S_flag,
	Bit1 PN_flag,
	Oct1 messagetype,
	Oct2 len,
	Oct4 teid,
	Oct2 seqnum optional,
	Oct1 npdu_num optional,
	Oct1 extensionheader optional
}*/
//============================================================
void GTPv1_Header::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
@@ -154,70 +153,43 @@ void GTPv1_Header::PreDecodeField (int id, Buffer& buffer) throw (DecodeError)
	std::ofstream logfile("C:\\Temp\\LibGtp.log", std::ios::app);
	logfile << "GTPv1_Header::PreDecodeField: " << id << std::endl;
#endif

	Unsigned u5(5);
	unsigned char buff;
	switch(id) {
	case id_version: // Version: GTP release 99 version (1)
		SetHypFieldIsPresent(id_version, 1);
		SetHypFieldLength(id_version, 3); // Three bits length
		break;
	case id_messagetype: // Message Type field
		SetHypFieldIsPresent(id_messagetype, 1);
		SetHypFieldLength(id_messagetype, 8); // One byte length
		// Extract other flag field
		buffer.Read(u5, 5);
#ifdef DEBUG_LOG
		logfile << "GTPv1_Header::PreDecodeField: u5: '" << u5.GetValue() << "'" << std::endl;
#endif
		if (u5.GetValue() == 18) // Is Sequence Number present?
		case id_seqnum:
			buff = Get_S_flag().GetValue().at(0); 
			int nS_flag =  (buff >> 7);
			
			if(nS_flag)
			{
#ifdef DEBUG_LOG
			logfile << "GTPv1_Header::PreDecodeField: optional fields are presents" << std::endl;
#endif
			SetHypFieldIsPresent(id_seqnum, 1);
			SetHypFieldLength(id_seqnum, 16); // Two bytes length
			SetHypFieldIsPresent(id_npdu_num, 1);
			SetHypFieldLength(id_npdu_num, 8); // One byte length
			SetHypFieldIsPresent(id_extensionheader, 1);
			SetHypFieldLength(id_extensionheader, 8); // One byte length
				SetHypFieldIsPresent(id, 1);
				SetHypFieldLength(id, 16); // 2 byte length
			}
			else
				SetHypFieldIsPresent(id, 0);
			break;
		case id_npdu_num:
			buff = Get_PN_flag().GetValue().at(0); 
			int nPN_flag =  (buff >> 7);
			
			if(nPN_flag)
			{
#ifdef DEBUG_LOG
			logfile << "GTPv1_Header::PreDecodeField: id# " << id_seqnum << " is omitted" << std::endl;
#endif
			SetHypFieldIsPresent(id_seqnum, 0); //  Omitted
			if (u5.GetValue() == 17) // Is N-PDU number present?
			{
				SetHypFieldIsPresent(id_npdu_num, 1);
				SetHypFieldLength(id_npdu_num, 8); // One byte length
				SetHypFieldIsPresent(id, 1);//TODO:
				SetHypFieldLength(id, 8); // 1 byte length
			}
			else
				SetHypFieldIsPresent(id, 0);
			break;
		case id_extensionheader:
			buff = Get_E_flag().GetValue().at(0); 
			int nE_flag =  (buff >> 7);
			
			if(nE_flag)
			{
				SetHypFieldIsPresent(id_npdu_num, 0); // Omitted
#ifdef DEBUG_LOG
				logfile << "GTPv1_Header::PreDecodeField: id# " << id_npdu_num << " is omitted" << std::endl;
#endif
			}
			if (u5.GetValue() == 20) // Is Next Extension Header present?
			{
				SetHypFieldIsPresent(id_extensionheader, 1);
				SetHypFieldLength(id_extensionheader, 8); // One byte length
				SetHypFieldIsPresent(id, 1);//TODO:
				SetHypFieldLength(id, 8); // 1 byte length
			}
			else
			{
				SetHypFieldIsPresent(id_extensionheader, 0); // Omitted
#ifdef DEBUG_LOG
				logfile << "GTPv1_Header::PreDecodeField: id# " << id_extensionheader << " is omitted" << std::endl;
#endif
			}
		}
		break;
	case id_len: // Length field
		SetHypFieldLength(id_len, 2 * 8); // Two bytes length
		break;
	case id_teid: // TEID field
		SetHypFieldLength(id_teid, 4 * 8); // Four bytes length
				SetHypFieldIsPresent(id, 0);
			break;
		default:
			break;
@@ -233,20 +205,28 @@ void GTPv1_Header::PreEncodeField (int field_id, Buffer& buffer) throw (EncodeEr
	std::ofstream logfile("C:\\Temp\\LibGtp.log", std::ios::app);
	logfile << "GTPv1_Header::PreEncodeField: " << field_id << std::endl;
#endif
	
	unsigned char buff;
	switch(field_id) {
	case id_messagetype: {
			Unsigned u5(5); // Padding to fill flag field
			u5.SetValue(0);
			buffer.Write(u5);
		}
		break;
		case id_seqnum:
		// No break;
			buff = Get_S_flag().GetValue().at(0); 
			int nS_flag =  (buff >> 7);
			
			if(nS_flag)
				SetHypFieldIsPresent(field_id, 0);
			break;
		case id_npdu_num:
		// No break;
			buff = Get_PN_flag().GetValue().at(0); 
			int nPN_flag =  (buff >> 7);
			
			if(!nPN_flag)
				SetHypFieldIsPresent(field_id, 0);
			break;
		case id_extensionheader:
		SetHypFieldIsPresent(field_id, 0); // FIXME Process optional part
			buff = Get_E_flag().GetValue().at(0); 
			int nE_flag =  (buff >> 7);

			if(!nE_flag)
				SetHypFieldIsPresent(field_id, 0);
			break;
	default:
		break;