/*<<<***************************************************************************
The MIT License (MIT)

Copyright(C) 2013 - 2015 Marc Mirti Mancinelli, Christophe Lardau and Philippe Pamart (xdcube.org)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
#Title: xbNetStruct
#Project: xdcBase
////////////////////////////////////////////////////////////////////////////////
#Author: Marc MIRTI MANCINELLI
#History:
<12/02/2014: creation.
12/02/2014: this notice inserted.
***************************************************************************>>>*/
#include "stdafx.h"

#include "xbNetStruct.h"

xbString xbnetLabel(xbnetStatus status)
{
	switch(status)
	{
	case xbnetStatus_Ok : return "OK";
	case xbnetStatus_Created : return "Created";
	case xbnetStatus_Accepted : return "Accepted";
	case xbnetStatus_NoContent : return "No content";
	case xbnetStatus_ResetContent : return "Reset content";
	case xbnetStatus_PartialContent : return "Partial content";
	case xbnetStatus_MultipleChoice : return "Multiple choice";
	case xbnetStatus_Moved : return "Moved";
	case xbnetStatus_Found : return "Found";
	case xbnetStatus_NotModified : return "Not modified";
	case xbnetStatus_UseProxy : return "Use proxy";
	case xbnetStatus_TemporaryRedirect : return "Temporary redirect";

	case xbnetStatus_BadRequest : return "Bad request";
	case xbnetStatus_AuthentificationReq : return "Authentification required";
	case xbnetStatus_Forbidden : return "Forbidden";
	case xbnetStatus_NotFound : return "Not found";
	case xbnetStatus_NotAllowed : return "Not allowed";
	case xbnetStatus_NotAcceptable : return "Not acceptable";
	case xbnetStatus_ProxyAuthentificationReq : return "Proxy authentification required";
	case xbnetStatus_TimeOut : return "Time out";
	case xbnetStatus_Conflict : return "Conflict";
	case xbnetStatus_Gone : return "Gone";
	case xbnetStatus_LengthReq : return "Length required";
	case xbnetStatus_PrecondFailed : return "Precondition failed";
	case xbnetStatus_EntityTooLarge : return "Entity too large";
	case xbnetStatus_UrlTooLong : return "Url too long";
	case xbnetStatus_UnsupportedMediaType : return "Unsupported media type";
	case xbnetStatus_BadRange : return "Bad range";
	case xbnetStatus_ExceptationFailed : return "Exceptation failed";

	case xbnetStatus_InternalError : return "Server error";
	case xbnetStatus_NotImpl : return "Not implemented";
	case xbnetStatus_BadGateway : return "Bad gateway";
	case xbnetStatus_ServiceUnavailable : return "Service unavailable";
	case xbnetStatus_GatewayTimeout : return "Gateway timeout";
	case xbnetStatus_ProtoVersionNotSupported : return "Protocol version not supported";
	case xbnetStatus_Continue : return "Continue";
	case xbnetStatus_RitaContinue : return "RITA continue";
	}
	return "??";
}

unsigned long xbnetInv32(unsigned long nb)
{
	char *pNb = (char*)&nb;
	char ch;

	ch = pNb[0];
	pNb[0] = pNb[3];
	pNb[3] = ch;

	ch = pNb[1];
	pNb[1] = pNb[2];
	pNb[2] = ch;

	return nb;
}

uint64 xbnetInv64(uint64 nb)
{
	char *pNb = (char*)&nb;
	char ch;

	ch = pNb[0];
	pNb[0] = pNb[7];
	pNb[7] = ch;

	ch = pNb[1];
	pNb[1] = pNb[6];
	pNb[6] = ch;

	ch = pNb[2];
	pNb[2] = pNb[5];
	pNb[5] = ch;

	ch = pNb[3];
	pNb[3] = pNb[4];
	pNb[4] = ch;

	return nb;
}

#ifdef xbnetEPRO_SUPPORT
/*************************************************************************
 * I - Frame used by client to init connection                           *
 *************************************************************************/
void xbnetFrameCusInit_Init(struct xbnetFrameCusInit *pFrame)
{
	xbAssert(sizeof(*pFrame) == 8);
	pFrame->m_hdr.m_cByteFrame = xbnetUlongToCom(sizeof(*pFrame));
	pFrame->m_hdr.m_status = xbnetFrameInit_STATUS;
	pFrame->m_hdr.m_action[0] = xbnetFrameInit_ACT0;
	pFrame->m_hdr.m_action[1] = xbnetFrameInit_ACT1;
	pFrame->m_hdr.m_action[2] = xbnetFrameInit_ACT2;
}

bool xbnetFrameCusInit_Check(const struct xbnetFrameCusInit *pFrame)
{
	if (pFrame->m_hdr.m_cByteFrame != xbnetUlongToCom(sizeof(*pFrame)))
		return false;
	if (pFrame->m_hdr.m_status != xbnetFrameInit_STATUS)
		return false;
	if (pFrame->m_hdr.m_action[0] != xbnetFrameInit_ACT0)
		return false;
	if (pFrame->m_hdr.m_action[1] != xbnetFrameInit_ACT1)
		return false;
	if (pFrame->m_hdr.m_action[2] != xbnetFrameInit_ACT2)
		return false;

	return true;
}

#ifdef xbnetCPP
bool xbnetFrameCusInit::Check()
{
	return xbnetFrameCusInit_Check(this);
}
xbnetFrameCusInit::xbnetFrameCusInit()
{
	xbnetFrameCusInit_Init(this);
}
#endif


/*************************************************************************
 * II - Frame used by server to answer to connection init                *
 *************************************************************************/
void xbnetFrameSrvInit_Init(struct xbnetFrameSrvInit *pFrame)
{
	xbAssert(sizeof(*pFrame) == 32);
	pFrame->m_hdr.m_cByteFrame = xbnetUlongToCom(sizeof(*pFrame));
	pFrame->m_hdr.m_status = xbnetFrameInit_STATUS;
	pFrame->m_hdr.m_action[0] = xbnetFrameInit_ACT0;
	pFrame->m_hdr.m_action[1] = xbnetFrameInit_ACT1;
	pFrame->m_hdr.m_action[2] = xbnetFrameInit_ACT2;
	pFrame->m_cp = 0;
	pFrame->m_rsrv = 0;
	pFrame->m_keyCrypt1 = 0;
	pFrame->m_keyCrypt2 = 0;
}

bool xbnetFrameSrvInit_Check(const struct xbnetFrameSrvInit *pFrame)
{
	if (pFrame->m_hdr.m_cByteFrame != xbnetUlongToCom(sizeof(*pFrame)))
		return false;
	if (pFrame->m_hdr.m_status != xbnetFrameInit_STATUS)
		return false;
	if (pFrame->m_hdr.m_action[0] != xbnetFrameInit_ACT0)
		return false;
	if (pFrame->m_hdr.m_action[1] != xbnetFrameInit_ACT1)
		return false;
	if (pFrame->m_hdr.m_action[2] != xbnetFrameInit_ACT2)
		return false;

	return true;
}

#ifdef xbnetCPP
bool xbnetFrameSrvInit::Check()
{
	return xbnetFrameSrvInit_Check(this);
}
xbnetFrameSrvInit::xbnetFrameSrvInit()
{
	xbnetFrameSrvInit_Init(this);
}
#endif


/*Communication encryption */
bool xbnetCryptOk(uint64 keyCrypt1,uint64 keyCrypt2)
{
	register uint64 kc = keyCrypt1;
	register int cb = 0;
	while(kc)
	{
		if (kc & 0x1) cb++;
		kc>>=1;
	}
	if (cb <= 4 || cb > 50) return false;
	kc = keyCrypt2;
	cb = 0;
	while(kc)
	{
		if (kc & 0x1) cb++;
		kc>>=1;
	}
	return cb > 4 && cb <= 50;
}

void xbnetCryptKeyGen(uint64 *pKeyCrypt1,uint64 *pKeyCrypt2)
{
	uint64 keyCrypt1 = 0,keyCrypt2 = 0;

	srand( (unsigned int)GetTickCount() );

	for(;;)
	{
		/*1*/ keyCrypt1 = rand() + (keyCrypt1 << 8);
		/*2*/ keyCrypt1 = rand() + (keyCrypt1 << 8);
		/*3*/ keyCrypt1 = rand() + (keyCrypt1 << 8);
		/*4*/ keyCrypt1 = rand() + (keyCrypt1 << 8);
		/*5*/ keyCrypt1 = rand() + (keyCrypt1 << 8);
		/*6*/ keyCrypt1 = rand() + (keyCrypt1 << 8);
		/*7*/ keyCrypt1 = rand() + (keyCrypt1 << 8);
		/*8*/ keyCrypt1 = rand() + (keyCrypt1 << 8);

		/*1*/ keyCrypt2 = rand() + (keyCrypt2 << 8);
		/*2*/ keyCrypt2 = rand() + (keyCrypt2 << 8);
		/*3*/ keyCrypt2 = rand() + (keyCrypt2 << 8);
		/*4*/ keyCrypt2 = rand() + (keyCrypt2 << 8);
		/*5*/ keyCrypt2 = rand() + (keyCrypt2 << 8);
		/*6*/ keyCrypt2 = rand() + (keyCrypt2 << 8);
		/*7*/ keyCrypt2 = rand() + (keyCrypt2 << 8);
		/*8*/ keyCrypt2 = rand() + (keyCrypt2 << 8);

		if(xbnetCryptOk(keyCrypt1,keyCrypt2))
		{
			*pKeyCrypt1 = keyCrypt1;
			*pKeyCrypt2 = keyCrypt2;
			return;
		}
	}
}

void xbnetCryptGet(uint64 keyCrypt1,uint64 keyCrypt2,struct xbnetCrypt *pCrypt)
{
	unsigned char	arrKey[xbnetCrypt_KEYSZ+sizeof(long)];
	int	valcnt[256];
	int	keyno = 0;
	uint64	digs;
	register unsigned char ch,ch2,cb;
	int	valcntmax = (xbnetCrypt_KEYSZ>>6)+2,cnt= 0;
	
	xbAssert((xbnetCrypt_KEYSZ % sizeof(long)) == 0 && sizeof(long) == 4);
	memset(valcnt,0,sizeof(valcnt));

	while(keyno < xbnetCrypt_KEYSZ+sizeof(long))
	{
		if (++cnt > 20)
		{
#ifdef xbnetCPP
#	ifdef _DEBUG
			xbDbgOutput("Key generating infinite loop : KeyCrypt1="+xbString(keyCrypt1)+", KeyCrypt2="+xbString(keyCrypt2)+ " (valcntmax="+xbString(valcntmax)+",cnt="+xbString(cnt)+")");
#	endif
			if (cnt > 50)
				xbThrow xbEsys("xbnetCryptGet() error : KeyCrypt1="+xbString(keyCrypt1)+", KeyCrypt2="+xbString(keyCrypt2)+ " (valcntmax="+xbString(valcntmax)+",cnt="+xbString(cnt)+")");
#endif
			valcntmax += 2;
		}
#ifndef _MSC_VER
		digs = (keyCrypt1 & 0x00000000000001FFULL);
#else
		digs = (keyCrypt1 & 0x00000000000001FF);
#endif
		digs <<= 55;
		keyCrypt1 >>= 9;
		keyCrypt1 += digs;
#ifndef _MSC_VER
		digs = (keyCrypt2 & 0xFE00000000000000ULL);
#else
		digs = (keyCrypt2 & 0xFE00000000000000);
#endif
		digs >>= 57;
		keyCrypt2 <<= 7;
		keyCrypt2 += digs;
		digs = (keyCrypt1 >> 8) ^ (keyCrypt2 >> 4);
		ch2 = ch = (unsigned char)(digs & 0xFF);
		cb = 0;
		while(ch2) 
		{
			if (ch2 & 0x1) cb++;
			ch2 >>= 1;
		}
		if (cb < 2 || cb > 7) continue;
		if (valcnt[ch] >= valcntmax) continue;
		valcnt[ch]++;
		arrKey[keyno] = ch;
		keyno++;
		cnt = 0;
	}	
	keyno = 0;
	while(keyno < ((xbnetCrypt_KEYSZ>>2)+1))
	{
		pCrypt->m_arrKey[keyno] = 
			xbnetUlongToCom(*(unsigned long*)&arrKey[keyno<<2]);
		keyno++;
	}
#if defined(xbnetCPP) && defined(_DEBUG)
	xbString str;
	keyno = 0;
	char buf[16];
	while(keyno < xbnetCrypt_KEYSZ+sizeof(long))
	{
		if (keyno > 0) str += ", ";
		_snprintf(buf,sizeof(buf),"%02lX",(ulong)arrKey[keyno]);
		str += buf;
		keyno++;
	}
	xbString str2;
	keyno = 0;
	while(keyno < ((xbnetCrypt_KEYSZ>>2) + 1))
	{
		if (keyno > 0) str2 += ", ";
		_snprintf(buf,sizeof(buf),"%08lX",(ulong)pCrypt->m_arrKey[keyno]);
		str2 += buf;
		keyno++;
	}
	xbDbgOutput("xbnetCryptGet("+xbString(xbnetCrypt_KEYSZ)+") : uc="+str);
	xbDbgOutput("xbnetCryptGet("+xbString(xbnetCrypt_KEYSZ)+") : ul="+str2);
#endif
}
#endif

void xbnetEncrypt(const struct xbnetCrypt *pCrypt,int sz,
				const void *_pSrce,void *_pDest)
{
	register const unsigned long	*pSrce = (const unsigned long *)_pSrce;
	register unsigned long			res = -1;
	register unsigned long			*pDest = (unsigned long *)_pDest,
		*pDestEnd = (unsigned long *)((char*)_pDest + sz);
	register const unsigned long	*pKey = pCrypt->m_arrKey;
	register const unsigned long	*pKeyEnd = pKey + (xbnetCrypt_KEYSZ>>2);

	xbAssert((xbnetCrypt_KEYSZ % sizeof(long)) == 0 && sizeof(long) == 4);

	while((pDest+1) <= pDestEnd)
	{
		res = *pDest = ((*pSrce + *pKey - res) ^ (~*(pKey+1)));
		pDest++;
		pSrce++;
		pKey++;
		if (pKey>= pKeyEnd)
			pKey = pCrypt->m_arrKey;
	}
	while(pDest < pDestEnd)
	{
		*(unsigned char*)pDest = 
			(*(unsigned char*)pSrce) ^ ((unsigned char)*pKey);
		pDest = (unsigned long*)(((char*)pDest)+1);
		pSrce = (const unsigned long*)(((char*)pSrce)+1);
		pKey++;
		if (pKey>= pKeyEnd)
			pKey = pCrypt->m_arrKey;
	}
}

void xbnetDecrypt(const struct xbnetCrypt *pCrypt,int sz,
				const void *_pSrce,void *_pDest)
{
	register const unsigned long	*pSrce = (const unsigned long *)_pSrce;
	register unsigned long			res = -1;
	register unsigned long			*pDest = (unsigned long *)_pDest,
		*pDestEnd = (unsigned long *)((char*)_pDest + sz);
	register const unsigned long	*pKey = pCrypt->m_arrKey;
	register const unsigned long	*pKeyEnd = pKey + (xbnetCrypt_KEYSZ>>2);

	xbAssert((xbnetCrypt_KEYSZ % sizeof(long)) == 0 && sizeof(long) == 4);

	while((pDest+1) <= pDestEnd)
	{
		*pDest = (*pSrce ^ (~*(pKey+1))) - *pKey + res;
		res = *(pSrce++);
		pDest++;
		pKey++;
		if (pKey>= pKeyEnd)
			pKey = pCrypt->m_arrKey;
	}
	while(pDest < pDestEnd)
	{
		*(unsigned char*)pDest = 
			(*(unsigned char*)pSrce) ^ ((unsigned char)*pKey);
		pDest = (unsigned long*)(((char*)pDest)+1);
		pSrce = (const unsigned long*)(((char*)pSrce)+1);
		pKey++;
		if (pKey>= pKeyEnd)
			pKey = pCrypt->m_arrKey;
	}
}


/*************************************************************************
 * III - Frame used by client to start connection                        *
 *************************************************************************/
bool xbnetFrameCusConnect_Check(const struct xbnetFrameCusConnect *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame)
		|| xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) - sizeof(*pFrame) 
		!= xbnetComToUlong(pFrame->m_cByteVars))
		return false;

//	if (pFrame->m_hdr.m_status != 0)
//		return false;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'C')
			return false;
		if (buf[1] != 'O')
			return false;
		if (buf[2] != 'N')
			return false;
	}
	else
	{
#endif
		if (pFrame->m_hdr.m_action[0] != 'C')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'O')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'N')
			return false;
#ifdef xbnetEBCDIC
	}
#endif

	return true;
}

#ifdef xbnetCPP
bool xbnetFrameCusConnect::Check(
#	ifdef xbnetEBCDIC
							 TEBCDICmap *pMap
#	endif
							   )
{
	return xbnetFrameCusConnect_Check(this
#	ifdef xbnetEBCDIC
							 ,pMap
#	endif
		);
}
#endif

void xbnetFrameCusConnect_Init(struct xbnetFrameCusConnect *pFrame,
							 const char *pszService
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
#ifdef xbnetEBCDIC
	int lgSrv;
#endif
	xbAssert(sizeof(*pFrame) == 24);
	pFrame->m_hdr.m_cByteFrame = 0;
	pFrame->m_hdr.m_status = 0;
	memset(pFrame->m_service,0,sizeof(pFrame->m_service));
#ifdef xbnetEBCDIC
	if (pMap)
	{
		pMap->ToEBCDIC((BYTE*)"CON",(BYTE*)pFrame->m_hdr.m_action,3);
		lgSrv = (int)strlen(pszService);
		xbAssert(lgSrv < sizeof(pFrame->m_service));
		if (lgSrv >= sizeof(pFrame->m_service))
			lgSrv = sizeof(pFrame->m_service) - 1;
		pMap->ToEBCDIC((BYTE*)pszService,(BYTE*)pFrame->m_service,lgSrv);
	}
	else
	{
#endif
		pFrame->m_hdr.m_action[0] = 'C';
		pFrame->m_hdr.m_action[1] = 'O';
		pFrame->m_hdr.m_action[2] = 'N';
		strncpy(pFrame->m_service,pszService,sizeof(pFrame->m_service)-1);
#ifdef xbnetEBCDIC
	}
#endif
	pFrame->m_cByteVars = 0;
}

#if defined(xbnetCPP)
xbnetFrameCusConnect::xbnetFrameCusConnect(
			const char *pszService
#	ifdef xbnetEBCDIC
			,TEBCDICmap *pMap
#	endif
									   )
{
	xbnetFrameCusConnect_Init(this,pszService
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
#endif


/*************************************************************************
 * IV - Frame used by server to answer to connection or execution ask    *
 *************************************************************************/
void xbnetFrameSrvRtn_Init(struct xbnetFrameSrvRtn *pFrame,
							 bool bErr
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	xbAssert(sizeof(*pFrame) == 12);
	pFrame->m_hdr.m_cByteFrame = 0;
	pFrame->m_hdr.m_status = 0;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		pMap->ToEBCDIC((BYTE*)(bErr?"ERR":"RTN"),
			(BYTE*)pFrame->m_hdr.m_action,3);
	}
	else
	{
#endif
		if (bErr)
		{
			pFrame->m_hdr.m_action[0] = 'E';
			pFrame->m_hdr.m_action[1] = 'R';
			pFrame->m_hdr.m_action[2] = 'R';
		}
		else
		{
			pFrame->m_hdr.m_action[0] = 'R';
			pFrame->m_hdr.m_action[1] = 'T';
			pFrame->m_hdr.m_action[2] = 'N';
		}
#ifdef xbnetEBCDIC
	}
#endif
	pFrame->m_cByteRtns = 0;
}

bool xbnetFrameSrvRtn_IsErr(struct xbnetFrameSrvRtn *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame)
		|| xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) - sizeof(*pFrame) 
			!= xbnetComToUlong(pFrame->m_cByteRtns))
		return false;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'E')
			return false;
		if (buf[1] != 'R')
			return false;
		if (buf[2] != 'R')
			return false;
	}
	else
	{
#endif
		if (pFrame->m_hdr.m_action[0] != 'E')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'R')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'R')
			return false;
#ifdef xbnetEBCDIC
	}
#endif
	return true;
}

bool xbnetFrameSrvRtn_IsRtn(struct xbnetFrameSrvRtn *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame)
		|| xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) - sizeof(*pFrame) 
			!= xbnetComToUlong(pFrame->m_cByteRtns))
		return false;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'R')
			return false;
		if (buf[1] != 'T')
			return false;
		if (buf[2] != 'N')
			return false;
	}
	else
	{
#endif
		if (pFrame->m_hdr.m_action[0] != 'R')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'T')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'N')
			return false;
#ifdef xbnetEBCDIC
	}
#endif
	return true;
}

#if defined(xbnetCPP)
xbnetFrameSrvRtn::xbnetFrameSrvRtn(
			bool bErr
#	ifdef xbnetEBCDIC
			,TEBCDICmap *pMap
#	endif
			)
{
	xbnetFrameSrvRtn_Init(this,bErr
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
bool xbnetFrameSrvRtn::IsErr(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
						   )
{
	return xbnetFrameSrvRtn_IsErr(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}

bool xbnetFrameSrvRtn::IsRtn(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
						   )
{
	return xbnetFrameSrvRtn_IsRtn(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
#endif


/*************************************************************************
 * V - Frame used by client to send execution context to server          *
 *************************************************************************/
void xbnetFrameCusCtx_Init(struct xbnetFrameCusCtx *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	xbAssert(sizeof(*pFrame) == 16);
	pFrame->m_hdr.m_cByteFrame = 0;
	pFrame->m_hdr.m_status = 0;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		pMap->ToEBCDIC((BYTE*)"CTX",(BYTE*)pFrame->m_hdr.m_action,3);
	}
	else
	{
#endif
		pFrame->m_hdr.m_action[0] = 'C';
		pFrame->m_hdr.m_action[1] = 'T';
		pFrame->m_hdr.m_action[2] = 'X';
#ifdef xbnetEBCDIC
	}
#endif
	pFrame->m_cByteEnvs = 0;
	pFrame->m_cByteVars = 0;
}

#if defined(xbnetCPP)
xbnetFrameCusCtx::xbnetFrameCusCtx(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
			)
{
	xbnetFrameCusCtx_Init(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
#endif


bool xbnetFrameCusCtx_Check(struct xbnetFrameCusCtx *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame)
		|| xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) - sizeof(*pFrame) 
			!= xbnetComToUlong(pFrame->m_cByteEnvs) 
			+ xbnetComToUlong(pFrame->m_cByteVars))
		return false;

//	if (pFrame->m_hdr.m_status != 0)
//		return false;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'C')
			return false;
		if (buf[1] != 'T')
			return false;
		if (buf[2] != 'X')
			return false;
	}
	else
	{
#endif
		if (pFrame->m_hdr.m_action[0] != 'C')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'T')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'X')
			return false;
#ifdef xbnetEBCDIC
	}
#endif

	return true;
}

#ifdef xbnetCPP
bool xbnetFrameCusCtx::Check(
#	ifdef xbnetEBCDIC
				 TEBCDICmap *pMap
#	endif
				 )
{
	return xbnetFrameCusCtx_Check(this
#	ifdef xbnetEBCDIC
							 ,pMap
#	endif
								 );
}
#endif


/*************************************************************************
 * VI - Frame used by client to execute a module                         *
 *************************************************************************/
void xbnetFrameCusExec_Init(struct xbnetFrameCusExec *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	xbAssert(sizeof(*pFrame) == 16);
	pFrame->m_hdr.m_cByteFrame = 0;
	pFrame->m_hdr.m_status = 0;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		pMap->ToEBCDIC((BYTE*)"MOD",(BYTE*)pFrame->m_hdr.m_action,3);
	}
	else
	{
#endif
		pFrame->m_hdr.m_action[0] = 'M';
		pFrame->m_hdr.m_action[1] = 'O';
		pFrame->m_hdr.m_action[2] = 'D';
#ifdef xbnetEBCDIC
	}
#endif
	pFrame->m_cByteMod = 0;
	pFrame->m_cBytePrms = 0;
}

#if defined(xbnetCPP)
xbnetFrameCusExec::xbnetFrameCusExec(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
									   )
{
	xbnetFrameCusExec_Init(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
#endif

bool xbnetFrameCusExec_Check(struct xbnetFrameCusExec *pFrame
#ifdef xbnetEBCDIC
			,TEBCDICmap *pMap
#endif
			)
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame)
		|| xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) - sizeof(*pFrame) 
			!= xbnetComToUlong(pFrame->m_cByteMod) 
			+ xbnetComToUlong(pFrame->m_cBytePrms))
		return false;

//	if (pFrame->m_hdr.m_status != 0)
//		return false;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'M')
			return false;
		if (buf[1] != 'O')
			return false;
		if (buf[2] != 'D')
			return false;
	}
	else
	{
#endif
		if (pFrame->m_hdr.m_action[0] != 'M')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'O')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'D')
			return false;
#ifdef xbnetEBCDIC
	}
#endif

	return true;
}

#ifdef xbnetCPP
bool xbnetFrameCusExec::Check(
#	ifdef xbnetEBCDIC
						 TEBCDICmap *pMap
#	endif
						 )
{
	return xbnetFrameCusExec_Check(this
#	ifdef xbnetEBCDIC
						 ,pMap
#	endif
							 );
}
#endif

/***************************************************************************
 * VII - Htlp Frame used by client and server for complex request or answer*
 ***************************************************************************/
void xbnetFrameHtlp_Init(struct xbnetFrameHtlp *pFrame,
							 xbOpMode opm
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	xbAssert(sizeof(*pFrame) == 40);
	pFrame->m_hdr.m_cByteFrame = 0;
	pFrame->m_hdr.m_status = 0;
#	ifdef xbnetEBCDIC
	if (pMap)
	{
		pMap->ToEBCDIC((BYTE*)(opm == xbOp_Required?"HTR":"HTA"),
			(BYTE*)pFrame->m_hdr.m_action,3);
	}
	else
	{
#	endif
		if (opm == xbOp_Required)
		{
			pFrame->m_hdr.m_action[0] = 'H';
			pFrame->m_hdr.m_action[1] = 'T';
			pFrame->m_hdr.m_action[2] = 'R';
		}
		else
		{
			pFrame->m_hdr.m_action[0] = 'H';
			pFrame->m_hdr.m_action[1] = 'T';
			pFrame->m_hdr.m_action[2] = 'A';
		}
#	ifdef xbnetEBCDIC
	}
#	endif
	pFrame->m_main.m_offset = 0;
	pFrame->m_main.m_contain = 0;
	pFrame->m_ctx.m_offset = 0;
	pFrame->m_ctx.m_contain = 0;
	pFrame->m_record.m_offset = 0;
	pFrame->m_record.m_contain = 0;
	pFrame->m_data.m_offset = 0;
	pFrame->m_data.m_contain = 0;
}

bool xbnetFrameHtlp_IsRequest(struct xbnetFrameHtlp *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame))
		return false;
#	ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'H')
			return false;
		if (buf[1] != 'T')
			return false;
		if (buf[2] != 'R')
			return false;
	}
	else
	{
#	endif
		if (pFrame->m_hdr.m_action[0] != 'H')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'T')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'R')
			return false;
#	ifdef xbnetEBCDIC
	}
#	endif
	return true;
}

bool xbnetFrameHtlp_IsAnswer(struct xbnetFrameHtlp *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame))
		return false;
#	ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'H')
			return false;
		if (buf[1] != 'T')
			return false;
		if (buf[2] != 'A')
			return false;
	}
	else
	{
#	endif
		if (pFrame->m_hdr.m_action[0] != 'H')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'T')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'A')
			return false;
#	ifdef xbnetEBCDIC
	}
#	endif
	return true;
}

#if defined(xbnetCPP)
xbnetFrameHtlp::xbnetFrameHtlp(
			xbOpMode opm
#	ifdef xbnetEBCDIC
			,TEBCDICmap *pMap
#	endif
			)
{
	xbnetFrameHtlp_Init(this,opm
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
bool xbnetFrameHtlp::IsRequest(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
						   )
{
	return xbnetFrameHtlp_IsRequest(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}

bool xbnetFrameHtlp::IsAnswer(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
						   )
{
	return xbnetFrameHtlp_IsAnswer(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
#endif

/*************************************************************************
 * VIII - Frame used for compression                                     *
 *************************************************************************/
void xbnetFrameEncode_Init(struct xbnetFrameEncode *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	xbAssert(sizeof(*pFrame) == 12);
	pFrame->m_hdr.m_cByteFrame = 0;
	pFrame->m_hdr.m_status = 0;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		pMap->ToEBCDIC((BYTE*)"ENC",(BYTE*)pFrame->m_hdr.m_action,3);
	}
	else
	{
#endif
		pFrame->m_hdr.m_action[0] = 'E';
		pFrame->m_hdr.m_action[1] = 'N';
		pFrame->m_hdr.m_action[2] = 'C';
#ifdef xbnetEBCDIC
	}
#endif
	pFrame->m_cByteType = 0;
}

#if defined(xbnetCPP)
xbnetFrameEncode::xbnetFrameEncode(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
									   )
{
	xbnetFrameEncode_Init(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
#endif

bool xbnetFrameEncode_Check(struct xbnetFrameEncode *pFrame
#	ifdef xbnetEBCDIC
			,TEBCDICmap *pMap
#	endif
			)
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < 
		sizeof(*pFrame) + pFrame->m_cByteType)
		return false;

#ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'E')
			return false;
		if (buf[1] != 'N')
			return false;
		if (buf[2] != 'C')
			return false;
	}
	else
	{
#endif
		if (pFrame->m_hdr.m_action[0] != 'E')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'N')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'C')
			return false;
#ifdef xbnetEBCDIC
	}
#endif

	return true;
}

#ifdef xbnetCPP
bool xbnetFrameEncode::Check(
#	ifdef xbnetEBCDIC
						 TEBCDICmap *pMap
#	endif
						 )
{
	return xbnetFrameEncode_Check(this
#ifdef xbnetEBCDIC
						 ,pMap
#endif
							 );
}
#endif


/*************************************************************************
 * Others frames    *
 *************************************************************************/
void xbnetFrameRaw_Init(struct xbnetFrameRaw *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	xbAssert(sizeof(*pFrame) == 12);
	pFrame->m_hdr.m_cByteFrame = 0;
	pFrame->m_hdr.m_status = 0;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		pMap->ToEBCDIC((BYTE*)("RAW"),
			(BYTE*)pFrame->m_hdr.m_action,3);
	}
	else
	{
#endif
		pFrame->m_hdr.m_action[0] = 'R';
		pFrame->m_hdr.m_action[1] = 'A';
		pFrame->m_hdr.m_action[2] = 'W';
#ifdef xbnetEBCDIC
	}
#endif
	pFrame->m_rawMode = 0;
}

bool xbnetFrameRaw_Check(struct xbnetFrameRaw *pFrame
#ifdef xbnetEBCDIC
							 ,TEBCDICmap *pMap
#endif
							 )
{
	if (xbnetComToUlong(pFrame->m_hdr.m_cByteFrame) < sizeof(*pFrame))
		return false;
#ifdef xbnetEBCDIC
	if (pMap)
	{
		char buf[3];
		pMap->ToASCII((BYTE*)pFrame->m_hdr.m_action,(BYTE*)buf,3);
		if (buf[0] != 'R')
			return false;
		if (buf[1] != 'A')
			return false;
		if (buf[2] != 'W')
			return false;
	}
	else
	{
#endif
		if (pFrame->m_hdr.m_action[0] != 'R')
			return false;
		if (pFrame->m_hdr.m_action[1] != 'A')
			return false;
		if (pFrame->m_hdr.m_action[2] != 'W')
			return false;
#ifdef xbnetEBCDIC
	}
#endif
	return true;
}


#if defined(xbnetCPP)
xbnetFrameRaw::xbnetFrameRaw(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
			)
{
	xbnetFrameRaw_Init(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
bool xbnetFrameRaw::Check(
#	ifdef xbnetEBCDIC
			TEBCDICmap *pMap
#	endif
						   )
{
	return xbnetFrameRaw_Check(this
#	ifdef xbnetEBCDIC
			,pMap
#	endif
		);
}
#endif
