/**************************************************************************************************
 * File Name	: NetSSLServerWrapper.cpp
 * Created		: 08/09/15
 * Author		: ChenWei
 * Model			: TSD
 * Description	: Network ssl connect wrapper.
 **************************************************************************************************/
#include "NetSSLServerWrapper.h"
#include "NetSSLClientWrapper.h"
#include "libsesdata.h"
#include "IntfData.h"
#include "RegMgr.h"
using namespace IPCAPI;
using namespace LibSESData;
using namespace std;
/**************************************************************************************************
 * Function Name	: CNetSSLServerWrapper
 * Description		:
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
//CNetSSLServerWrapper::CNetSSLServerWrapper() :
//	mi_listen_port(8888), mi_out_time(5)
//{
//	mb_if_listen = false;
//}

/**************************************************************************************************
 * Function Name	: CNetSSLServerWrapper
 * Description		:
 * Date				: 08/09/15
 * Parameter			:
 * Return Code		:
 * Author				: ChenWei
 **************************************************************************************************/
CNetSSLServerWrapper::CNetSSLServerWrapper(int acc_port, int out_time) :
	mi_listen_port(acc_port), mi_out_time(out_time)
{
	mb_if_listen = false;
}

/**************************************************************************************************
 * Function Name	: ~CNetSSLServerWrapper
 * Description		: Destory CNetSSLServerWrapper.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
CNetSSLServerWrapper::~CNetSSLServerWrapper()
{
	Close();
}
/**************************************************************************************************
 * Function Name	: handle_input
 * Description		: handle_input
 * Date				: 08/09/15
 * Parameter		: int acc_port, int out_time
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/

int CNetSSLServerWrapper::handle_input(ACE_HANDLE handle)
{
	CSESLog::WriteLine("CNetSSLServerWrapper::handle_input>>Start");
	CSESLog::WriteLine(CSESLogData::LOG_STUDENT_CONNECTTEACHER,
			"CNetSSLServerWrapper::handle_input start");
	int iReturn = 0, iResult = 0;
	CNetSSLClientWrapper* cNetSSLClientWrapper = new CNetSSLClientWrapper();
	if (Accept(*cNetSSLClientWrapper))
	{
		if (RegMgr::instance()->IsPort(mi_listen_port))
		{
			cNetSSLClientWrapper->SetOption();
			std::string buff;
			int nret = cNetSSLClientWrapper->Recv(buff, RECVTIMEOUT);
			if (nret > 0)
			{
				//add err handle
				RegMgr::instance()->AddStudent(buff, cNetSSLClientWrapper);
				//cNetSSLClientWrapper = new CNetSSLClientWrapper();
			}
			else
			{
				CSESLog::WriteLine("RegMgr Accept >>Recv", CSESLog::WARNING);
				CSESLog::WriteLine(ACE_OS_String::strerror(errno),
						CSESLog::WARNING);
				delete cNetSSLClientWrapper;
				//cNetSSLClientWrapper = new CNetSSLClientWrapper();
			}

		}
		else
		{
			string buff;
			ifstream finRootCaFile;
			finRootCaFile.open(CAROOT, ios::binary);

			if (finRootCaFile.good())
			{
				char ch;

				while (finRootCaFile.get(ch))
				{
					//pch=&ch;
					buff.append(1, ch);
				}
				finRootCaFile.close();
				CIntfData cIntfData;
				CSESLog::WriteLine(buff);
				cIntfData.ParaXmlDoc.setString(TEACHER_ROOTCA, buff);
				string netMsg;
				cIntfData.toString(netMsg);
				unsigned long iLen = 0;
				unsigned char* pucStr = NULL;
				if (CSESDataTools::Compress(netMsg, &pucStr, iLen))
				{
					cNetSSLClientWrapper->Send(pucStr, iLen);
				}
				if (NULL != pucStr)
				{
					delete pucStr;
				}
				delete cNetSSLClientWrapper;
			}

		}
	}
	else
	{
		CSESLog::WriteLine("CNetSSLServerWrapper::Accept>>ERR");
		CSESLog::WriteLine(ACE_OS_String::strerror(errno), CSESLog::WARNING);
		iResult = ACE_Reactor::instance()->remove_handler(this,
				ACE_Event_Handler::ACCEPT_MASK);
		CSESLog::WriteLine(
				iResult,
				" ACE_Reactor::instance()->remove_handler(this, ACE_Event_Handler::ACCEPT_MASK):");
		Close();
		Open();
		CSESLog::WriteLine(
				ACE_Reactor::instance()->register_handler(this,
						ACE_Event_Handler::ACCEPT_MASK),
				" ACE_Reactor::instance()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK):");
		//iReturn=-1;
		delete cNetSSLClientWrapper;
	}
	CSESLog::WriteLine(CSESLogData::LOG_STUDENT_CONNECTTEACHER,
			"CNetSSLServerWrapper::handle_input end");
	CSESLog::WriteLine("CNetSSLServerWrapper::handle_input<<End");
	return iReturn;
}

/**************************************************************************************************
 * Function Name	: handle_input
 * Description		: handle_input
 * Date				: 08/09/15
 * Parameter		: int acc_port, int out_time
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
ACE_HANDLE CNetSSLServerWrapper::get_handle(void) const
{
	ACE_HANDLE iHandle = mc_acceptor.get_handle();
	CSESLog::WriteLine(iHandle, " CNetSSLServerWrapper::get_handle:");
	return iHandle;
}

/**************************************************************************************************
 * Function Name	: Open
 * Description		: Open CNetSSLServerWrapper.
 * Date				: 08/09/15
 * Parameter		: int acc_port, int out_time
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CNetSSLServerWrapper::Open(int acc_port, int out_time)
{
	// make these two open to one.
	mi_out_time = out_time;
	if (0 == acc_port)
	{
		acc_port = mi_listen_port;
	}
	if (mb_if_listen)
	{
		if (acc_port != mi_listen_port)
		{
			Close();
			mi_listen_port = acc_port;
		}
	}
	if (mb_if_listen)
		return true;

	ACE_Time_Value t_value(mi_out_time); //10s
	ACE_INET_Addr port_to_listen(mi_listen_port); //chinese

	int nret = mc_acceptor.open(port_to_listen, 1);//, //reuse_addr

	if (nret < 0)
	{
		return false;
	}
	mb_if_listen = true;

	return true;
}

/**************************************************************************************************
 * Function Name	: Open
 * Description		: Open CNetSSLServerWrapper.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
//bool CNetSSLServerWrapper::Open()
//{
//	if (mb_if_listen)
//		return true;
//
//	ACE_Time_Value t_value(mi_out_time); //10s
//	ACE_INET_Addr port_to_listen(mi_listen_port); //chinese
//
//	int nret = mc_acceptor.open(port_to_listen, 1);//, //reuse_addr
//
//	if (nret < 0)
//	{
//		return false;
//	}
//	mb_if_listen = true;
//
//	return true;
//}

/**************************************************************************************************
 * Function Name	: Close
 * Description		: Close CNetSSLServerWrapper.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CNetSSLServerWrapper::Close()
{
	if (mb_if_listen == false)
		return true;

	mc_acceptor.close();
	mb_if_listen = false;

	return true;
}

/**************************************************************************************************
 * Function Name	: Accept
 * Description		: CNetSSLServerWrapper accept.
 * Date				: 08/09/15
 * Parameter		: CNetSSLClientWrapper & client
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
bool CNetSSLServerWrapper::Accept(CNetSSLClientWrapper & client)
{
	ACE_INET_Addr remoteAddr;
	ACE_Time_Value t_value(mi_out_time); //10s


	//???accept
	//nret = acceptor.accept (new_stream);

	CSESLog::WriteLine("CNetSSLServerWrapper::Accept");
	int nret = mc_acceptor.accept(*(client.GetTcpStream()), &remoteAddr,
			&t_value);
	CSESLog::WriteLine(remoteAddr.get_host_addr());

	client.SetIsConnect(true);
	if (nret >= 0)
	{
		//client = new_stream;

		return true;
	}
	else
	{
		CSESLog::WriteLine(" CNetSSLServerWrapper::Accept()>>Err:",
				CSESLog::WARNING);
		CSESLog::WriteLine(ACE_OS_String::strerror(errno));

		client.Disconnect();

	}
	return false;
}

/**************************************************************************************************
 * Function Name	: GetErrInfo
 * Description		: Get ErrInfo.
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
std::string CNetSSLServerWrapper::GetErrInfo()
{

	return ACE_OS_String::strerror(errno);
}

///**************************************************************************************************
// * Function Name	: get_handle
// * Description		: get_handle
// * Date				: 08/09/15
// * Parameter		:
// * Return Code		:
// * Author			: ChenWei
// **************************************************************************************************/
//ACE_HANDLE CNetSSLServerWrapper::GetHandle() const
//{
//	return mc_acceptor.get_handle();
//
//}

/**************************************************************************************************
 * Function Name	: SetOption
 * Description		: SetOption
 * Date				: 08/09/15
 * Parameter		:
 * Return Code		:
 * Author			: ChenWei
 **************************************************************************************************/
int CNetSSLServerWrapper::SetOption()
{
	//add err handle
	if (mb_if_listen)
	{
		int keepAlive = 1;//设定KeepAlive
		int keepIdle = 5;//开始首次KeepAlive探测前的TCP空闭时间
		int keepInterval = 5;//两次KeepAlive探测间的时间间隔
		int keepCount = 3;//判定断开前的KeepAlive探测次数
		if (mc_acceptor.set_option(SOL_SOCKET, SO_KEEPALIVE,
				(void*) &keepAlive, sizeof(keepAlive)) == -1)
		{
			CSESLog::WriteLine(
					"CNetSSLServerWrapper setsockopt SO_KEEPALIVE error!");
			CSESLog::WriteLine(ACE_OS_String::strerror(errno));
		}
		if (mc_acceptor.set_option(SOL_TCP, TCP_KEEPIDLE, (void *) &keepIdle,
				sizeof(keepIdle)) == -1)
		{
			CSESLog::WriteLine(
					"CNetSSLServerWrapper setsockopt TCP_KEEPIDLE error!");
			CSESLog::WriteLine(ACE_OS_String::strerror(errno));
		}
		if (mc_acceptor.set_option(SOL_TCP, TCP_KEEPINTVL,
				(void*) &keepInterval, sizeof(keepInterval)) == -1)
		{
			CSESLog::WriteLine(
					"CNetSSLServerWrapper setsockopt TCP_KEEPINTVL error!");
			CSESLog::WriteLine(ACE_OS_String::strerror(errno));
		}
		if (mc_acceptor.set_option(SOL_TCP, TCP_KEEPCNT, (void*) &keepCount,
				sizeof(keepCount)) == -1)
		{
			CSESLog::WriteLine(
					"CNetSSLServerWrapper setsockopt TCP_KEEPCNT error!");
			CSESLog::WriteLine(ACE_OS_String::strerror(errno));
		}
	}
	return 0;
}

