#include "StdAfx.h"
#include "PipeListener.h"

CPipeListener::CPipeListener(void)
{
	m_maxConnection = 0;
	m_waiting = 0;
	m_pipe = NULL;
	m_iocp = NULL;
}

CPipeListener::~CPipeListener(void)
{
}

//////////////////////////////////////////////////////////////////////////////////
//	初期化
//////////////////////////////////////////////////////////////////////////////////
/*!
	パイプ通信の開始
*/
int CPipeListener::Init(CString pipeName, int maxConnection)
{
	//	接続数
	m_maxConnection = maxConnection;

	//	名前の修正
	if(pipeName.Left(4) != "\\\\.\\")
		m_pipeName = "\\\\.\\pipe\\" + pipeName;

	//	セキュリティ設定
	m_sa.BuildLocalSA();

	return(0);
}


/*!
	終了
*/
void CPipeListener::Close()
{
	SAFE_CLOSE_HANDLE(m_pipe);
	m_waiting = 0;
}

//////////////////////////////////////////////////////////////////////////////////
//	接続
//////////////////////////////////////////////////////////////////////////////////
/*!
	パイプを待つ
*/
int CPipeListener::StartWaitPipe(HANDLE iocp, ULONG_PTR CompletionKey)
{
	m_iocp = iocp;
	m_completionKey = CompletionKey;

	//	すでに待機中
	if(m_waiting)
		return(0);

	//	新規パイプ
	if(CreateNewPipe())
		return(-1);

	//	待ち受け開始
	if(StartWaitConnect())
	{
		Close();
		return(-1);
	}

	m_waiting = 1;
	return(0);
}


/*!
	パイプを取得
*/
HANDLE CPipeListener::GetNewPipe()
{
	DWORD	temp;
	if(!GetOverlappedResult(m_pipe, &m_connectOvrp, &temp, FALSE))
	{
		if(GetLastError() == ERROR_IO_INCOMPLETE)
			return(NULL);

		Close();
		return(NULL);	//	エラー
	}

	m_waiting = 0;
	return(m_pipe);
}


//////////////////////////////////////////////////////////////////////////////////
//	接続
//////////////////////////////////////////////////////////////////////////////////
/*!
	開く
*/
int CPipeListener::CreateNewPipe()
{
	//	未初期化？
	if(m_pipeName.IsEmpty())
		return(-1);

	// 名前付きパイプの生成
	m_pipe = ::CreateNamedPipe(m_pipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
									PIPE_TYPE_MESSAGE | PIPE_WAIT, m_maxConnection, 0, 0, 100, m_sa.GetSA());
	if(m_pipe == INVALID_HANDLE_VALUE)
		return(-1);

	//	IOCPが有効？
	if(m_iocp != NULL)
	{
		if(CreateIoCompletionPort(m_pipe, m_iocp, m_completionKey, 0) == NULL)
			return(-1);
	}

	return(0);
}

/*!
	接続待機開始
*/
int CPipeListener::StartWaitConnect()
{
	//	OVRP初期化
	INIT_OVERLAPPED(m_connectOvrp, NULL);

	//	待機開始
	if(ConnectNamedPipe(m_pipe, &m_connectOvrp))
	{
		return(0);	//	即終了
	}

	//	その他のエラー？
	if(GetLastError() !=  ERROR_IO_PENDING)
		return(-1);

	return(0);
}

