From 1fd93817faf2aa7cb33cf3738609c363085bb498 Mon Sep 17 00:00:00 2001 From: MacOMNI <414294494@qq.com> Date: Tue, 22 Oct 2024 14:27:17 +0800 Subject: [PATCH] ajust netaddr & more test (#187) --- Networking/Sources/MsQuicSwift/NetAddr.swift | 87 ++++++++++++------ .../Tests/MsQuicSwiftTests/NetAddrTests.swift | 90 +++++++++++++++++++ 2 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift diff --git a/Networking/Sources/MsQuicSwift/NetAddr.swift b/Networking/Sources/MsQuicSwift/NetAddr.swift index d9af4c92..e6593558 100644 --- a/Networking/Sources/MsQuicSwift/NetAddr.swift +++ b/Networking/Sources/MsQuicSwift/NetAddr.swift @@ -1,6 +1,7 @@ import CHelpers import Foundation import msquic + #if canImport(Glibc) import Glibc #elseif canImport(Darwin) @@ -74,11 +75,12 @@ extension NetAddr: CustomStringConvertible { private func parseQuicAddr(_ addr: QUIC_ADDR) -> (String, UInt16, Bool)? { let ipv6 = addr.Ip.sa_family == QUIC_ADDRESS_FAMILY(QUIC_ADDRESS_FAMILY_INET6) - let port = if ipv6 { - helper_ntohs(addr.Ipv6.sin6_port) - } else { - helper_ntohs(addr.Ipv4.sin_port) - } + let port = + if ipv6 { + helper_ntohs(addr.Ipv6.sin6_port) + } else { + helper_ntohs(addr.Ipv4.sin_port) + } var addr = addr if ipv6 { addr.Ipv6.sin6_port = 0 @@ -99,29 +101,62 @@ private func parseQuicAddr(_ addr: QUIC_ADDR) -> (String, UInt16, Bool)? { return (ipAddr, port, ipv6) } -private func parseIpv6Addr(_ address: String) -> (String, UInt16)? { - let parts = address.split(separator: "]:") - guard parts.count == 2 else { - return nil - } - let host = String(parts[0]) - let port = parts[1].dropFirst() - guard let portNum = UInt16(port, radix: 10) else { - return nil +private func parseIpv4Addr(_ address: String) -> (String, UInt16)? { + let ipv4Pattern = + #"((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"# + let ipv4WithPortPattern = #"(\#(ipv4Pattern)):(\d{1,5})"# + + let regex = try? NSRegularExpression(pattern: ipv4WithPortPattern, options: []) + let range = NSRange(location: 0, length: address.utf16.count) + + if let match = regex?.firstMatch(in: address, options: [], range: range) { + let ipRange = Range(match.range(at: 1), in: address)! + let portRange = Range(match.range(at: 3), in: address)! + + let ip = String(address[ipRange]) + let portString = String(address[portRange]) + + if let port = UInt16(portString) { + return (ip, port) + } } - return (host, portNum) + return nil } -private func parseIpv4Addr(_ address: String) -> (String, UInt16)? { - print(address) - let parts = address.split(separator: ":") - guard parts.count == 2 else { - return nil - } - let host = String(parts[0]) - let port = parts[1].dropFirst() - guard let portNum = UInt16(port, radix: 10) else { - return nil +private func parseIpv6Addr(_ address: String) -> (String, UInt16)? { + let ipv6Pattern = [ + "(?:", + "(?:(?:[0-9A-Fa-f]{1,4}:){6}", + "|::(?:[0-9A-Fa-f]{1,4}:){5}", + "|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}", + "|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}", + "|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}", + "|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:", + "|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)", + "(?:", + "[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}", + "|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}", + "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)", + ")", + "|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}", + "|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::", + ")", + ].reduce("", +) + let ipv6WithPortPattern = #"\[(\#(ipv6Pattern))\]:(\d{1,5})"# + + let regex = try? NSRegularExpression(pattern: ipv6WithPortPattern, options: []) + let range = NSRange(location: 0, length: address.utf16.count) + + if let match = regex?.firstMatch(in: address, options: [], range: range) { + let ipRange = Range(match.range(at: 1), in: address)! + let portRange = Range(match.range(at: 2), in: address)! + + let ip = String(address[ipRange]) + let portString = String(address[portRange]) + + if let port = UInt16(portString) { + return (ip, port) + } } - return (host, portNum) + return nil } diff --git a/Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift b/Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift new file mode 100644 index 00000000..7ef858b0 --- /dev/null +++ b/Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift @@ -0,0 +1,90 @@ +import Foundation +import MsQuicSwift +@testable import Networking +import Testing + +struct NetAddrTests { + @Test + func parseValidIPv4() async throws { + let address = "127.0.0.1:9955" + let netAddr1 = NetAddr(address: address) + let netAddr2 = NetAddr(ipAddress: "127.0.0.1", port: 9955) + #expect(netAddr1!.getAddressAndPort() == ("127.0.0.1", 9955)) + #expect(netAddr2!.getAddressAndPort() == ("127.0.0.1", 9955)) + } + + @Test + func parseValidIPv6Full() async throws { + let address = "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080" + let netAddr1 = NetAddr(address: address) + let netAddr2 = NetAddr(ipAddress: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", port: 8080) + #expect(netAddr1!.getAddressAndPort() == ("2001:db8:85a3::8a2e:370:7334", 8080)) + #expect(netAddr2!.getAddressAndPort() == ("2001:db8:85a3::8a2e:370:7334", 8080)) + } + + @Test + func parseValidIPv6Compressed() async throws { + let address = "[2001:db8:85a3::8a2e:370:7334]:8080" + let netAddr1 = NetAddr(address: address) + let netAddr2 = NetAddr(ipAddress: "2001:db8:85a3::8a2e:370:7334", port: 8080) + #expect(netAddr1 != nil) + #expect(netAddr2 != nil) + #expect(netAddr1!.getAddressAndPort() == ("2001:db8:85a3::8a2e:370:7334", 8080)) + #expect(netAddr2!.getAddressAndPort() == ("2001:db8:85a3::8a2e:370:7334", 8080)) + } + + @Test + func parseValidIPv6Loopback() async throws { + let address = "[::1]:8080" + let netAddr1 = NetAddr(address: address) + let netAddr2 = NetAddr(ipAddress: "::1", port: 8080) + #expect(netAddr1!.getAddressAndPort() == ("::1", 8080)) + #expect(netAddr2!.getAddressAndPort() == ("::1", 8080)) + } + + @Test + func parseInvalidMissingPort() async throws { + let address = "127.0.0.1" + let netAddr = NetAddr(address: address) + #expect(netAddr == nil) + } + + @Test + func parseInvalidFormat() async throws { + let address = "abcd:::" + let netAddr = NetAddr(address: address) + #expect(netAddr == nil) + } + + @Test + func parseInvalidPortIPv4() async throws { + let address = "127.0.0.1:75535" + let netAddr1 = NetAddr(address: address) + #expect(netAddr1 == nil) + } + + @Test + func parseInvalidPortIPv6() async throws { + let address = "[2001:db8::1]:75535" + let netAddr1 = NetAddr(address: address) + #expect(netAddr1 == nil) + } + + @Test + func parseInvalidIPv4Format() async throws { + let address = "256.256.256.256:8080" + let netAddr1 = NetAddr(address: address) + let netAddr2 = NetAddr(ipAddress: "256.256.256.256", port: 8080) + #expect(netAddr1 == nil) + #expect(netAddr2 == nil) + } + + @Test + func parseInvalidIPv6Format() async throws { + let address = "[2001:db8:::1]:8080" + let netAddr1 = NetAddr(address: address) + let netAddr2 = NetAddr(ipAddress: "2001:db8:::1", port: 8080) + #expect(netAddr1 == nil) + #expect(netAddr2 == nil) + } +}