#include "StdAfx.h"
#include "IClientImpl.h"
#include <comdef.h>
#include <atlbase.h>
#include "ThreadPool.hpp"

const int AF_IPV4   = 0;
const int AF_IPV6   = 1;
const int SOCK_TCP  = SOCK_STREAM-1;
const int SOCK_UDP  = SOCK_DGRAM-1;

//IClientImpl* IClientImpl::m_pTcpClient[TCPCLIENTNUM] = {NULL};

IClientImpl::IClientImpl():m_nMode(AF_IPV4)
,m_nSockType(SOCK_TCP) 
{
	m_bSocket = FALSE;
	m_SocketClient.SetInterface(this);
}

IClientImpl::~IClientImpl()
{
	m_SocketClient.Terminate();
}

void IClientImpl::GetAddress(const SockAddrIn& addrIn, CString& rString) const
{
	TCHAR szIPAddr[MAX_PATH] = { 0 };
	CSocketHandle::FormatIP(szIPAddr, MAX_PATH, addrIn);
	rString.Format(_T("%s : %d"), szIPAddr, static_cast<int>(static_cast<UINT>(ntohs(addrIn.GetPort()))) );
}

void IClientImpl::AppendText(LPCTSTR lpszFormat, ...)
{
	//	if ( !::IsWindow(m_ctlMsgList.GetSafeHwnd()) ) return;
	//	TCHAR szBuffer[512];
	//	HWND hWnd = m_ctlMsgList.GetSafeHwnd();
	//	DWORD dwResult = 0;
	//	if (SendMessageTimeout(hWnd, WM_GETTEXTLENGTH, 0, 0, SMTO_NORMAL, 500L, &dwResult) != 0)
	//	{
	//		int nLen = (int) dwResult;
	//		if (SendMessageTimeout(hWnd, EM_SETSEL, nLen, nLen, SMTO_NORMAL, 500L, &dwResult) != 0)
	//		{
	//			size_t cb = 0;
	//			va_list args;
	//			va_start(args, lpszFormat);
	//			::StringCchVPrintfEx(szBuffer, 512, NULL, &cb, 0, lpszFormat, args);
	//			va_end(args);
	//			SendMessageTimeout(hWnd, EM_REPLACESEL, FALSE, reinterpret_cast<LPARAM>(szBuffer), SMTO_NORMAL, 500L, &dwResult);
	//		}
	//	}
}

bool IClientImpl::GetDestination(SockAddrIn& addrIn) const
{
	CString strPort;
	int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
	return addrIn.CreateFrom(NULL, strPort, nFamily);
}

bool IClientImpl::SetupMCAST()
{
	const TCHAR szIPv4MCAST[] = TEXT("239.121.1.2");
	const TCHAR szIPv6MCAST[] = TEXT("FF02:0:0:0:0:0:0:1"); // All Nodes local address
	bool result = false;
	if ( m_nSockType == SOCK_UDP )
	{
		if ( m_nMode == AF_IPV4 ) {
			result = m_SocketClient->AddMembership(szIPv4MCAST, NULL);
		} else {
			result = m_SocketClient->AddMembership(szIPv6MCAST, NULL);
			HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
			hr = hr;
		}
	}
	return result;
}

///////////////////////////////////////////////////////////////////////////////

void IClientImpl::OnThreadBegin(CSocketHandle* pSH)
{
	ASSERT( pSH == m_SocketClient );
	(pSH);
	CString strAddr;
	SockAddrIn sockAddr;
	m_SocketClient->GetSockName(sockAddr);
	GetAddress( sockAddr, strAddr );
	InitializeCriticalSection(&pSH->m_hClient2SrvSection);
}

void IClientImpl::OnThreadExit(CSocketHandle* pSH)
{
	ASSERT( pSH == m_SocketClient );
	DeleteCriticalSection( &pSH->m_hClient2SrvSection );
	(pSH);
}

void IClientImpl::OnConnectionDropped(CSocketHandle* pSH)
{
	ASSERT( pSH == m_SocketClient );
	(pSH);
	AppendText( _T("Connection lost with client.\r\n") );
}

void IClientImpl::OnConnectionError(CSocketHandle* pSH, DWORD dwError)
{
	ASSERT( pSH == m_SocketClient );
	(pSH);
	_com_error err(dwError);
	AppendText( _T("Communication Error:\r\n%s\r\n"), err.ErrorMessage() );
}

void IClientImpl::OnDataReceived(CSocketHandle* pSH, const BYTE* pbData, DWORD dwCount, const SockAddrIn& addr)
{
	ASSERT( pSH == m_SocketClient );
	(pSH);

	if( !m_SocketClient->IsOpen() ) return;

	// 处理接收回来的数据;
	ToprocessRecivebuf(pSH,pbData,dwCount);
}

void IClientImpl::ToprocessRecivebuf(IN CSocketHandle *pSockHandle, IN const BYTE* pReceivebuf, IN DWORD dwReceiveSize)
{
	STProtocolheader *pHeader;
	if ( pSockHandle->m_npendingSize == 0 )
	{
		pHeader = (STProtocolheader *)(pReceivebuf);

		if ( dwReceiveSize < pHeader->nDataLen )	// 不足一个完整包;
		{
			pSockHandle->m_npendingSize = dwReceiveSize + sizeof(STProtocolheader);
			memcpy(pSockHandle->m_szpendingbuf,pReceivebuf,pSockHandle->m_npendingSize);
		}
		else if ( dwReceiveSize >= pHeader->nDataLen )	// 粘包;	
		{
			if( -1 == OnIntegrityPacket(pSockHandle,pHeader))
			{
				;
			}

			// 处理剩余数据;
			pSockHandle->m_npendingSize = dwReceiveSize - sizeof(STProtocolheader) - pHeader->nDataLen;
			if(pSockHandle->m_npendingSize != 0)
				memcpy(pSockHandle->m_szpendingbuf,pReceivebuf+sizeof(STProtocolheader)+pHeader->nDataLen,pSockHandle->m_npendingSize);
		}
	}
	else if ( pSockHandle->m_npendingSize > 0 )
	{
		pHeader = (STProtocolheader *)pSockHandle->m_szpendingbuf;

		if ( pSockHandle->m_npendingSize > pHeader->nDataLen+sizeof(STProtocolheader) )
		{
			// 异常处理:出现缓存数据大于完整包数据长度;
		}

		if ( pHeader->nDataLen+sizeof(STProtocolheader) - pSockHandle->m_npendingSize > dwReceiveSize )	// 还是没有收够一个完整的包;
		{
			memcpy(pSockHandle->m_szpendingbuf+pSockHandle->m_npendingSize,pReceivebuf,dwReceiveSize);
			pSockHandle->m_npendingSize += dwReceiveSize;
		}
		else if ( pHeader->nDataLen+sizeof(STProtocolheader) - pSockHandle->m_npendingSize <= dwReceiveSize )	// 收够完整的包;
		{
			// 完整的包;
			memcpy(pSockHandle->m_szpendingbuf+pSockHandle->m_npendingSize,pReceivebuf,pHeader->nDataLen+sizeof(STProtocolheader) - pSockHandle->m_npendingSize);
			pSockHandle->m_npendingSize += dwReceiveSize - pHeader->nDataLen;
			if( -1 == OnIntegrityPacket(pSockHandle,pHeader))
			{
				;
			}

			// 处理剩余数据;
			memset(pSockHandle->m_szpendingbuf,0,pSockHandle->m_npendingSize);
			if ( pSockHandle->m_npendingSize != 0)
				memcpy(pSockHandle->m_szpendingbuf,pReceivebuf+dwReceiveSize-pSockHandle->m_npendingSize,pSockHandle->m_npendingSize);
		}
	}
}

int IClientImpl::OnIntegrityPacket(IN CSocketHandle *pSockHandle, IN void *pIntegrityPacket)
{
	STProtocolheader *pHeader = (STProtocolheader *)pIntegrityPacket;

	if( pHeader == NULL || pHeader->bof != PBOF)
		return -1;

	if( pHeader->nDataLen < 0 || pHeader->nDataLen > 65535 ) 
		return -1;

	unsigned int tmp = VerityIntegrityPacket(pHeader, pHeader->nDataLen);
	if(tmp != pHeader->nVerify)  
	{	
		return -1;
	}

	switch (pHeader->nCmd)              
	{
	case 1:
		break;
	default: return 0;
	}

	return 0;
}

unsigned int IClientImpl::VerityIntegrityPacket(IN void *pIntegrityPacket,unsigned int nPacketSize)
{
	unsigned int checksum = 0;
	unsigned char *pBody = &((unsigned char*)pIntegrityPacket)[sizeof(STProtocolheader)];

	if( pBody )
		checksum = crc32( 0, pBody, nPacketSize );

	return checksum;
}


BOOL IClientImpl::Initialize()
{
	TCHAR szIPAddr[MAX_PATH] = { 0 };
	CSocketHandle::GetLocalAddress(szIPAddr, MAX_PATH, AF_INET);
	AppendText(_T("Local Address (IPv4): %s\r\n"), szIPAddr);
	CSocketHandle::GetLocalAddress(szIPAddr, MAX_PATH, AF_INET6);
	AppendText(_T("Local Address (IPv6): %s\r\n"), szIPAddr);

	return TRUE;
}


BOOL IClientImpl::ConnectServer(LPCTSTR strAddr, LPCTSTR strPort)
{
	int nFamily = (m_nMode == AF_IPV4) ? AF_INET : AF_INET6;
	if ( !m_SocketClient.StartClient(NULL, strAddr, strPort, nFamily, (m_nSockType+1) ) )
	{
		m_bSocket = FALSE;
		//LOG4C((LOG_NOTICE, "连接失败 [%s, %s, %d, %d]",strAddr, strPort, nFamily, (m_nSockType+1)));
		//AfxMessageBox(NULL, _T("连接服务器失败！"), "提示", MB_ICONSTOP);
		return FALSE;
	}
	else
	{
		m_bSocket = TRUE;
		CSocketHandle* pSH = (CSocketHandle *)m_SocketClient;

		pSH->m_npendingSize = 0;
		memset(pSH->m_szpendingbuf, 0, SOCKET_BUFFSIZE);

		SetupMCAST();
		return TRUE;
	}
}

void IClientImpl::DisConnectServer()
{
	m_SocketClient.Terminate();
}

void IClientImpl::SendMsg(void *pMsg,const int nLen)
{
	if ( m_SocketClient.IsOpen() )
	{
		USES_CONVERSION;
		if (m_nSockType == SOCK_TCP)
		{
			m_SocketClient.Write((const LPBYTE)(pMsg), nLen, NULL);
		}
		else
		{
			SockAddrIn sockAddr;
			GetDestination(sockAddr);
			m_SocketClient.Write((const LPBYTE)(pMsg), nLen, sockAddr);
		}
	}
	else
	{
		AfxMessageBox(_T("Socket is not connected"));
	}
}

// 静态成员函数，提供全局访问的接口
//IClientImpl* IClientImpl::GetInstancePtr( int iTCPIndex )
//{
//	if( NULL == m_pTcpClient[iTCPIndex] )
//	{
//		m_pTcpClient[iTCPIndex] = new IClientImpl();
//	}
//
//	return m_pTcpClient[iTCPIndex];
//}