#include "StdAfx.h"
#include "ListenSocket.h"

CListenSocket::CListenSocket(int port)
{
	m_port = port;
	m_listenSocket = INVALID_SOCKET;
	m_listenEvent.Create(FALSE, FALSE);
}

CListenSocket::~CListenSocket(void)
{
	EndListen();
}


///////////////////////////////////////////////////////////////////////////
//	初期化
///////////////////////////////////////////////////////////////////////////
/*!
	ポート番号の設定
*/
void CListenSocket::SetPort(int port)
{
	m_port = port;
}

/*!
	待ち受けを開始する
*/
int CListenSocket::StartListen()
{
	//	生成済み？
	EndListen();

	//	ソケット生成
	m_listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(m_listenSocket == INVALID_SOCKET)
		return(-1);

	//	イベントクリア
	::ResetEvent(m_listenEvent);

	//	ソケットを非ブロッキングモードへ
	if(::WSAEventSelect(m_listenSocket, m_listenEvent, FD_ACCEPT | FD_CLOSE))
		return(-1);

	//	ポート割り当て
	if(Bind(m_port))
		return(-1);

	//	受付実行
	if(listen(m_listenSocket, 5) != 0)
		return(-1);

	return(0);
}

/*!
	待ち受けを終了する
*/
void CListenSocket::EndListen()
{
	if(m_listenSocket != INVALID_SOCKET)
	{
		closesocket(m_listenSocket);
		m_listenSocket = INVALID_SOCKET;
	}
}

/*!
	受付してみる

	\return LISTEN_SOCKET_NOCLIENT:接続なし、LISTEN_SOCKET_ERROR:エラー、LISTEN_SOCKET_ACCEPTED:接続
*/
int CListenSocket::TryAccept(SOCKET &socket, CIPAddress &ip)
{
	//	アドレスバッファ
	sockaddr_in	addr;
	memset(&addr, 0, sizeof(sockaddr_in));
	int	nSockAddrLen = sizeof(sockaddr_in);

	//	受け付けてみる
	socket = ::WSAAccept(m_listenSocket, (SOCKADDR*)&addr, &nSockAddrLen, NULL, NULL);

	//	成功？
	if(socket != INVALID_SOCKET)
	{
		ip = addr.sin_addr;
		return(LISTEN_SOCKET_ACCEPTED);
	}

	//	なし？
	int errorCode = WSAGetLastError();
	if(errorCode == WSAEWOULDBLOCK || errorCode == WSAECONNRESET)
		return(LISTEN_SOCKET_NOCLIENT);

	//	エラー
	return(LISTEN_SOCKET_ERROR);
}


///////////////////////////////////////////////////////////////////////////
//	ツール
///////////////////////////////////////////////////////////////////////////
/*!
	ポート割り当て
*/
int CListenSocket::Bind(int bindPort)
{
	SOCKADDR_IN	sockAddr;

	memset(&sockAddr, 0, sizeof(sockAddr));
	sockAddr.sin_family			= AF_INET;
	sockAddr.sin_addr.s_addr	= htonl(INADDR_ANY);
	sockAddr.sin_port			= htons((u_short)bindPort);

	if(bind(m_listenSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
		return(-1);
	return(0);
}