#include "StdAfx.h"
#include "IPv4ClientConnection.h"
#include "Context.h"
#include "ServerException.h"

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


//////////////////////////////////////////////////////////////////////////////////////////////
//	コンストラクタ
//////////////////////////////////////////////////////////////////////////////////////////////
/*!
	コンストラクタ
*/
CIPv4ClientConnection::CIPv4ClientConnection(SOCKET sock, int timeout)
{
	m_socket.AttachSocket(sock);
	m_socket.SetTimeout(timeout);
}


/*!
	デストラクタ
*/
CIPv4ClientConnection::~CIPv4ClientConnection(void)
{
	Close();
}


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

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


/*!
	クライアント情報の取得
*/
void CIPv4ClientConnection::GetClientInfo(IWorkspaceAccessPtr clientInfo)
{
	//	ラッパ定義
	CContextClientInfo info = CWorkspaceAccess(clientInfo);

	//	クライアント情報
	//	ホスト名は自動設定されない
	info.SetAcceptedPort(m_socket.GetPort());
	info.SetAcceptedAddress(m_socket.GetAddres());
	info.SetClientPort(m_socket.GetPeerPort());
	info.SetClientAddress(m_socket.GetPeerAddres());
}

/*!
	次の接続を待つ

	\return TRUE->検出、FALSE->タイムアウト
*/
int CIPv4ClientConnection::WaitNextRequest(int waitTime)
{
	return m_socket.WaitNextRequest(waitTime);
}

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


/////////////////////////////////////////////////////////////////////
//	IClientConnection
/////////////////////////////////////////////////////////////////////
/*!
	ヘッダを受信(throw)
*/
void CIPv4ClientConnection::RecvRequestHeader(IStringPtr _requestHeader)
{
	CUTF8String	requestHeader;

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

	//	設定
	_requestHeader->SetString(requestHeader);
}


/*!
	ボディを受信(throw)
*/
int CIPv4ClientConnection::RecvRequestBody(IBinaryDataPtr _body, int leftSize)
{
	//	ラッパ定義
	CBinaryData	body(_body);

	//	受信
	int recved = m_socket.RecvBinary(body, leftSize);
	if(m_socket.GetLastError())
		throw CConnectionErrorException(_U16("データの受信に失敗しました: ") + m_socket.GetLastErrorString());

	return(recved);
}


/*!
	ヘッダを送信(throw)
*/
void CIPv4ClientConnection::SendResponseHeader(IStringPtr _responseHeader)
{
	CUTF8String	responseHeader = _responseHeader->GetString();

	//	レスポンスヘッダ送信
	m_socket.SendString(responseHeader);
	if(m_socket.GetLastError())
		throw CConnectionErrorException(_U16("HTTPヘッダの送信に失敗しました: ") + m_socket.GetLastErrorString());
}

/*!
	ボディを送信(throw)
*/
void CIPv4ClientConnection::SendResponseBody(IBinaryDataPtr _body)
{
	//	ラッパ定義
	CBinaryData	body(_body);

	//	送信
	m_socket.SendBinary(body);
	if(m_socket.GetLastError())
		throw CConnectionErrorException(_U16("データの送信に失敗しました: ") + m_socket.GetLastErrorString());
}


