#include "stdafx.h"
#include "SSLAgent.h"
#include "../Log/LogMgr.h"


CNetHttpClientListener::CNetHttpClientListener()
{
	m_dwTotalBodyLen = 0;
	m_dwRecvBodyLen = 0;
}

CNetHttpClientListener::~CNetHttpClientListener()
{

}



EnHandleResult CNetHttpClientListener::OnPrepareConnect(ITcpClient* pSender, CONNID dwConnID, SOCKET socket)
{

	return HR_IGNORE;
}
EnHandleResult CNetHttpClientListener::OnConnect(ITcpClient* pSender, CONNID dwConnID)
{
	//Trace("on connect");
	return HR_IGNORE;
}
EnHandleResult CNetHttpClientListener::OnHandShake(ITcpClient* pSender, CONNID dwConnID)
{
	//Trace("handshake");
	return HR_IGNORE;
}
EnHandleResult CNetHttpClientListener::OnReceive(ITcpClient* pSender, CONNID dwConnID, int iLength)
{
	//Trace("recv");
	return HR_IGNORE;
}
EnHandleResult CNetHttpClientListener::OnReceive(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	//Trace("recv2");
	return HR_IGNORE;
}
EnHandleResult CNetHttpClientListener::OnSend(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	return HR_IGNORE;
}

EnHttpParseResult CNetHttpClientListener::OnMessageBegin(IHttpClient* pSender, CONNID dwConnID)
{
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnRequestLine(IHttpClient* pSender, CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)
{
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnStatusLine(IHttpClient* pSender, CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc)
{
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnHeader(IHttpClient* pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
{
	if (strcmp(lpszName, "Content-Length") == 0)
	{
		m_dwTotalBodyLen = atoi(lpszValue);
	}
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnChunkHeader(IHttpClient* pSender, CONNID dwConnID, int iLength)
{
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnChunkComplete(IHttpClient* pSender, CONNID dwConnID)
{
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnUpgrade(IHttpClient* pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
{
	return HPR_OK;
}

EnHandleResult CNetHttpClientListener::OnWSMessageHeader(IHttpClient* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
{
	return HR_IGNORE;
}
EnHandleResult CNetHttpClientListener::OnWSMessageBody(IHttpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	return HR_IGNORE;
}
EnHandleResult CNetHttpClientListener::OnWSMessageComplete(IHttpClient* pSender, CONNID dwConnID)
{
	return HR_IGNORE;
}

EnHttpParseResult CNetHttpClientListener::OnHeadersComplete(IHttpClient* pSender, CONNID dwConnID)
{
	//Trace("headers complete");
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnBody(IHttpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	if (m_dwTotalBodyLen <= 0)
	{
		return HPR_OK;
	}
	m_dwRecvBodyLen += iLength;
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnMessageComplete(IHttpClient* pSender, CONNID dwConnID)
{
	return HPR_OK;
}
EnHttpParseResult CNetHttpClientListener::OnParseError(IHttpClient* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
{
	return HPR_OK;
}
EnHandleResult CNetHttpClientListener::OnClose(ITcpClient* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
	return HR_IGNORE;
}


CSSLAgent*  CSSLAgent::m_instance = nullptr;
CSSLAgent::CSSLAgent():m_bHttps(true), dwRequestTimeout(3000), nRetryTimes(3)
{
	//m_pListener = ::Create_HP_TcpPullClientListener();
	//m_pClient = ::Create_HP_SSLPullClient(m_pListener);
}


CSSLAgent::~CSSLAgent()
{
	//::HP_SSLClient_CleanupSSLContext(m_pClient);
	//::Destroy_HP_SSLPullClient(m_pClient);
	//::Destroy_HP_TcpPullClientListener(m_pListener);
}

void CSSLAgent::SendMsg(HTTP_TYPE enType, string strUrl, string strParam, string &strOut)
{
	CNetHttpClientListener listener;
	IHttpSyncClient* pHttp = NULL;
	if (enType == T_HTTPS_REQUEST_GET || enType == T_HTTPS_REQUEST_POST)
	{
		m_bHttps = true;
	}
	else {
		m_bHttps = false;
	}
	if (m_bHttps)
	{
		pHttp = HP_Create_HttpsSyncClient(&listener);
	}
	else
	{
		pHttp = HP_Create_HttpSyncClient(&listener);
	}

	if (pHttp)
	{
		if (m_bHttps)
		{
			pHttp->SetupSSLContext(SSL_VM_NONE);
		}

		//设置请求超时时间
		if (dwRequestTimeout > 0 )
		{
			pHttp->SetRequestTimeout(dwRequestTimeout);
		}

		//get or post
		BOOL bPost = FALSE;
		string sRequestMethod;
		if (enType == T_HTTPS_REQUEST_GET || enType == T_HTTP_REQUEST_GET)
		{
			sRequestMethod = "GET";
			bPost = FALSE;
		}
		else if (enType == T_HTTPS_REQUEST_POST || enType == T_HTTP_REQUEST_POST)
		{
			sRequestMethod = "POST";
			bPost = TRUE;
		}

		//body
		BYTE* pBody = NULL;
		int nBodyLen = 0;
		if (bPost)
		{
			string sBody = strParam;
			nBodyLen = strlen(sBody.c_str());
			if (nBodyLen > 0)
			{
				pBody = new BYTE[nBodyLen + 1];
				memset(pBody, 0, sizeof(pBody) / sizeof(BYTE));
				memcpy_s(pBody, nBodyLen + 1, sBody.c_str(), nBodyLen);
				pBody[nBodyLen] = '\0';
			}
		}

		//send request
		THeader headerUA;
		headerUA.name = "User-Agent";
		headerUA.value = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36";
		THeader headerContentType;
		headerContentType.name = "Content-Type";
		headerContentType.value = "application/x-www-form-urlencoded;charset=UTF-8";//
		//headerContentType.value = "application/json;charset=UTF-8";//
		THeader headers[] = { headerUA, headerContentType };

		BYTE* pData = NULL;
		int nLen = 0;
		//重试次数
		int nTimes = (nRetryTimes == 0 ? 1 : nRetryTimes);
		while (nTimes > 0)
		{
			
			if (!pHttp->Start((LPCTSTR)strUrl.c_str(), m_bHttps ? 443 : 80, FALSE))
			{
				DWORD uErrCode = ::GetLastError();
				LPCSTR chErrMsg = { 0 };
				USHORT uCode = pHttp->GetParseErrorCode(&chErrMsg);
				//Trace(chErrMsg);
				//LOGFMTE("http openurl error. code=%d, msg=%hs", uErrCode, chErrMsg);
			}
			BOOL bOpen = FALSE;
			if (bPost)
			{
				X_INFO("POST   " + strUrl);
				X_INFO("PARAM   " + strParam);
				bOpen = pHttp->OpenUrl(sRequestMethod.c_str(), strUrl.c_str(), headers, 2, pBody, nBodyLen);
			}
			else
			{
				string sFullUrl;
				string sBody = strParam;
				sFullUrl = strUrl + "?" + sBody;
				X_INFO("GET   "+sFullUrl);
				bOpen = pHttp->OpenUrl(sRequestMethod.c_str(), sFullUrl.c_str(), headers, 2, NULL, 0);
			}

			if (bOpen)//
			{
				pHttp->GetResponseBody((LPCBYTE*)&pData, &nLen);//返回内容
				string str((char*)pData, nLen);
				strOut = str;
				X_INFO(strOut);
				//Trace(sTrace);
				break;
			}
			else
			{
				DWORD nErr = ::GetLastError();
				USHORT uErrCode = pHttp->GetStatusCode();
				LPCSTR chErrMsg = { 0 };
				USHORT uCode = pHttp->GetParseErrorCode(&chErrMsg);
				//Trace(chErrMsg);
				string strMsg;
				char pBuf[1000] = {0};
				sprintf_s(pBuf, "http openurl error. statusCode=%d, code=%d, msg=%hs", uErrCode, nErr, chErrMsg);
				strMsg = pBuf;
				X_ERR(strMsg);
			}
			pHttp->CleanupRequestResult();
			//////////////
			nTimes--;
		}

		//release
		if (pBody && nBodyLen > 0)
		{
			delete pBody;
			pBody = NULL;
		}

		if (m_bHttps)
		{
			HP_Destroy_HttpsSyncClient(pHttp);
		}
		else
		{
			HP_Destroy_HttpSyncClient(pHttp);
		}
	}
}
