[639] | 1 |
|
---|
| 2 | /*!
|
---|
| 3 | @brief IPアドレスを表すクラス
|
---|
| 4 | @author OverTaker
|
---|
[647] | 5 | @date 2008/10/18
|
---|
[639] | 6 | */
|
---|
| 7 |
|
---|
| 8 |
|
---|
| 9 | Namespace System
|
---|
| 10 | Namespace Net
|
---|
| 11 |
|
---|
| 12 | Class IPAddress
|
---|
[647] | 13 | item As *Byte
|
---|
| 14 | size As Long
|
---|
| 15 | family As DWord
|
---|
[639] | 16 | Public
|
---|
| 17 |
|
---|
| 18 | /*!
|
---|
[647] | 19 | @brief アドレスをバイト配列で取得する
|
---|
| 20 | @return アドレスを表したバイト列
|
---|
| 21 | @note このメソッドはライブラリ内のみで使用する目的で作られています。
|
---|
| 22 | */
|
---|
| 23 | Function Address() As *Byte
|
---|
| 24 | Return item As *Byte
|
---|
| 25 | End Function
|
---|
| 26 |
|
---|
| 27 | /*!
|
---|
[639] | 28 | @brief コンストラクタ
|
---|
| 29 | */
|
---|
| 30 | Sub IPAddress()
|
---|
| 31 | End Sub
|
---|
| 32 |
|
---|
| 33 | /*!
|
---|
| 34 | @brief コンストラクタ
|
---|
| 35 | @param IPアドレスを表した32bit値(ネットワークバイトオーダー)
|
---|
| 36 | */
|
---|
| 37 | Sub IPAddress(ip As DWord)
|
---|
[647] | 38 | family = AF_INET
|
---|
| 39 | size = SizeOf(in_addr)
|
---|
| 40 | item = malloc(size)
|
---|
| 41 | memcpy(item, VarPtr(ip), size)
|
---|
[639] | 42 | End Sub
|
---|
| 43 |
|
---|
| 44 | /*!
|
---|
[648] | 45 | @brief コンストラクタ
|
---|
| 46 | @param SocketAddressクラスから作成
|
---|
| 47 | @note このコンストラクタはライブラリ内のみで使用する目的で作られています。
|
---|
| 48 | */
|
---|
| 49 | Sub IPAddress(address As SocketAddress)
|
---|
| 50 | family = address.AddressFamily
|
---|
| 51 | Select Case family
|
---|
| 52 | Case AF_INET
|
---|
| 53 | Dim addr4 = address.Items As *sockaddr_in
|
---|
| 54 | size = SizeOf(in_addr)
|
---|
| 55 | item = malloc(size)
|
---|
| 56 | memcpy(item, VarPtr(addr4->sin_addr.s_addr), size)
|
---|
| 57 | Case AF_INET6
|
---|
| 58 | Dim addr6 = address.Items As *sockaddr_in6
|
---|
| 59 | size = SizeOf(in6_addr)
|
---|
| 60 | item = malloc(size)
|
---|
| 61 | memcpy(item, VarPtr(addr6->sin6_addr.s6_addr), size)
|
---|
| 62 | Case Else
|
---|
| 63 | Throw New NotSupportedException("IPAddress: Not Supported AddressFamily.")
|
---|
| 64 | End Select
|
---|
| 65 | End Sub
|
---|
| 66 |
|
---|
| 67 | /*!
|
---|
[639] | 68 | @brief デストラクタ
|
---|
| 69 | */
|
---|
| 70 | Sub ~IPAddress()
|
---|
[647] | 71 | If item <> NULL Then free(item)
|
---|
[639] | 72 | End Sub
|
---|
| 73 |
|
---|
[647] | 74 | Function Operator== (address As IPAddress) As Boolean
|
---|
| 75 | Return Equals(address)
|
---|
| 76 | End Function
|
---|
| 77 |
|
---|
[639] | 78 | /*!
|
---|
| 79 | @brief アドレスファミリを取得する。
|
---|
| 80 | @return アドレスファミリ
|
---|
| 81 | */
|
---|
| 82 | Function AddressFamily() As Sockets.AddressFamily
|
---|
[647] | 83 | Return New System.Net.Sockets.AddressFamily(family, "AddressFamily")
|
---|
[639] | 84 | End Function
|
---|
| 85 |
|
---|
| 86 | /*!
|
---|
| 87 | @brief スコープを取得する。
|
---|
| 88 | @return スコープ
|
---|
| 89 | */
|
---|
[647] | 90 | /* Function ScopeId() As DWord
|
---|
[639] | 91 | End Function
|
---|
[647] | 92 | */
|
---|
[639] | 93 | /*!
|
---|
| 94 | @brief リンクローカルアドレスかどうかを取得する。
|
---|
| 95 | @retval True リンクローカルアドレス
|
---|
| 96 | @retval Flase リンクローカルアドレスではない
|
---|
| 97 | */
|
---|
| 98 | Function IsIPv6LinkLocal() As Boolean
|
---|
[647] | 99 | If family = AF_INET6 Then
|
---|
| 100 | Return (item[0] = &HFF) And (item[1] = &H00)
|
---|
[639] | 101 | Else
|
---|
| 102 | Throw New System.Net.Sockets.SocketException("IPAddress.IsIPv6LinkLocal: AddressFamily is not IPv6.")
|
---|
| 103 | End If
|
---|
| 104 | End Function
|
---|
| 105 |
|
---|
| 106 | /*!
|
---|
| 107 | @brief IPv6のマルチキャストアドレスかどうかを取得する。
|
---|
| 108 | @retval True IPv6のマルチキャストアドレス
|
---|
| 109 | @retval Flase IPv6のマルチキャストアドレス
|
---|
| 110 | */
|
---|
| 111 | Function IsIPv6Multicast() As Boolean
|
---|
[647] | 112 | If family = AF_INET6 Then
|
---|
| 113 | Return (item[0] = &HFE) And (item[1] = &H80)
|
---|
[639] | 114 | Else
|
---|
| 115 | Throw New System.Net.Sockets.SocketException("IPAddress.IsIPv6Multicast: AddressFamily is not IPv6.")
|
---|
| 116 | End If
|
---|
| 117 | End Function
|
---|
| 118 |
|
---|
| 119 | /*!
|
---|
| 120 | @brief IPアドレスが等しいかどうかを取得する
|
---|
| 121 | @retval True 等しい
|
---|
| 122 | @retval Flase 等しくない
|
---|
| 123 | */
|
---|
[647] | 124 | Function Equals(ip As IPAddress) As Boolean
|
---|
| 125 | If family = ip.family Then
|
---|
| 126 | Dim i As Long
|
---|
| 127 | For i = 0 To ELM(size)
|
---|
| 128 | If item[i] <> ip.item[i] Then Return False
|
---|
| 129 | Next
|
---|
| 130 | Return True
|
---|
| 131 | Else
|
---|
| 132 | Return False
|
---|
| 133 | End If
|
---|
[639] | 134 | End Function
|
---|
| 135 |
|
---|
| 136 | /*!
|
---|
| 137 | @brief IPアドレスを文字列で取得する
|
---|
| 138 | @return 文字列
|
---|
| 139 | */
|
---|
| 140 | Override Function ToString() As String
|
---|
| 141 | Dim temp[ELM(64)] As TCHAR
|
---|
[647] | 142 | Dim ret As Long
|
---|
| 143 | Select Case family
|
---|
| 144 | Case AF_INET
|
---|
| 145 | Dim addr4 As sockaddr_in
|
---|
| 146 | addr4.sin_family = family As Integer
|
---|
| 147 | addr4.sin_addr.s_addr = GetDWord(item)
|
---|
| 148 | ret = WSAAddressToString(addr4 As sockaddr, SizeOf(sockaddr_in), ByVal 0, temp, Len(temp))
|
---|
| 149 | Case AF_INET6
|
---|
| 150 | Dim addr6 As sockaddr_in6
|
---|
| 151 | addr6.sin6_family = family As Word
|
---|
| 152 | memcpy(addr6.sin6_addr.s6_addr, item, size)
|
---|
| 153 | ret = WSAAddressToString(addr6 As sockaddr, SizeOf(sockaddr_in6), ByVal 0, temp, Len(temp))
|
---|
| 154 | Case Else
|
---|
| 155 | Throw New NotSupportedException("IPAddress.ToString: Unknown Protocol.")
|
---|
| 156 | End Select
|
---|
| 157 |
|
---|
| 158 | If ret Then
|
---|
| 159 | Throw New System.Net.Sockets.SocketException(WSAGetLastError(), "IPAddress.ToString: Failed to WSAAddressToString.")
|
---|
[639] | 160 | Else
|
---|
| 161 | Return New String(temp)
|
---|
| 162 | End If
|
---|
| 163 | End Function
|
---|
| 164 |
|
---|
| 165 |
|
---|
| 166 | /*!
|
---|
| 167 | @brief 文字列からIPAddressクラスを作成する
|
---|
| 168 | @param 文字列で表したIPアドレス
|
---|
| 169 | @return IPAddressクラス
|
---|
| 170 | @exception 作成に失敗した場合
|
---|
| 171 | */
|
---|
| 172 | Static Function Parse(ip As String) As IPAddress
|
---|
[647] | 173 | Dim ipAddress = New IPAddress
|
---|
| 174 | If TryParse(ip, ipAddress) Then
|
---|
| 175 | Return ipAddress
|
---|
[639] | 176 | Else
|
---|
[647] | 177 | Throw New System.Net.Sockets.SocketException(WSAGetLastError(), "IPAddress.Parse: Failed to Parse.")
|
---|
[639] | 178 | End If
|
---|
| 179 | End Function
|
---|
| 180 |
|
---|
| 181 | /*!
|
---|
| 182 | @brief 文字列からIPAddressクラスを作成する
|
---|
| 183 | @param[in] 文字列で表したIPアドレス
|
---|
| 184 | @param[out] 作成したIPアドレスを格納するIPAddressクラス
|
---|
| 185 | @retval True 成功
|
---|
| 186 | @retval False 失敗
|
---|
| 187 | */
|
---|
[647] | 188 | Static Function TryParse(ip As String, ByRef address As IPAddress) As Boolean
|
---|
| 189 | address = New IPAddress
|
---|
[639] | 190 | If ip.Contains(".") Then
|
---|
[647] | 191 | address.family = AF_INET
|
---|
| 192 | address.item = Detail.CreateAddressFromIPv4String(ip)
|
---|
| 193 | address.size = SizeOf(in_addr)
|
---|
[639] | 194 | ElseIf ip.Contains(":") Then
|
---|
[647] | 195 | address.family = AF_INET6
|
---|
| 196 | address.item = Detail.CreateAddressFromIPv6String(ip)
|
---|
| 197 | address.size = SizeOf(in6_addr)
|
---|
[639] | 198 | Else
|
---|
| 199 | Return False
|
---|
| 200 | End If
|
---|
| 201 |
|
---|
[647] | 202 | If address.item <> NULL Then
|
---|
[639] | 203 | Return True
|
---|
| 204 | Else
|
---|
[647] | 205 | address = Nothing
|
---|
[639] | 206 | Return False
|
---|
| 207 | End If
|
---|
| 208 | End Function
|
---|
| 209 |
|
---|
| 210 | /*!
|
---|
| 211 | @brief Anyアドレスを作成
|
---|
| 212 | @return IPAddressクラス
|
---|
| 213 | */
|
---|
| 214 | Static Function Any() As IPAddress
|
---|
| 215 | Return New IPAddress(0)
|
---|
| 216 | End Function
|
---|
| 217 |
|
---|
| 218 | /*!
|
---|
| 219 | @brief ブロードキャストアドレスを作成
|
---|
| 220 | @return IPAddressクラス
|
---|
| 221 | */
|
---|
| 222 | Static Function Broadcast() As IPAddress
|
---|
| 223 | Return New IPAddress(&HFFFFFFFF)
|
---|
| 224 | End Function
|
---|
| 225 |
|
---|
| 226 | /*!
|
---|
| 227 | @brief ループバックアドレスを作成
|
---|
| 228 | @return IPAddressクラス
|
---|
| 229 | */
|
---|
| 230 | Static Function Loopback() As IPAddress
|
---|
[647] | 231 | Return New IPAddress( HostToNetworkOrder(&H7F000001) )
|
---|
[639] | 232 | End Function
|
---|
| 233 |
|
---|
| 234 | /*!
|
---|
| 235 | @brief Noneアドレスを作成
|
---|
| 236 | @return IPAddressクラス
|
---|
| 237 | */
|
---|
| 238 | Static Function None() As IPAddress
|
---|
| 239 | Return New IPAddress(&HFFFFFFFF)
|
---|
| 240 | End Function
|
---|
| 241 |
|
---|
| 242 | /*!
|
---|
| 243 | @brief IPv6 Anyアドレスを作成
|
---|
| 244 | @return IPAddressクラス
|
---|
| 245 | */
|
---|
| 246 | Static Function IPv6Any() As IPAddress
|
---|
| 247 | Return IPAddress.Parse("::")
|
---|
| 248 | End Function
|
---|
| 249 |
|
---|
| 250 | /*!
|
---|
| 251 | @brief IPv6 ループバックアドレスを作成
|
---|
| 252 | @return IPAddressクラス
|
---|
| 253 | */
|
---|
| 254 | Static Function IPv6Loopback() As IPAddress
|
---|
| 255 | Return IPAddress.Parse("::1")
|
---|
| 256 | End Function
|
---|
| 257 |
|
---|
| 258 | /*!
|
---|
| 259 | @brief IPv6 Noneアドレスを作成
|
---|
| 260 | @return IPAddressクラス
|
---|
| 261 | */
|
---|
| 262 | Static Function IPv6None() As IPAddress
|
---|
| 263 | Return IPAddress.Parse("::")
|
---|
| 264 | End Function
|
---|
| 265 |
|
---|
| 266 |
|
---|
| 267 |
|
---|
| 268 | /*!
|
---|
| 269 | @brief 16bitのホストバイトオーダーをネットワークバイトオーダーに変換する
|
---|
| 270 | @param ホストバイトオーダー
|
---|
| 271 | @return ネットワークバイトオーダー
|
---|
| 272 | */
|
---|
| 273 | Static Function HostToNetworkOrder(host As Word) As Word
|
---|
| 274 | Return htons(host)
|
---|
| 275 | End Function
|
---|
| 276 |
|
---|
| 277 | /*!
|
---|
| 278 | @brief 32bitのホストバイトオーダーをネットワークバイトオーダーに変換する
|
---|
| 279 | @param ホストバイトオーダー
|
---|
| 280 | @return ネットワークバイトオーダー
|
---|
| 281 | */
|
---|
| 282 | Static Function HostToNetworkOrder(host As DWord) As DWord
|
---|
| 283 | Return htonl(host)
|
---|
| 284 | End Function
|
---|
| 285 |
|
---|
| 286 | /*!
|
---|
| 287 | @brief 16bitのネットワークバイトオーダーをホストバイトオーダーに変換する
|
---|
| 288 | @param ネットワークバイトオーダー
|
---|
| 289 | @return ホストバイトオーダー
|
---|
| 290 | */
|
---|
| 291 | Static Function NetworkToHostOrder(network As Word) As Word
|
---|
| 292 | Return ntohs(network)
|
---|
| 293 | End Function
|
---|
| 294 |
|
---|
| 295 | /*!
|
---|
| 296 | @brief 32bitのネットワークバイトオーダーをホストバイトオーダーに変換する
|
---|
| 297 | @param ネットワークバイトオーダー
|
---|
| 298 | @return ホストバイトオーダー
|
---|
| 299 | */
|
---|
| 300 | Static Function NetworkToHostOrder(network As DWord) As DWord
|
---|
| 301 | Return ntohl(network)
|
---|
| 302 | End Function
|
---|
| 303 | End Class
|
---|
| 304 |
|
---|
| 305 | Namespace Detail
|
---|
| 306 |
|
---|
| 307 | /*!
|
---|
[647] | 308 | @brief IPv4アドレスを表した文字列からアドレスを作成する
|
---|
| 309 | @param IPv4アドレスを表したバイト列
|
---|
| 310 | @return バイト列
|
---|
[639] | 311 | */
|
---|
[647] | 312 | Function CreateAddressFromIPv4String(ip As String) As *Byte
|
---|
| 313 | Dim addr4 As sockaddr_in
|
---|
| 314 | If WSAStringToAddress(ToTCStr(ip), AF_INET, ByVal 0, addr4 As sockaddr, SizeOf(sockaddr_in)) Then
|
---|
[639] | 315 | Return NULL
|
---|
| 316 | Else
|
---|
[647] | 317 | Dim item = malloc(SizeOf(in_addr)) As *Byte
|
---|
| 318 | memcpy(item, VarPtr(addr4.sin_addr.s_addr), SizeOf(in_addr))
|
---|
| 319 | Return item
|
---|
[639] | 320 | End If
|
---|
| 321 | End Function
|
---|
| 322 |
|
---|
| 323 | /*!
|
---|
[647] | 324 | @brief IPv6アドレスを表した文字列からアドレスを作成する
|
---|
| 325 | @param IPv6アドレスを表したバイト列
|
---|
| 326 | @return バイト列
|
---|
[639] | 327 | */
|
---|
[647] | 328 | Function CreateAddressFromIPv6String(ip As String) As *Byte
|
---|
| 329 | Dim addr6 As sockaddr_in6
|
---|
| 330 | If WSAStringToAddress(ToTCStr(ip), AF_INET6, ByVal 0, addr6 As sockaddr, SizeOf(sockaddr_in6)) Then
|
---|
[639] | 331 | Return NULL
|
---|
| 332 | Else
|
---|
[647] | 333 | Dim item = malloc(SizeOf(in6_addr)) As *Byte
|
---|
| 334 | memcpy(item, addr6.sin6_addr.s6_addr, SizeOf(in6_addr))
|
---|
| 335 | Return item
|
---|
[639] | 336 | End If
|
---|
| 337 | End Function
|
---|
| 338 |
|
---|
| 339 | End Namespace
|
---|
| 340 |
|
---|
| 341 | End Namespace
|
---|
| 342 | End Namespace
|
---|