#include "StdAfx.h"
#include "fastlistener.h"
#include "SSLSocket.h"
#include <Mswsock.h>

CFastListener::CFastListener(void)
{
	m_sslEnable = 0;
}

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



//	初期化
void CFastListener::Init(CWorkspaceAccess setting)
{
	//	サーバ設定
	CWorkspaceAccess basic = setting.GetAccess("Basic");
	CWorkspaceAccess enhance = setting.GetAccess("Enhance");

	//	変数初期化
	m_maxListenQueue = enhance.GetConfig("MaxListenQueue",50);
	int ListenThread = enhance.GetConfig("ListenThreadCount",3);
	int ListenThreadSSL = 0;

	//	ポート待ち受け開始
	if(m_listenSocket.Listen(setting.GetConfig("Basic::Port",80)))
		throw CFastListenerException("ポート待ちうけに失敗しました、ポート番号を確認してください");


	//	SSL有効？
	if(setting.GetConfig("Basic::EnableSSL",0))
	{
		m_sslEnable = 1;
		ListenThreadSSL = enhance.GetConfig("ListenThreadCountSSL",3);

		//	SSLライブラリ初期化
		if(m_sslContext.Init(setting))
			throw CFastListenerException("SSL初期化に失敗しました、暗号化キー、パスワード、証明書のいずれかが異常です");

		//	ポート待ち受け開始
		if(m_listenSocketSSL.Listen(setting.GetConfig("SSL::Port",443)))
			throw CFastListenerException("SSLのポート待ちうけに失敗しました、SSLのポート番号を確認してください");
	}

	//	スレッド起動
	m_maxListenThread = ListenThread + ListenThreadSSL;

	//	HTTP
	for(int i=0;i<ListenThread;i++)
	{
		CFastListenerThread *newThread = new CFastListenerThread;
		m_threadArray.Add(newThread);

		if(newThread->Start(&m_listenSocket,this))
			throw CFastListenerException("リスナスレッドの起動に失敗しました");
	}

	//	HTTPS
	for(int i=ListenThread;i<m_maxListenThread;i++)
	{
		CFastListenerThread *newThread = new CFastListenerThread;
		m_threadArray.Add(newThread);

		if(newThread->Start(&m_listenSocketSSL,this,TRUE))
			throw CFastListenerException("リスナスレッドの起動に失敗しました");
	}
}

//	停止
void CFastListener::Close()
{
	//	まず、閉じる
	m_listenSocket.Close();
	m_listenSocketSSL.Close();

	//	全て停止
	for(int i=0;i<m_threadArray.GetSize();i++)
		m_threadArray[i]->Break();

	//	すべて削除
	for(int i=0;i<m_threadArray.GetSize();i++)
		delete m_threadArray[i];
	m_threadArray.RemoveAll();

	//	全て削除
	for(int i=0;m_socketList.GetSize()>0;)
	{
		delete m_socketList.GetTail();
		m_socketList.RemoveTail();
	}
}

//	エラーの取得
int CFastListener::IsError()
{
	int err = 0;

	if(m_listenSocket.IsError())
		err = 1;

	if(m_sslEnable)
	{
		if(m_listenSocketSSL.IsError())
			err = 1;
	}

	return(err);
}


//	アクセスの取得
CMySocket *CFastListener::GetNextAccess()
{
	SCOPE_LOCK();

	if(m_socketList.GetCount() <= 0)
		return(NULL);

	CMySocket *sock = (CMySocket *)m_socketList.GetHead();
	m_socketList.RemoveHead();

	return(sock);
}

//	アクセスの追加
void CFastListener::AddNewSocket(CMySocket *sock)
{
	SCOPE_LOCK();

	if(m_socketList.GetCount() >= m_maxListenQueue)
	{
		//	オーバー
		delete sock;
	}
	else
	{
		m_socketList.AddTail(sock);
	}
}

//	初期化
CFastListenerThread::CFastListenerThread()
{
	DEBUG_SET_THREAD_CLASS_NAME("CFastListenerThread");
}

//	削除
CFastListenerThread::~CFastListenerThread()
{
	Break();
	while(IsRunning())
		Sleep(20);
}


//	スレッド起動
int CFastListenerThread::Start(CMySocket *listen,CFastListener *manager,int SSL)
{
	m_isSSL = SSL;
	m_listen = listen;
	m_manager = manager;

	return(StartThread());
}


//	リスナースレッド
void CFastListenerThread::ThreadMain()
{
	DEBUG_SET_THREAD_FUNCTION_NAME("CFastListenerThread::ThreadMain");

	//	プライオリティを上げる
	::SetThreadPriority(::GetCurrentThread(),THREAD_PRIORITY_HIGHEST);

	while(!GetBreak())
	{
		try
		{
			CMySocket *sock;
			
			if(m_isSSL)
				sock = new CSSLSocket(&m_manager->m_sslContext);
			else
				sock = new CMySocket;

			//	接続待ち
			int ret = m_listen->Accept(*sock,TRUE);

			if(ret == 1)
				m_manager->AddNewSocket(sock);
			else
			{
				delete sock;
				Sleep(100);
			}
		}
		catch(CMemoryException *err)
		{
			err->Delete();
			Sleep(5000);
		}
	}
}
