/*! @brief IPアドレスを表すクラス @author OverTaker @date 2008/10/05 */ Namespace System Namespace Net Class IPAddress Address As *sockaddr Length As Long Public /*! @brief コンストラクタ */ Sub IPAddress() Address = NULL End Sub /*! @brief コンストラクタ @param IPアドレスを表した32bit値(ネットワークバイトオーダー) */ Sub IPAddress(ip As DWord) Length = SizeOf(sockaddr_in) Dim temp = calloc(Length) As *sockaddr_in temp->sin_addr.s_addr = ip temp->sin_family = AF_INET Address = temp End Sub /*! @brief デストラクタ */ Sub ~IPAddress() If Address Then free(Address) End Sub /*! @brief アドレスファミリを取得する。 @return アドレスファミリ */ Function AddressFamily() As Sockets.AddressFamily Return New Sockets.AddressFamily(Address->sa_family, "AddressFamily") End Function /*! @brief スコープを取得する。 @return スコープ */ Function ScopeId() As DWord If AddressFamily = System.Net.Sockets.AddressFamily.InterNetworkV6 Then Dim sock = Address As *sockaddr_in6 Return sock->sin6_scope_id Else Throw New System.Net.Sockets.SocketException("IPAddress.ScopeId: AddressFamily is not IPv6.") End If End Function /*! @brief スコープを設定する。 @param スコープ */ Sub ScopeId(id As DWord) If id > &HFFFFFFFF Then Throw New ArgumentOutOfRangeException("IPAddress.ScopeId", New Int32(id), "id") End If If AddressFamily = System.Net.Sockets.AddressFamily.InterNetworkV6 Then Dim sock = Address As *sockaddr_in6 sock->sin6_scope_id = id Else Throw New System.Net.Sockets.SocketException("IPAddress.ScopeId: AddressFamily is not IPv6.") End If End Sub /*! @brief リンクローカルアドレスかどうかを取得する。 @retval True リンクローカルアドレス @retval Flase リンクローカルアドレスではない */ Function IsIPv6LinkLocal() As Boolean If AddressFamily = System.Net.Sockets.AddressFamily.InterNetworkV6 Then Dim sock = Address As *sockaddr_in6 Return (sock->sin6_addr.s6_addr[0] = &HFF) And (sock->sin6_addr.s6_addr[1] = &H00) Else Throw New System.Net.Sockets.SocketException("IPAddress.IsIPv6LinkLocal: AddressFamily is not IPv6.") End If End Function /*! @brief IPv6のマルチキャストアドレスかどうかを取得する。 @retval True IPv6のマルチキャストアドレス @retval Flase IPv6のマルチキャストアドレス */ Function IsIPv6Multicast() As Boolean If AddressFamily = System.Net.Sockets.AddressFamily.InterNetworkV6 Then Dim sock = Address As *sockaddr_in6 Return (sock->sin6_addr.s6_addr[0] = &HFE) And (sock->sin6_addr.s6_addr[1] = &H80) Else Throw New System.Net.Sockets.SocketException("IPAddress.IsIPv6Multicast: AddressFamily is not IPv6.") End If End Function /*! @brief IPアドレスが等しいかどうかを取得する @retval True 等しい @retval Flase 等しくない @note 手抜き実装 */ Override Function Equals(ip As Object) As Boolean Return This.ToString() = ip.ToString() End Function /*! @brief IPアドレスを文字列で取得する @return 文字列 */ Override Function ToString() As String Dim temp[ELM(64)] As TCHAR If WSAAddressToString(Address As sockaddr, Length, ByVal 0, temp, Len(temp)) Then Throw New System.Net.Sockets.SocketException(WSAGetLastError()) Else Return New String(temp) End If End Function /*! @brief 文字列からIPAddressクラスを作成する @param 文字列で表したIPアドレス @return IPAddressクラス @exception 作成に失敗した場合 */ Static Function Parse(ip As String) As IPAddress Dim address = New IPAddress If TryParse(ip, address) Then Return address Else Throw New System.Net.Sockets.SocketException(WSAGetLastError()) End If End Function /*! @brief 文字列からIPAddressクラスを作成する @param[in] 文字列で表したIPアドレス @param[out] 作成したIPアドレスを格納するIPAddressクラス @retval True 成功 @retval False 失敗 */ Static Function TryParse(ip As String, ByRef ipAddress As IPAddress) As Boolean If ipAddress.Address Then free(ipAddress.Address) If ip.Contains(".") Then ipAddress.Address = Detail.CreateAddressFromIPv4String(ip) ipAddress.Length = SizeOf(sockaddr_in) ElseIf ip.Contains(":") Then ipAddress.Address = Detail.CreateAddressFromIPv6String(ip) ipAddress.Length = SizeOf(sockaddr_in6) Else Return False End If If ipAddress.Address Then Return True Else Return False End If End Function /*! @brief Anyアドレスを作成 @return IPAddressクラス */ Static Function Any() As IPAddress Return New IPAddress(0) End Function /*! @brief ブロードキャストアドレスを作成 @return IPAddressクラス */ Static Function Broadcast() As IPAddress Return New IPAddress(&HFFFFFFFF) End Function /*! @brief ループバックアドレスを作成 @return IPAddressクラス */ Static Function Loopback() As IPAddress Return New IPAddress( HostToNetworkOrder(&HFF000000) ) End Function /*! @brief Noneアドレスを作成 @return IPAddressクラス */ Static Function None() As IPAddress Return New IPAddress(&HFFFFFFFF) End Function /*! @brief IPv6 Anyアドレスを作成 @return IPAddressクラス */ Static Function IPv6Any() As IPAddress Return IPAddress.Parse("::") End Function /*! @brief IPv6 ループバックアドレスを作成 @return IPAddressクラス */ Static Function IPv6Loopback() As IPAddress Return IPAddress.Parse("::1") End Function /*! @brief IPv6 Noneアドレスを作成 @return IPAddressクラス */ Static Function IPv6None() As IPAddress Return IPAddress.Parse("::") End Function /*! @brief 16bitのホストバイトオーダーをネットワークバイトオーダーに変換する @param ホストバイトオーダー @return ネットワークバイトオーダー */ Static Function HostToNetworkOrder(host As Word) As Word Return htons(host) End Function /*! @brief 32bitのホストバイトオーダーをネットワークバイトオーダーに変換する @param ホストバイトオーダー @return ネットワークバイトオーダー */ Static Function HostToNetworkOrder(host As DWord) As DWord Return htonl(host) End Function /*! @brief 16bitのネットワークバイトオーダーをホストバイトオーダーに変換する @param ネットワークバイトオーダー @return ホストバイトオーダー */ Static Function NetworkToHostOrder(network As Word) As Word Return ntohs(network) End Function /*! @brief 32bitのネットワークバイトオーダーをホストバイトオーダーに変換する @param ネットワークバイトオーダー @return ホストバイトオーダー */ Static Function NetworkToHostOrder(network As DWord) As DWord Return ntohl(network) End Function End Class Namespace Detail /*! @brief IPv4アドレスを表した文字列から、IPアドレスが設定されたsockaddr構造体を作成します @param IPv4アドレスを表した文字列 @return sockaddr構造体を示すアドレス */ Function CreateAddressFromIPv4String(ip As String) As *sockaddr Dim address = malloc(SizeOf(sockaddr_in)) As *sockaddr_in If WSAStringToAddress(ToTCStr(ip), AF_INET, ByVal 0, address As sockaddr, SizeOf(sockaddr_in)) Then Return NULL Else Return address End If End Function /*! @brief IPv6アドレスを表した文字列からIPアドレスが設定されたsockaddr構造体を作成します @param IPv6アドレスを表した文字列 @return sockaddr構造体を示すアドレス */ Function CreateAddressFromIPv6String(ip As String) As *sockaddr Dim address = malloc(SizeOf(sockaddr_in6)) As *sockaddr_in6 If WSAStringToAddress(ToTCStr(ip), AF_INET6, ByVal 0, address As sockaddr, SizeOf(sockaddr_in6)) Then Return NULL Else Return address End If End Function End Namespace End Namespace End Namespace