
/** @file
    @brief		非同期型ソケットサーバークラス
    @author		Noriyuki Lee
    @since		2003.07.01
*/


//=============================================================================
// INCLUDE
//=============================================================================
#include "Luna.h"
#include "LunaSocketServerAsync.h"
#include "LunaSystem.h"
#include "LunaMemory.h"

#include "LunaWork.h"


//=============================================================================
// VARIABLE
//=============================================================================
static WORK_LUNASOCKETSERVERASYNC *pWork;


//=============================================================================
/**
	クラスの初期化をします。

	@param pWorkData	[in] ワークエリアのアドレス

	@retval true	成功
	@retval false	失敗
*/
//=============================================================================
bool LunaSocketServerAsync::Initialize( void *pWorkData )
{
	Luna::LogoutMainCategory( "LunaSocketServerAsyncクラスの初期化" );
	Luna::LogoutNextLine();

	//----------------------------------------------------------
	// ワークエリアの取得
	//----------------------------------------------------------
	pWork = (WORK_LUNASOCKETSERVERASYNC*)pWorkData;

	//----------------------------------------------------------
	// ワークエリアの初期化
	//----------------------------------------------------------
	MemoryClear( pWork, sizeof(WORK_LUNASOCKETSERVERASYNC) );
	pWork->Socket = INVALID_SOCKET;

	return true;
}

//=============================================================================
/**
	クラスの解放をします。
*/
//=============================================================================
void LunaSocketServerAsync::Uninitialize( void )
{
	Luna::LogoutMainCategory( "LunaSocketServerAsyncクラスの解放" );
	Luna::LogoutNextLine();

	Release();
}

//=============================================================================
/**
	WinSockの解放処理を行います
*/
//=============================================================================
void LunaSocketServerAsync::Release( void )
{
	Shutdown();
}

//=============================================================================
/**
	接続中のネットワークから切断します
*/
//=============================================================================
void LunaSocketServerAsync::Shutdown( void )
{
	//-------------------------------------------------------
	// クライアントリストの解放
	//-------------------------------------------------------
	CONNECTCLIENTDATA *p = pWork->pConnectionList;
	while ( p != NULL )
	{
		CONNECTCLIENTDATA *pNext = p->pNext;

		char TempBuff[64] = "";
		::shutdown( p->Socket, SD_SEND );
		while ( ::recv( p->Socket, TempBuff, sizeof(TempBuff), 0 ) > 0 );
		::shutdown( p->Socket, SD_BOTH );
		::closesocket( p->Socket );

		MemoryFree( p );

		p = pNext;
	}

	pWork->pConnectionList = NULL;

	//-------------------------------------------------------
	// ソケット切断
	//-------------------------------------------------------
	if ( pWork->IsConnect )
	{
		char TempBuff[64] = "";
		::shutdown( pWork->Socket, SD_SEND );
		while ( ::recv( pWork->Socket, TempBuff, sizeof(TempBuff), 0 ) > 0 );
		::shutdown( pWork->Socket, SD_BOTH );
		::closesocket( pWork->Socket );

		pWork->IsConnect = false;
	}
}

//=============================================================================
/*
	最後に発生したエラーを文字列の状態で取得します

	@param pError	: エラー文字列格納先バッファ

	@retval true	エラーがある場合
	@retval false	エラーがない場合
*/
//=============================================================================
bool LunaSocketServerAsync::GetLastError( char *pError )
{
	if ( pWork->LastError[0] != '\0' )
	{
		strcpy( pError, pWork->LastError );
		return true;
	}

	return false;
}

//=============================================================================
/**
	WinSockの初期化をします

	@retval true	成功
	@retval false	失敗
*/
//=============================================================================
bool LunaSocketServerAsync::Start( void )
{
	unsigned long Result;

	//------------------------------------------------------------
	// ソケット生成
	//------------------------------------------------------------
	pWork->Socket = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	if ( pWork->Socket == INVALID_SOCKET )
	{
		GetMakeError( ::WSAGetLastError(), pWork->LastError );
		return false;
	}

	//------------------------------------------------------------
	// 非同期モードへ
	//------------------------------------------------------------
	pWork->hWindow	= Luna::GetWindowHandle();
	pWork->Message	= WM_SOCKET;
	Result = ::WSAAsyncSelect( pWork->Socket, pWork->hWindow, pWork->Message, FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE );
	if ( Result == SOCKET_ERROR )
	{
		::closesocket( pWork->Socket );
		pWork->Socket = INVALID_SOCKET;

		GetMakeError( ::WSAGetLastError(), pWork->LastError );
		return false;
	}

	pWork->IsInitialize = true;

	return true;
}

//=============================================================================
/**
	指定名のホスト情報を取得します

	@param pServerString	[in] ホスト識別名称格納先アドレス（ホスト名でもＩＰでも可）
	@param pHost			[out] ホスト情報格納先アドレス

	@retval true	成功
	@retval false	失敗
*/
//=============================================================================
bool LunaSocketServerAsync::GetHostInfo( const char *pServerString, HOSTINFO *pHost )
{
	long i;
	IN_ADDR InAddrHost;
	HOSTENT *pHostEntry;

	//------------------------------------------------------------
	// 指定された文字列がホスト名かＩＰアドレスか調べる
	//------------------------------------------------------------
	InAddrHost.s_addr = ::inet_addr( pServerString );
	if ( InAddrHost.s_addr == INADDR_NONE )
	{
		// ＩＰではないのでホスト名として処理
		pHostEntry = ::gethostbyname( pServerString );
		if ( pHostEntry == NULL )
		{
			GetMakeError( ::WSAGetLastError(), pWork->LastError );
			return false;
		}
	}
	else
	{
		// ＩＰアドレスのようでふ
		pHostEntry = ::gethostbyaddr( (const char *)&InAddrHost, sizeof(IN_ADDR), AF_INET );
		if ( pHostEntry == NULL )
		{
			GetMakeError( ::WSAGetLastError(), pWork->LastError );
			return false;
		}
	}

	//------------------------------------------------------------
	// ホスト情報の保存
	//------------------------------------------------------------
	MemoryClear( &pWork->HostInfo, sizeof(pWork->HostInfo) );

	// ホスト公式名
	strcpy( pWork->HostInfo.Name, pHostEntry->h_name );

	// ホストの別名
	for ( i = 0; pHostEntry->h_aliases[i] != NULL; i++ )
	{
		strcpy( pWork->HostInfo.Alias[pWork->HostInfo.AliasCount++], pHostEntry->h_aliases[i] );
	}

	// アドレス
	for ( i = 0; pHostEntry->h_addr_list[i] != NULL; i++ )
	{
		const char *p = ::inet_ntoa( *((IN_ADDR*)pHostEntry->h_addr_list[i]));
		strcpy( pWork->HostInfo.Address[pWork->HostInfo.AddressCount++], p );
	}

	// データサイズ
	pWork->HostInfo.Length = pHostEntry->h_length;
	// データタイプ
	pWork->HostInfo.Type = pHostEntry->h_addrtype;

	//------------------------------------------------------------
	// ホストデータコピー
	//------------------------------------------------------------
	if ( pHost != NULL )
	{
		MemoryCopy( pHost, &pWork->HostInfo, sizeof(HOSTINFO) );
	}

	MemoryCopy( &pWork->HostEntry, pHostEntry, sizeof(HOSTENT) );

	return true;
}

//======================================================================================
/**
	ローカルホスト名を取得します

	@param pName	[out] ホスト名格納先ポインタ
*/
//======================================================================================
void LunaSocketServerAsync::GetLocalHostName( char *pName )
{
	char Buff[256] = "";
	// ホスト名取得
	::gethostname( Buff, sizeof(Buff) );
	strcpy( pName, Buff );
}

//======================================================================================
/**
	ローカルホストをサーバーとして起動します

	@param PortNo	[in] ポート番号

	@retval true	成功
	@retval false	失敗
*/
//======================================================================================
bool LunaSocketServerAsync::CreateServer( unsigned short PortNo )
{
	long ReturnCode;
	SOCKADDR_IN SockAddr;

	//------------------------------------------------------------
	// 接続用データ生成
	//------------------------------------------------------------
	MemoryClear( &SockAddr, sizeof(SOCKADDR_IN) );
	SockAddr.sin_family	= AF_INET;
	SockAddr.sin_port	= ::htons( PortNo );

	//------------------------------------------------------------
	// ソケットにアドレスとポートを関連付ける
	//------------------------------------------------------------
	ReturnCode = ::bind( pWork->Socket, (SOCKADDR*)&SockAddr, sizeof(SOCKADDR_IN) );
	if ( ReturnCode == SOCKET_ERROR )
	{
		GetMakeError( ::WSAGetLastError(), pWork->LastError );
		return false;
	}

	//------------------------------------------------------------
	// 接続
	//------------------------------------------------------------
	ReturnCode = ::listen( pWork->Socket, 64 );
	if ( ReturnCode == SOCKET_ERROR )
	{
		GetMakeError( ::WSAGetLastError(), pWork->LastError );
		return false;
	}

	pWork->IsConnect = true;

	return true;
}

//======================================================================================
/**
	接続許可時のコールバック関数を設定します

	@param pCallBack		[in] 関数アドレス
*/
//======================================================================================
void LunaSocketServerAsync::SetAsynCallBackAccept( PCALLBACKSOCKETPROC pCallBack )
{
	pWork->pCallBackAccept = pCallBack;
}


//======================================================================================
/**
	接続終了時のコールバック関数を設定します

	@param pCallBack		[in] 関数アドレス
*/
//======================================================================================
void LunaSocketServerAsync::SetAsynCallBackClose( PCALLBACKSOCKETPROC pCallBack )
{
	pWork->pCallBackClose = pCallBack;
}

//======================================================================================
/**
	受信可能時のコールバック関数を設定します

	@param pCallBack		[in] 関数アドレス
*/
//======================================================================================
void LunaSocketServerAsync::SetAsynCallBackRead( PCALLBACKSOCKETPROC pCallBack )
{
	pWork->pCallBackRead = pCallBack;
}

//======================================================================================
/**
	送信可能時のコールバック関数を設定します

	@param pCallBack		[in] 関数アドレス
*/
//======================================================================================
void LunaSocketServerAsync::SetAsynCallBackWrite( PCALLBACKSOCKETPROC pCallBack )
{
	pWork->pCallBackWrite = pCallBack;
}

//======================================================================================
/**
	ウィンドウメッセージを処理します

	@param hWnd		[in] ウィンドウハンドル
	@param wParam	[in] パラメータ１
	@param lParam	[in] パラメータ２
*/
//======================================================================================
void LunaSocketServerAsync::ReceiveMessage( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
	long EventCode = WSAGETSELECTEVENT( lParam );
	long ErrorCode = WSAGETSELECTERROR( lParam );

	SOCKET Socket = (SOCKET)wParam;
	CONNECTCLIENTDATA *p = (CONNECTCLIENTDATA*)List_Search( Socket );

	GetMakeError( ErrorCode, pWork->LastError );

	switch ( EventCode )
	{
	//------------------------------------------------------------
	// 接続許可時
	//------------------------------------------------------------
	case FD_ACCEPT:
		// クライアントの接続待ち
		if ( !ASyncAccept() )
		{
			GetMakeError( ErrorCode, pWork->LastError );
		}
		// コールバック
		else
		if ( pWork->pCallBackAccept != NULL )
		{
			pWork->pCallBackAccept( hWnd, (long)pWork->ConnectClient.Socket );
		}
		break;

	//------------------------------------------------------------
	// 接続終了時
	//------------------------------------------------------------
	case FD_CLOSE:
		if ( p != NULL )
		{
			// 同一ソケットのクライアント取得
			MemoryCopy( &pWork->CloseClient, p, sizeof(CONNECTCLIENTDATA) );
			pWork->CloseClient.pNext = NULL;
			// クライアント切断
			char TempBuff[64] = "";
			::shutdown( p->Socket, SD_SEND );
			while ( ::recv( p->Socket, TempBuff, sizeof(TempBuff), 0 ) > 0 );
			::shutdown( p->Socket, SD_BOTH );
			::closesocket( p->Socket );
			// 指定クライアントをリストから削除
			List_Erase( p );

			// コールバック
			if ( pWork->pCallBackClose != NULL )
			{
				pWork->pCallBackClose( hWnd, (long)wParam );
			}
		}
		break;

	//------------------------------------------------------------
	// 読み込み可能時
	//------------------------------------------------------------
	case FD_READ:
		if ( p != NULL )
		{
			p->IsReadEnable = true;

			// コールバック
			if ( pWork->pCallBackRead != NULL )
			{
				pWork->pCallBackRead( hWnd, (long)wParam );
			}
		}
		break;

	//------------------------------------------------------------
	// 書き込み可能時
	//------------------------------------------------------------
	case FD_WRITE:
		if ( p != NULL )
		{
			p->IsWriteEnable = true;

			// 送信バッファが残っている時は送信を行う
			if ( p->SendData.pData != NULL )
			{
				long Send = ASyncSend( p->SendData.pData + p->SendData.Send, p->SendData.Size - p->SendData.Send, (long)wParam );
				if ( Send < 0 )
				{
				}
			}
			// 送信バッファがなければ、コールバック関数を呼び出す
			else
			{
				// コールバック
				if ( pWork->pCallBackWrite != NULL )
				{
					pWork->pCallBackWrite( hWnd, (long)wParam );
				}
			}
		}
		break;
	}
}

//======================================================================================
/**
	クライアントが接続待ちをします

	@retval true	成功
	@retval false	失敗
*/
//======================================================================================
bool LunaSocketServerAsync::ASyncAccept( void )
{
	long Result;
	SOCKET RemoteSocket;
	SOCKADDR_IN SocketAddr;
	int Size = sizeof(SOCKADDR_IN);

	//------------------------------------------------------------
	// クライアント受信待ち
	//------------------------------------------------------------
	RemoteSocket = ::accept( pWork->Socket, (SOCKADDR*)&SocketAddr, &Size );
	if ( RemoteSocket == SOCKET_ERROR )
	{
		if ( ::WSAGetLastError() != WSAEWOULDBLOCK )
		{
			GetMakeError( ::WSAGetLastError(), pWork->LastError );
			return false;
		}
	}

	//------------------------------------------------------------
	// 新しいソケットが非同期通知を受け取れるようにする
	//------------------------------------------------------------
	unsigned long Flag = FD_READ | FD_WRITE | FD_CLOSE;
	Result = ::WSAAsyncSelect( RemoteSocket, pWork->hWindow, pWork->Message, Flag );
	if ( Result == SOCKET_ERROR )
	{
		GetMakeError( ::WSAGetLastError(), pWork->LastError );
		return false;
	}

	//------------------------------------------------------------
	// 新規クライアントデータ生成
	//------------------------------------------------------------
	MemoryClear( &pWork->ConnectClient, sizeof(pWork->ConnectClient) );
	pWork->ConnectClient.Socket		= RemoteSocket;
	pWork->ConnectClient.SockAddr	= SocketAddr;
	pWork->ConnectClient.Length		= Size;
	// ＩＰ取得
	const char *pAddress = ::inet_ntoa( pWork->ConnectClient.SockAddr.sin_addr );
	// ホスト情報取得
	GetHostInfo( pAddress, &pWork->ConnectClient.HostInfo );
	// 元ＩＰ取得
	strcpy( pWork->ConnectClient.IPAddress, pAddress );

	// リストに追加
	List_Insert( &pWork->ConnectClient );

	return true;
}

//======================================================================================
/**
	指定したデータを非同期モード用で接続先へ受信

	@param pData	[out] データアドレス
	@param Size		[in] データサイズ
	@param Id		[in] クライアントソケットＩＤ

	@retval -2		接続は閉じられた
	@retval -1		送信に失敗
	@retval 0以上	受信したバイト数
*/
//======================================================================================
long LunaSocketServerAsync::ASyncSend( const void *pData, unsigned long Size, long Id )
{
	const char *pBuffer = (const char *)pData;
	unsigned long Rest = Size;

	SOCKET Socket = (SOCKET)Id;
	CONNECTCLIENTDATA *p = (CONNECTCLIENTDATA*)List_Search( Socket );
	if ( !p->IsWriteEnable ) return 0;

	//----------------------------------------------------
	// データ送信用ループ
	//----------------------------------------------------
	while ( Rest > 0 )
	{
		//--------------------------------------------
		// 残りのバイト数を送信する
		//--------------------------------------------
		unsigned long SendSize = ::send( Socket, pBuffer, Rest, 0 );
		if ( SendSize == SOCKET_ERROR )
		{
			if ( ::WSAGetLastError() != WSAEWOULDBLOCK )
			{
				GetMakeError( ::WSAGetLastError(), pWork->LastError );
				return -1;
			}
			else
			{
				p->IsWriteEnable = false;
				break;
			}
		}
		else
		if ( SendSize == 0 )
		{
			strcpy( pWork->LastError, "回線は切断されました" );
			return -2;
		}

		// 送信した分進める
		Rest -= SendSize;
		pBuffer += SendSize;
	}

	// バッファ解放
	MemoryFree( p->SendData.pData );
	MemoryClear( &p->SendData, sizeof(SOCKETSENDDATA) );

	return (Size - Rest);
}

//======================================================================================
/**
	指定したデータを非同期モード用で接続先から受信

	@param pData	[out] データアドレス
	@param Size		[in] データサイズ
	@param Id		[in] クライアントＩＤ

	@retval -2		接続は閉じられた
	@retval -1		送信に失敗
	@retval 0以上	送信したバイト数
*/
//======================================================================================
long LunaSocketServerAsync::ASyncReceive( void *pData, unsigned long Size, long Id )
{
	char *pBuffer = (char *)pData;
	unsigned long Rest = Size;

	SOCKET Socket = (SOCKET)Id;
	CONNECTCLIENTDATA *p = (CONNECTCLIENTDATA*)List_Search( Socket );
	if ( !p->IsReadEnable ) return 0;

	//----------------------------------------------------
	// データ受信用ループ
	//----------------------------------------------------
	while ( Rest > 0 )
	{
		//--------------------------------------------
		// 残りのバイト数を受信する
		//--------------------------------------------
		unsigned long ReceiveSize = ::recv( Socket, pBuffer, Rest, 0 );
		if ( ReceiveSize == SOCKET_ERROR )
		{
			if ( ::WSAGetLastError() != WSAEWOULDBLOCK )
			{
				GetMakeError( ::WSAGetLastError(), pWork->LastError );
				return -1;
			}
			else
			{
				p->IsReadEnable = false;
				break;
			}
		}
		else
		if ( ReceiveSize == 0 )
		{
			strcpy( pWork->LastError, "回線は切断されました" );
			return -2;
		}

		// 受信した分進める
		Rest -= ReceiveSize;
		pBuffer += ReceiveSize;
	}

	return (Size - Rest);
}

//======================================================================================
/**
	指定したクライアントに送信データを設定します

	@param pSend	[in] データアドレス
	@param Id		[in] クライアントＩＤ

	@retval true	成功
	@retval false	失敗
*/
//======================================================================================
bool LunaSocketServerAsync::SetSendData( SOCKETSENDDATA *pSend, long Id )
{
	SOCKET Socket = (SOCKET)Id;
	CONNECTCLIENTDATA *p = (CONNECTCLIENTDATA*)List_Search( Socket );

	if ( p->SendData.pData != NULL ) return false;
	if ( Id == -1 ) Id = (long)pWork->Socket;

	// データ設定
	p->SendData.Send = 0;
	p->SendData.Size = pSend->Size;
	p->SendData.pData = (unsigned char *)MemoryClearAlloc( p->SendData.Size );
	MemoryCopy( p->SendData.pData, pSend->pData, p->SendData.Size );

	// すぐに送信を始める
	p->SendData.Send += ASyncSend( p->SendData.pData, p->SendData.Size - p->SendData.Send, Id );

	return true;
}

//======================================================================================
/**
	新規接続されたクライアントのホスト情報を取得します

	@param pHostInfo	[out] ホスト情報格納先アドレス
	@param pAddr		[out] アドレス格納先バッファ
*/
//======================================================================================
void LunaSocketServerAsync::GetConnectClientInfo( HOSTINFO *pHostInfo, char *pAddr )
{
	strcpy( pAddr, pWork->ConnectClient.IPAddress );
	MemoryCopy( pHostInfo, &pWork->ConnectClient.HostInfo, sizeof(HOSTINFO) );
}

//======================================================================================
/**
	最後に切断されたクライアントのホスト情報を取得します

	@param pHostInfo	[out] ホスト情報格納先アドレス
	@param pAddr		[out] アドレス格納先バッファ
*/
//======================================================================================
void LunaSocketServerAsync::GetCloseClientInfo( HOSTINFO *pHostInfo, char *pAddr )
{
	strcpy( pAddr, pWork->CloseClient.IPAddress );
	MemoryCopy( pHostInfo, &pWork->CloseClient.HostInfo, sizeof(HOSTINFO) );
}

//======================================================================================
/**
	現在接続中のクライアントの数を取得します

	@return		クライアント数
*/
//======================================================================================
long LunaSocketServerAsync::GetClientCount( void )
{
	return pWork->ClientCount;
}

//======================================================================================
/**
	指定した番号のクライアントのホスト名を取得します

	@param No		[in] リストのインデックス番号
	@param pName	[out] 名前格納先バッファ
	@param pAddress	[out] ＩＰ格納先バッファ
*/
//======================================================================================
void LunaSocketServerAsync::GetClientInfo( long No, char *pName, char *pAddress )
{
	CONNECTCLIENTDATA *pClient = (CONNECTCLIENTDATA*)List_Search( No );

	if ( pClient->HostInfo.Name[0] == '\0' )
	{
		strcpy( pName, "Unknown" );
	}
	else
	{
		strcpy( pName, pClient->HostInfo.Name );
	}

	if ( pClient->HostInfo.Address[0][0] == '\0' )
	{
		strcpy( pAddress, pClient->IPAddress );
	}
	else
	{
		strcpy( pAddress, pClient->HostInfo.Address[0] );
	}
}

//======================================================================================
/**
	エラーコードからエラー文字列を取得します

	@param ErrorCode	[in] エラーコード
	@param pErrStr		[out] エラーメッセージ格納先
*/
//======================================================================================
void LunaSocketServerAsync::GetMakeError( long ErrorCode, char *pErrStr )
{
	MemoryClear( pWork->LastError, sizeof(pWork->LastError) );
	LunaSystem::GetSocketError( ErrorCode, pErrStr );
}


//======================================================================================
/**
	新しい接続クライアントを接続リストに追加します

	@param pConnect		[in] クライアント情報
*/
//======================================================================================
void LunaSocketServerAsync::List_Insert( void *pConnect )
{
	//------------------------------------------------------------
	// 新規データ生成
	//------------------------------------------------------------
	CONNECTCLIENTDATA *pNew = (CONNECTCLIENTDATA*)MemoryClearAlloc( sizeof(CONNECTCLIENTDATA) );
	MemoryCopy( pNew, pConnect, sizeof(CONNECTCLIENTDATA) );
	MemoryClear( &pNew->SendData, sizeof(SOCKETSENDDATA) );
	pNew->pNext = NULL;

	//------------------------------------------------------------
	// リストに追加
	//------------------------------------------------------------
	CONNECTCLIENTDATA *p = pWork->pConnectionList;
	// 最初の１人目
	if ( p == NULL )
	{
		// そのまま設定
		pWork->pConnectionList = pNew;
	}
	else
	{
		// 終端検索
		while ( p != NULL )
		{
			// 自分の次は誰もいない？
			if ( p->pNext == NULL )
			{
				// 接続
				p->pNext = pNew;
				break;
			}

			p = p->pNext;
		}
	}

	pWork->ClientCount++;
}

//======================================================================================
/**
	指定した接続先をリストから削除します

	@param pConnect		[in] クライアント情報
*/
//======================================================================================
void LunaSocketServerAsync::List_Erase( void *pConnect )
{
	CONNECTCLIENTDATA *p = pWork->pConnectionList;
	// 最初の１人目
	if ( p == pConnect )
	{
		// 接続解除
		pWork->pConnectionList = ((CONNECTCLIENTDATA*)pConnect)->pNext;
	}
	else
	{
		// 終端検索
		while ( p != NULL )
		{
			// 次は私ですか？
			if ( p->pNext == pConnect )
			{
				// 接続解除
				p->pNext = ((CONNECTCLIENTDATA*)pConnect)->pNext;
				break;
			}

			p = p->pNext;
		}
	}

	pWork->ClientCount--;

	if ( ((CONNECTCLIENTDATA*)pConnect)->SendData.pData != NULL )
	{
		MemoryFree( ((CONNECTCLIENTDATA*)pConnect)->SendData.pData );
	}

	MemoryFree( pConnect );
}

//======================================================================================
/**
	指定したソケットを持つ接続先を検索します

	@param Socket	[in] 検索対象ソケット

	@return		クライアント情報
*/
//======================================================================================
void *LunaSocketServerAsync::List_Search( SOCKET Socket )
{
	CONNECTCLIENTDATA *p = pWork->pConnectionList;
	// 検索処理
	while ( p != NULL )
	{
		// 私ですかね？
		if ( p->Socket == Socket )
		{
			return p;
		}

		p = p->pNext;
	}

	return NULL;
}

//======================================================================================
/**
	指定した番号の接続先を検索します

	@param No	[in] 番号

	@return		クライアント情報
*/
//======================================================================================
void *LunaSocketServerAsync::List_Search( long No )
{
	CONNECTCLIENTDATA *p = pWork->pConnectionList;
	// 検索処理
	while ( p != NULL )
	{
		// 私ですかね？
		if ( No-- == 0 )
		{
			return p;
		}

		p = p->pNext;
	}

	return NULL;
}


