//ClientTunnel.cpp
#include "stdafx.h"
///////////////////////////////////////////////////////////////////////////////
#include "ClientTunnel.h"
#include "./include/struct_def.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////////////////////////Callback functions////////////////////////////////////
/*Get the header length according to header struct*/
static void netGetDataBufLenCb(IN SOCKET hSocket, IN void *pHeaderBuf, 
							   OUT unsigned long *nDataLen);

/*net event*/
static void netHandleNetEvent(IN SOCKET hSocket, IN ETransportEvent eEvent, 
							  IN void *pDataBuf, IN unsigned long nDataLen, 
							  IN int nError, IN void *pContext);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#pragma comment(lib, "Transport.lib")
CClientTunnel::CClientTunnel()
{
	m_hSocket = INVALID_SOCKET;
}

CClientTunnel::~CClientTunnel()
{
}

int CClientTunnel::net_OpenSocket(IN ETransportType eType, 									 
									 IN unsigned short usPort, 
									 IN LPTRANSPORT_EVENT eventHandler, 									 
									 void *pContext)
{
	TransportStatus status = TRANSPORT_OK;
	
	unsigned long ulHeaderLen = MESSAGE_HEADER_LEN;

	/*Use this layer handle event and context, 
	save the application layer handle event and context*/
	m_eventHandler = eventHandler;
	m_pContext = pContext;

	eventHandler = netHandleNetEvent;
	pContext = this;
	
	LPTRANSPORT_GETDATABUFLEN cbHandler = netGetDataBufLenCb;	
	SOCKET hSocket = CTransportImpl::net_OpenSocket(eType, usPort, 
											eventHandler, 
											cbHandler, 
											ulHeaderLen, 
											pContext);

	if( INVALID_SOCKET == hSocket )
	{
		return TRANSPORT_ERROR;
	}

	m_hSocket = hSocket;

	return status;
}

void CClientTunnel::net_CloseSocket()
{
	CTransportImpl::net_CloseSocket();
}

int CClientTunnel::net_Connect(IN unsigned long ulIPValue, IN unsigned short usPort)
{
	int nResult = TRANSPORT_OK;

	nResult = CTransportImpl::net_Connect(ulIPValue, usPort);
	
	return nResult;
}

unsigned long CClientTunnel::net_Send(IN void *pHeader, 
									  IN void *pMessage, 
									  IN unsigned long ulDataLen)
{
	unsigned long ulSendLen = 0;
	unsigned long ulBufLen = 0;

	TMessageHeader *pSendHeader = (TMessageHeader *)pHeader;

	ulBufLen = MESSAGE_HEADER_LEN + ulDataLen;	
	char *pSendBuf = new char[ulBufLen];
	memset(pSendBuf, 0, ulBufLen);

	TMessageHeader *pMessageHeader = (TMessageHeader *)pSendBuf;
	pMessageHeader->byVersion = 101;
	pMessageHeader->wHeaderFlag = MESSAGE_HEADER_FLAG;
	pMessageHeader->wMessageId = pSendHeader->wMessageId;
	pMessageHeader->wMessageSubId = pSendHeader->wMessageSubId;
	pMessageHeader->dwDataLen = ulDataLen;
	pMessageHeader->wReserve = 0;
	
	memcpy((void *)(pSendBuf+MESSAGE_HEADER_LEN), pMessage, ulDataLen);
	
	/* convert network word */
	htons(pMessageHeader->wHeaderFlag);
	htons(pMessageHeader->wMessageId);
	htons(pMessageHeader->wMessageSubId);
	htonl(pMessageHeader->dwDataLen);
	htons(pMessageHeader->wCheckSum);	
	htonl(pMessageHeader->wReserve);

	/*Send the message*/
	SOCKET hSocket = m_hSocket;
	ulSendLen = CTransportImpl::net_Send(hSocket, (void *)pSendBuf, ulBufLen);
	
	/**/
	delete [] pSendBuf;
	pSendBuf = NULL;


	return ulSendLen;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////callback functions/////////////////////////////
void netGetDataBufLenCb(IN SOCKET hSocket, IN void *pHeaderBuf, 
						OUT unsigned long *nDataLen)
{
	TMessageHeader *pHeader = NULL;
	
	*nDataLen = 0;
	
	pHeader = (TMessageHeader *)pHeaderBuf;
	if( NULL == pHeader )
	{
		return;
	}
	
	if( MESSAGE_HEADER_FLAG != pHeader->wHeaderFlag )
	{
		return;
	}
	
	unsigned long dwDataBufLen = pHeader->dwDataLen;
	ntohl(dwDataBufLen);
	*nDataLen = dwDataBufLen;
	
	return;
}

void netHandleNetEvent(IN SOCKET hSocket, IN ETransportEvent eEvent, 
					   IN void *pDataBuf, IN unsigned long nDataLen, 
					   IN int nError, IN void *pContext)
{
	/*Notify application layer*/
	CClientTunnel *pClientTunnel = (CClientTunnel *)pContext;
	if( NULL == pClientTunnel )
	{
		return;
	}

	void *pUserData = pClientTunnel->m_pContext;

	TransportBool bHandle = TRUE;
	
	if( Transport_ReadEv == eEvent )
	{
		if( nDataLen <= 0 )
		{
			return;
		}
				
				
		/*��ȡ��Ϣͷ�������ϢID*/
		char *pMessageBuf = (char *)pDataBuf;		
		TMessageHeader *pHeader = (TMessageHeader *)pMessageBuf;		
		
		/*�����ֽ�˳���ת��*/
		ntohs(pHeader->wHeaderFlag);
		ntohs(pHeader->wMessageId);
		ntohs(pHeader->wMessageSubId);
		ntohl(pHeader->dwDataLen);
		ntohs(pHeader->wCheckSum);
		ntohl(pHeader->wReserve);

		bHandle = (MESSAGE_HEADER_FLAG == pHeader->wHeaderFlag);
	}
	
	if( bHandle )
	{
		if( NULL != pClientTunnel->m_eventHandler )
		{
			pClientTunnel->m_eventHandler(hSocket, eEvent, 
											pDataBuf, nDataLen, 
											nError, pUserData);
		}
	}
}