
/*!
	@brief  DNS名前解決をする関数群
	@author OverTaker
	@date 2008/10/19
*/


Namespace System
Namespace Net
Namespace Dns

/*!
@brief  ホスト名からIPアドレスを取得します
@param  ホスト名
@return IPAddressクラスが格納されたリスト
*/
Function GetHostAddresses(hostname As String) As System.Collections.Generic.List<IPAddress>
	Return GetHostEntry(hostname).IPAddressList
End Function

/*!
@brief  IPアドレスからホストの情報を取得します
@param  IPアドレスを表すIPAddressクラス
@return ホスト情報が格納されたIPHostEntryクラス
*/
Function GetHostEntry(ip As IPAddress) As IPHostEntry
	Return GetHostEntry(ip.ToString())
End Function

/*!
@brief  ホスト名からホストの情報を取得します
@param  ホスト名
@return ホスト情報が格納されたIPHostEntryクラス
*/
Function GetHostEntry(hostname As String) As IPHostEntry
	Return GetHostEntry(hostname, String.Empty)
End Function

/*!
@brief  ホスト名とポート番号からホストの情報を取得します
@param  ホスト名
@param  ポート番号
@return ホスト情報が格納されたIPHostEntryクラス
*/
Function GetHostEntry(hostname As String, port As Word) As IPHostEntry
	Return GetHostEntry(hostname, port.ToString())
End Function

/*!
@brief  ホスト名とサービス名からホストの情報を取得します
@param  ホスト名
@param  サービス名
@return ホスト情報が格納されたIPHostEntryクラス
*/
Function GetHostEntry(hostname As String, service As String) As IPHostEntry
	Dim results As *addrinfo
	If getaddrinfo(ToTCStr(hostname), ToTCStr(service), ByVal 0, results) Then
		Throw New System.Net.Sockets.SocketException(WSAGetLastError(), "Dns.GetHostEntry: Failed to getaddrinfo.")
	End If
	Return New Detail.IPHostEntryAddrinfo(results)
End Function

/*!
@brief  自身のコンピュータのホスト名を取得します
@return ホスト名
*/
Function GetHostName() As String
	Return GetHostEntry(String.Empty, "").HostName
End Function

/*!
@brief  ホスト名からIPアドレスを非同期で取得します
@param  ホスト名
@param  コールバック
@param  ユーザー情報
@return 非同期の操作をするIAsyncResultインターフェース
*/
Function BeginGetHostAddresses(hostname As String, callback As AsyncCallback, state As Object) As IAsyncResult
	Return BeginGetHostEntry(hostname, callback, state)
End Function

/*!
@brief  ホスト名からホストの情報を取得します
@param  ホスト名
@param  コールバック
@param  ユーザー情報
@return 非同期の操作をするIAsyncResultインターフェース
*/
Function BeginGetHostEntry(hostname As String, callback As AsyncCallback, state As Object) As IAsyncResult
	Return BeginGetHostEntry(hostname, String.Empty, callback, state)
End Function

/*!
@brief  ホスト名とサービス名からホストの情報を取得します
@param  ホスト名
@param  サービス名
@param  コールバック
@param  ユーザー情報
@return 非同期の操作をするIAsyncResultインターフェース
*/
Function BeginGetHostEntry(hostname As String, service As String, callback As AsyncCallback, state As Object) As IAsyncResult
	Dim data As Detail.AsyncGetHostEntryData
	data.Hostname = hostname
	data.Service = service
	data.Callback = callback

	Dim result = New Detail.AsyncGetHostEntryResult(state)
	data.Result = result
	Threading.ThreadPool.QueueUserWorkItem(AddressOf(Detail.AsyncGetHostEntry), data)
	Return result
End Function

/*!
@brief  BeginGetHostAddressesの結果を待ち、取得します
@param  BeginGetHostAddressesで取得したIAsyncResultインターフェース
@return IPAddressクラスが格納されたリスト
@note   この関数は、結果が取得されるまでブロッキングが発生します
*/
Function EndGetHostAddresses(ar As IAsyncResult) As System.Collections.Generic.List<IPAddress>
	Dim result = ar As Detail.IAsyncGetResult
	Return result.WaitAndGetResult().IPAddressList
End Function

/*!
@brief  BeginGetHostEntryの結果を待ち、取得します
@param  BeginGetHostEntryで取得したIAsyncResultインターフェース
@return ホスト情報が格納されたIPHostEntryクラス
@note   この関数は、結果が取得されるまでブロッキングが発生します
*/
Function EndGetHostEntry(ar As IAsyncResult) As IPHostEntry
	Dim result = ar As Detail.IAsyncGetResult
	Return result.WaitAndGetResult()
End Function

Namespace Detail

Sub AsyncGetHostEntry(o As Object)
	Dim data = o As AsyncGetHostEntryData
	Dim results As *addrinfo
	If getaddrinfo(ToTCStr(data.Hostname), ToTCStr(data.Service), ByVal 0, results) Then
		data.Result.SetException(New ActiveBasic.Windows.WindowsException(WSAGetLastError(), "Dns.GetHostEntry: Failed to getaddrinfo."))
	End If
	data.Result.Result = New Detail.IPHostEntryAddrinfo(results)

	data.Result.AsyncEventWaitHandle.Set()
	If Not ActiveBasic.IsNothing(data.Callback) Then
		Dim c = data.Callback
		c(data.Result)
	End If
End Sub

Class AsyncGetHostEntryData
	hostname As String
	service As String
Public
	Callback As AsyncCallback
	Result As AsyncGetHostEntryResult

	Function Hostname() As String
		Return hostname
	End Function

	Sub Hostname(name As String)
		If Not String.IsNullOrEmpty(name) Then hostname = String.Copy(name)
	End Sub

	Function Service() As String
		Return service
	End Function

	Sub Service(serv As String)
		If Not String.IsNullOrEmpty(serv) Then service = String.Copy(serv)
	End Sub
End Class

Interface IAsyncGetResult
	Inherits IAsyncResult
	Function WaitAndGetResult() As IPHostEntry
End Interface

Class AsyncGetHostEntryResult
Implements IAsyncGetResult
Public
	Sub AsyncGetHostEntryResult(s As Object)
		state = s
		wait = New Threading.EventWaitHandle(False, System.Threading.EventResetMode.ManualReset)
	End Sub

	Function AsyncState() As Object
		Return state
	End Function

	Function AsyncWaitHandle() As Threading.WaitHandle
		Return wait
	End Function

	Function AsyncEventWaitHandle() As Threading.EventWaitHandle
		AsyncEventWaitHandle = wait
	End Function

	Function CompletedSynchronously() As Boolean
		Return False
	End Function

	Function IsCompleted() As Boolean
		Return AsyncWaitHandle.WaitOne(0)
	End Function

	Override Function WaitAndGetResult() As IPHostEntry
		AsyncWaitHandle.WaitOne()
		If Not ActiveBasic.IsNothing(exception) Then
			Throw exception
		End If
		Return Result
	End Function

	Sub SetException(ex As Exception)
		exception = ex
	End Sub

	Result = Nothing As IPHostEntry
Private
	state As Object
	wait As Threading.EventWaitHandle
	exception As Exception
End Class

End Namespace

End Namespace
End Namespace
End Namespace