#include "StdAfx.h"
#include "SSLClientConnection.h"
#include "HTTPHeaderParser.h"

#define	MAX_HEADER_SIZE	(16 * 1024)	//	16K
#define	END_HEADER		"\r\n\r\n"

CSSLClientConnection::CSSLClientConnection(SOCKET sock, SSL_CTX *sslContext, int timeout)
{
	m_sslAccepted = 0;
	m_sslContext = sslContext;
	m_socket.AttachSocket(sock);
	m_socket.SetTimeout(timeout);
}

CSSLClientConnection::~CSSLClientConnection(void)
{
	Close();
}




/////////////////////////////////////////////////////////////////////
//	IClientConnection
/////////////////////////////////////////////////////////////////////
/*!
	初期化
*/
void CSSLClientConnection::AttacheToThread(IServerToolPtr serverTool, IConnectionThreadStatusPtr threadStatus)
{
	m_threadStatus = threadStatus;
	m_socket.SetExBreakEvent(m_threadStatus->GetBreakEvent());
}

/*!
	切断
*/
void CSSLClientConnection::Close()
{
	m_socket.Close();
}


/*!
	クライアント情報の取得
*/
void CSSLClientConnection::GetClientInfo(CContextClientInfo info)
{
	//	クライアント情報
	//	ホスト名は自動設定されない
	info.SetAcceptedPort(m_socket.GetPort());
	info.SetClientPort(m_socket.GetPeerPort());
	info.SetClientIP(m_socket.GetPeerAddres());
}

/*!
	次の接続を待つ

	\return TRUE->検出、FALSE->タイムアウト
*/
int CSSLClientConnection::WaitNextConnection(int waitTime)
{
	//	SSL開始
	if(!m_sslAccepted)
	{
		if(m_socket.SSLAccept(m_sslContext))
			throw CConnectionErrorException("HTTPヘッダの受信に失敗しました: " + m_socket.GetLastErrorString());
		m_sslAccepted = TRUE;
	}

	return m_socket.WaitNextRequest(waitTime);
}

/*!
	接続中か取得する
*/
int CSSLClientConnection::IsConnecting()
{
	return !m_socket.IsDisconnect();
}


/////////////////////////////////////////////////////////////////////
//	IFilter
/////////////////////////////////////////////////////////////////////
/*!
	ヘッダを受信(throw)
*/
void CSSLClientConnection::RecvRequestHeader(CString &requestHeader)
{
	//	SSL開始
	if(!m_sslAccepted)
	{
		if(m_socket.SSLAccept(m_sslContext))
			throw CConnectionErrorException("HTTPヘッダの受信に失敗しました: " + m_socket.GetLastErrorString());
		m_sslAccepted = TRUE;
	}

	//	ヘッダ受信
	if(m_socket.RecvProtocolHeader(requestHeader, END_HEADER, MAX_HEADER_SIZE, FALSE))
		throw CConnectionErrorException("HTTPヘッダの受信に失敗しました: " + m_socket.GetLastErrorString());
}


/*!
	ボディを受信(throw)
*/
int CSSLClientConnection::RecvRequestBody(CBinaryData &body, int leftSize)
{
	//	受信
	int recved = m_socket.RecvBinary(body, leftSize);
	if(m_socket.GetLastError())
		throw CConnectionErrorException("データの受信に失敗しました: " + m_socket.GetLastErrorString());

	return(recved);
}


/*!
	ヘッダを送信(throw)
*/
void CSSLClientConnection::SendResponseHeader(CString &responseHeader)
{
	//	レスポンスヘッダ送信
	m_socket.SendString(responseHeader);
	if(m_socket.GetLastError())
		throw CConnectionErrorException("HTTPヘッダの送信に失敗しました: " + m_socket.GetLastErrorString());
}

/*!
	ボディを送信(throw)
*/
void CSSLClientConnection::SendResponseBody(CBinaryData &body)
{
	//	送信
	m_socket.SendBinary(body);
	if(m_socket.GetLastError())
		throw CConnectionErrorException("データの送信に失敗しました: " + m_socket.GetLastErrorString());
}


