From 4d982212ed0b80e351fff12883b612ddd2c2a0d4 Mon Sep 17 00:00:00 2001 From: MacOMNI <414294494@qq.com> Date: Wed, 23 Oct 2024 06:55:56 +0800 Subject: [PATCH 1/6] update --- ...eerTest.swift => MockPeerEventTests.swift} | 2 +- .../Tests/NetworkingTests/PeerTests.swift | 137 ++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) rename Networking/Tests/NetworkingTests/{PeerTest.swift => MockPeerEventTests.swift} (99%) create mode 100644 Networking/Tests/NetworkingTests/PeerTests.swift diff --git a/Networking/Tests/NetworkingTests/PeerTest.swift b/Networking/Tests/NetworkingTests/MockPeerEventTests.swift similarity index 99% rename from Networking/Tests/NetworkingTests/PeerTest.swift rename to Networking/Tests/NetworkingTests/MockPeerEventTests.swift index d35f166a..0d88c2c1 100644 --- a/Networking/Tests/NetworkingTests/PeerTest.swift +++ b/Networking/Tests/NetworkingTests/MockPeerEventTests.swift @@ -5,7 +5,7 @@ import Utils @testable import Networking -final class PeerTests { +final class MockPeerEventTests { let registration: QuicRegistration let certData: Data let badCertData: Data diff --git a/Networking/Tests/NetworkingTests/PeerTests.swift b/Networking/Tests/NetworkingTests/PeerTests.swift new file mode 100644 index 00000000..2d79bc9a --- /dev/null +++ b/Networking/Tests/NetworkingTests/PeerTests.swift @@ -0,0 +1,137 @@ +import Foundation +import MsQuicSwift +import Testing +import Utils + +@testable import Networking + +struct PeerTests { + struct MockMessage: MessageProtocol { + let data: Data + func encode() throws -> Data { + data + } + } + + struct MockRequest: RequestProtocol { + var kind: Kind + var data: Data + func encode() throws -> Data { + data + } + + typealias StreamKind = Kind + } + + public enum UniquePresistentStreamKind: UInt8, StreamKindProtocol { + case uniqueA = 0x01 + case uniqueB = 0x02 + case uniqueC = 0x03 + } + + public enum EphemeralStreamKind: UInt8, StreamKindProtocol { + case typeA = 0x04 + case typeB = 0x05 + case typeC = 0x06 + } + + struct MockMessageDecoder: MessageDecoder { + typealias Message = MockMessage + + func decode(data: Data) throws -> Message { + MockMessage(data: data) + } + + func finish() -> Data? { + print("MockMessageDecoder finish") + return nil + } + } + + struct MockEphemeralStreamHandler: EphemeralStreamHandler { + typealias StreamKind = EphemeralStreamKind + typealias Request = MockRequest + + func createDecoder(kind _: StreamKind) -> any MessageDecoder { + return MockMessageDecoder() as! any MessageDecoder + } + + // deal with data + func handle(connection _: any ConnectionInfoProtocol, request _: Request) async throws -> Data { + print("MockEphemeralStreamHandler handle") + return Data() + } + } + + struct MockPresentStreamHandler: PresistentStreamHandler { + func streamOpened( + connection _: any Networking.ConnectionInfoProtocol, + stream _: any Networking.StreamProtocol, kind _: PeerTests.UniquePresistentStreamKind + ) async throws { + print("streamOpened") + } + + func handle( + connection _: any Networking.ConnectionInfoProtocol, + message _: PeerTests.MockRequest + ) async throws { + print("handle") + } + + typealias StreamKind = UniquePresistentStreamKind + typealias Request = MockRequest + + func createDecoder(kind _: StreamKind) -> any MessageDecoder { + return MockMessageDecoder() as! any MessageDecoder + } + + func handle(connection _: any ConnectionInfoProtocol, request _: Request) async throws -> Data { + Data() + } + } + + struct MockStreamHandler: StreamHandler { + typealias PresistentHandler = MockPresentStreamHandler + + typealias EphemeralHandler = MockEphemeralStreamHandler + } + + @Test + func peerInit() async throws { + let peer1 = try Peer( + options: PeerOptions( + mode: .validator, + listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 8081)!, + genesisHeader: Data32(), + secretKey: Ed25519.SecretKey(from: Data32()), + presistentStreamHandler: MockPresentStreamHandler(), + ephemeralStreamHandler: MockEphemeralStreamHandler(), + serverSettings: .defaultSettings, + clientSettings: .defaultSettings + ) + ) + let peer2 = try Peer( + options: PeerOptions( + mode: .validator, + listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 8082)!, + genesisHeader: Data32(), + secretKey: Ed25519.SecretKey(from: Data32()), + presistentStreamHandler: MockPresentStreamHandler(), + ephemeralStreamHandler: MockEphemeralStreamHandler(), + serverSettings: .defaultSettings, + clientSettings: .defaultSettings + ) + ) + let connection = try peer1.connect( + to: NetAddr(ipAddress: "127.0.0.1", port: 8082)!, mode: .validator + ) + try? await Task.sleep(for: .seconds(2)) + let data = try await connection.request(MockRequest(kind: .typeA, data: Data("hello world".utf8))) + if let string = String(data: data, encoding: .utf8) { + print(string) + } else { + print("Failed to convert Data to String") + } + try? await Task.sleep(for: .seconds(10)) + } +} From 83afeeaa6d80de41eabcb26b196aae9c63af49b7 Mon Sep 17 00:00:00 2001 From: MacOMNI <414294494@qq.com> Date: Wed, 23 Oct 2024 09:29:35 +0800 Subject: [PATCH 2/6] update netaddr test --- Boka/Package.resolved | 4 ++-- Networking/Sources/MsQuicSwift/NetAddr.swift | 4 ++-- .../Tests/MsQuicSwiftTests/NetAddrTests.swift | 12 +++++++++--- .../xcshareddata/swiftpm/Package.resolved | 14 +++++++------- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Boka/Package.resolved b/Boka/Package.resolved index fbf27596..c4ca695a 100644 --- a/Boka/Package.resolved +++ b/Boka/Package.resolved @@ -6,8 +6,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/gh123man/Async-Channels.git", "state" : { - "revision" : "37d32cfc70f08b72a38a2c40f65338ee023afa45", - "version" : "1.0.1" + "revision" : "e4c71cd0364532d34b27e76f4ab7229abaaaefb4", + "version" : "1.0.2" } }, { diff --git a/Networking/Sources/MsQuicSwift/NetAddr.swift b/Networking/Sources/MsQuicSwift/NetAddr.swift index e6593558..245e201d 100644 --- a/Networking/Sources/MsQuicSwift/NetAddr.swift +++ b/Networking/Sources/MsQuicSwift/NetAddr.swift @@ -104,7 +104,7 @@ private func parseQuicAddr(_ addr: QUIC_ADDR) -> (String, UInt16, Bool)? { 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 ipv4WithPortPattern = #"(\#(ipv4Pattern)):(\d{1,5})(?=\s*$|\s+)"# let regex = try? NSRegularExpression(pattern: ipv4WithPortPattern, options: []) let range = NSRange(location: 0, length: address.utf16.count) @@ -142,7 +142,7 @@ private func parseIpv6Addr(_ address: String) -> (String, UInt16)? { "|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::", ")", ].reduce("", +) - let ipv6WithPortPattern = #"\[(\#(ipv6Pattern))\]:(\d{1,5})"# + let ipv6WithPortPattern = #"\[(\#(ipv6Pattern))\]:(\d{1,5})(?=\s*$|\s+)"# let regex = try? NSRegularExpression(pattern: ipv6WithPortPattern, options: []) let range = NSRange(location: 0, length: address.utf16.count) diff --git a/Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift b/Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift index 7ef858b0..dbd3104c 100644 --- a/Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift +++ b/Networking/Tests/MsQuicSwiftTests/NetAddrTests.swift @@ -51,9 +51,15 @@ struct NetAddrTests { @Test func parseInvalidFormat() async throws { - let address = "abcd:::" - let netAddr = NetAddr(address: address) - #expect(netAddr == nil) + let address1 = "abcd:::" + let netAddr1 = NetAddr(address: address1) + #expect(netAddr1 == nil) + let address2 = "127.0.0.1:12,awef" + let netAddr2 = NetAddr(address: address2) + #expect(netAddr2 == nil) + let address3 = "[2001:db8:85a3::8a2e:370:7334]:8080,8081,8082" + let netAddr3 = NetAddr(address: address3) + #expect(netAddr3 == nil) } @Test diff --git a/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3b97f812..346b6588 100644 --- a/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/boka.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "15c8990c2a71904ae0fb2311d87b37d53447f70bb359a55f0a30906bb5dcd56f", + "originHash" : "a1c5a905aa50d79012ebf1996304b1c1eb89ff484b4c2fb93ed061eca43155f6", "pins" : [ { "identity" : "async-channels", "kind" : "remoteSourceControl", "location" : "https://github.com/gh123man/Async-Channels.git", "state" : { - "revision" : "37d32cfc70f08b72a38a2c40f65338ee023afa45", - "version" : "1.0.1" + "revision" : "e4c71cd0364532d34b27e76f4ab7229abaaaefb4", + "version" : "1.0.2" } }, { @@ -87,8 +87,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-asn1.git", "state" : { - "revision" : "df5d2fcd22e3f480e3ef85bf23e277a4a0ef524d", - "version" : "1.2.0" + "revision" : "7faebca1ea4f9aaf0cda1cef7c43aecd2311ddf6", + "version" : "1.3.0" } }, { @@ -114,8 +114,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-certificates.git", "state" : { - "revision" : "2f797305c1b5b982acaa6005d8a9f970cc4e97ff", - "version" : "1.5.0" + "revision" : "1fbb6ef21f1525ed5faf4c95207b9c11bea27e94", + "version" : "1.6.1" } }, { From 8849624c9f5801a81bb8919be16c362675fdf425 Mon Sep 17 00:00:00 2001 From: MacOMNI <414294494@qq.com> Date: Wed, 23 Oct 2024 11:10:37 +0800 Subject: [PATCH 3/6] update peer test --- Networking/Sources/CHelpers/helpers.c | 83 ++++++ Networking/Sources/CHelpers/helpers.h | 10 +- Networking/Sources/Networking/PKCS12.swift | 42 ++- Networking/Sources/Networking/Peer.swift | 4 +- .../NetworkingTests/MockPeerEventTests.swift | 60 ++++ .../Tests/NetworkingTests/PKCS12Tests.swift | 6 +- .../Tests/NetworkingTests/PeerTests.swift | 275 +++++++++--------- 7 files changed, 327 insertions(+), 153 deletions(-) diff --git a/Networking/Sources/CHelpers/helpers.c b/Networking/Sources/CHelpers/helpers.c index 0e449fc9..d0a9fbc8 100644 --- a/Networking/Sources/CHelpers/helpers.c +++ b/Networking/Sources/CHelpers/helpers.c @@ -7,6 +7,89 @@ #include "helpers.h" +int parse_certificate( + const unsigned char *data, + size_t length, + unsigned char **public_key, + size_t *public_key_len, + char **alt_name, + char **error_message) +{ + int ret = -1; + BIO *bio = NULL; + X509 *cert = NULL; + STACK_OF(GENERAL_NAME) *alt_names = NULL; + + // Create BIO from certificate data + bio = BIO_new_mem_buf(data, (int)length); + if (!bio) { + *error_message = "Failed to create BIO."; + goto cleanup; + } + + // Parse the X509 certificate from the BIO + cert = d2i_X509_bio(bio, NULL); + if (!cert) { + *error_message = "Failed to parse X509 certificate."; + goto cleanup; + } + + // Extract the public key from the certificate + EVP_PKEY *pkey = X509_get_pubkey(cert); + if (!pkey) { + *error_message = "Failed to get public key from certificate."; + goto cleanup; + } + + // Get the raw public key + if (EVP_PKEY_get_raw_public_key(pkey, NULL, public_key_len) <= 0) { + *error_message = "Failed to get public key length."; + goto cleanup; + } + *public_key = (unsigned char *)malloc(*public_key_len); + if (!*public_key) { + *error_message = "Failed to allocate memory for public key."; + goto cleanup; + } + + if (EVP_PKEY_get_raw_public_key(pkey, *public_key, public_key_len) <= 0) { + *error_message = "Failed to extract public key."; + goto cleanup; + } + + // Extract the alternative name from the certificate (if present) + alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + if (alt_names) { + for (int i = 0; i < sk_GENERAL_NAME_num(alt_names); i++) { + GENERAL_NAME *gen_name = sk_GENERAL_NAME_value(alt_names, i); + if (gen_name->type == GEN_DNS) { + ASN1_STRING *name = gen_name->d.dNSName; + *alt_name = strdup((char *)ASN1_STRING_get0_data(name)); + break; + } + } + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + } + + if (!*alt_name) { + *error_message = "No alternative name found."; + goto cleanup; + } + + ret = EXIT_SUCCESS; // Success + +cleanup: + if (ret != 0 && *public_key) { + free(*public_key); + *public_key = NULL; + } + BIO_free(bio); + EVP_PKEY_free(pkey); + X509_free(cert); + + return ret; +} + // Function to parse certificate and extract public key and alternative name int parse_pkcs12_certificate( const unsigned char *data, diff --git a/Networking/Sources/CHelpers/helpers.h b/Networking/Sources/CHelpers/helpers.h index 3c269797..869f6659 100644 --- a/Networking/Sources/CHelpers/helpers.h +++ b/Networking/Sources/CHelpers/helpers.h @@ -1,6 +1,14 @@ #include #include +int parse_certificate( + const unsigned char *data, + size_t length, + unsigned char **public_key, + size_t *public_key_len, + char **alt_name, + char **error_message); + int parse_pkcs12_certificate( const unsigned char *data, size_t length, @@ -21,4 +29,4 @@ char *get_error_string(int error); static inline uint16_t helper_ntohs(in_port_t netport) { return ntohs(netport); -} \ No newline at end of file +} diff --git a/Networking/Sources/Networking/PKCS12.swift b/Networking/Sources/Networking/PKCS12.swift index 0120c824..b6f6c74c 100644 --- a/Networking/Sources/Networking/PKCS12.swift +++ b/Networking/Sources/Networking/PKCS12.swift @@ -7,21 +7,43 @@ enum CryptoError: Error { case parseFailed(String) } -public func parseCertificate(data: Data) throws -> (publicKey: Data, alternativeName: String) { +public enum CertificateType { + case x509 + case p12 +} + +public func parseCertificate(data: Data, type: CertificateType) throws -> ( + publicKey: Data, alternativeName: String +) { var publicKeyPointer: UnsafeMutablePointer! var publicKeyLen = 0 var altNamePointer: UnsafeMutablePointer! var errorMessage: UnsafeMutablePointer? defer { free(altNamePointer) } - let result = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in - parse_pkcs12_certificate( - bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), - data.count, - &publicKeyPointer, - &publicKeyLen, - &altNamePointer, - &errorMessage - ) + + let result: Int32 = switch type { + case .x509: + data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in + parse_certificate( + bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), + data.count, + &publicKeyPointer, + &publicKeyLen, + &altNamePointer, + &errorMessage + ) + } + case .p12: + data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in + parse_pkcs12_certificate( + bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), + data.count, + &publicKeyPointer, + &publicKeyLen, + &altNamePointer, + &errorMessage + ) + } } guard result == 0 else { diff --git a/Networking/Sources/Networking/Peer.swift b/Networking/Sources/Networking/Peer.swift index 33f026fe..b3f5e072 100644 --- a/Networking/Sources/Networking/Peer.swift +++ b/Networking/Sources/Networking/Peer.swift @@ -266,7 +266,7 @@ private struct PeerEventHandler: QuicEventHandler { return .code(.requiredCert) } do { - let (publicKey, alternativeName) = try parseCertificate(data: certificate) + let (publicKey, alternativeName) = try parseCertificate(data: certificate,type: .x509) logger.debug( "Certificate parsed", metadata: ["publicKey": "\(publicKey.toHexString())", "alternativeName": "\(alternativeName)"] @@ -385,7 +385,7 @@ public final class MockPeerEventHandler: QuicEventHandler { return .code(.requiredCert) } do { - let (publicKey, alternativeName) = try parseCertificate(data: certificate) + let (publicKey, alternativeName) = try parseCertificate(data: certificate,type: .x509) if alternativeName != generateSubjectAlternativeName(pubkey: publicKey) { return .code(.badCert) } diff --git a/Networking/Tests/NetworkingTests/MockPeerEventTests.swift b/Networking/Tests/NetworkingTests/MockPeerEventTests.swift index 0d88c2c1..1ad9adda 100644 --- a/Networking/Tests/NetworkingTests/MockPeerEventTests.swift +++ b/Networking/Tests/NetworkingTests/MockPeerEventTests.swift @@ -98,6 +98,66 @@ final class MockPeerEventTests { ) } + @Test + func connected() async throws { + let serverHandler = MockPeerEventHandler() + let clientHandler = MockPeerEventHandler() + let privateKey1 = try Ed25519.SecretKey(from: Data32()) + let cert = try generateSelfSignedCertificate(privateKey: privateKey1) + let serverConfiguration = try QuicConfiguration( + registration: registration, + pkcs12: certData, + alpns: [Data("testalpn".utf8)], + client: false, + settings: QuicSettings.defaultSettings + ) + + let listener = try QuicListener( + handler: serverHandler, + registration: registration, + configuration: serverConfiguration, + listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 0)!, + alpns: [Data("testalpn".utf8)] + ) + + let listenAddress = try listener.listenAddress() + // Client setup with certificate + let clientConfiguration = try QuicConfiguration( + registration: registration, + pkcs12: cert, + alpns: [Data("testalpn".utf8)], + client: true, + settings: QuicSettings.defaultSettings + ) + + let clientConnection = try QuicConnection( + handler: clientHandler, + registration: registration, + configuration: clientConfiguration + ) + + // Attempt to connect + try clientConnection.connect(to: listenAddress) + let stream1 = try clientConnection.createStream() + try stream1.send(data: Data("test data 1".utf8)) + + try? await Task.sleep(for: .milliseconds(100)) + let (_, info) = serverHandler.events.value.compactMap { + switch $0 { + case let .newConnection(_, connection, info): + (connection, info) as (QuicConnection, ConnectionInfo)? + default: + nil + } + }.first! + let (ipAddress2, _) = info.remoteAddress.getAddressAndPort() + + #expect(info.negotiatedAlpn == Data("testalpn".utf8)) + #expect(info.serverName == "127.0.0.1") + #expect(info.localAddress == listenAddress) + #expect(ipAddress2 == "127.0.0.1") + } + @Test func rejectsConDueToBadClientCert() async throws { let serverHandler = MockPeerEventHandler() diff --git a/Networking/Tests/NetworkingTests/PKCS12Tests.swift b/Networking/Tests/NetworkingTests/PKCS12Tests.swift index a884b6de..19b5801d 100644 --- a/Networking/Tests/NetworkingTests/PKCS12Tests.swift +++ b/Networking/Tests/NetworkingTests/PKCS12Tests.swift @@ -8,14 +8,14 @@ import Utils struct PKCS12Tests { @Test func invalidParseCertificate() async throws { #expect(throws: CryptoError.self) { - _ = try parseCertificate(data: Data("wrong cert data".utf8)) + _ = try parseCertificate(data: Data("wrong cert data".utf8), type: .p12) } } - @Test func vailidParseCertificate() async throws { + @Test func vailidParseP12Certificate() async throws { let privateKey = try Ed25519.SecretKey(from: Data32()) let cert = try generateSelfSignedCertificate(privateKey: privateKey) - let (publicKey, alternativeName) = try parseCertificate(data: cert) + let (publicKey, alternativeName) = try parseCertificate(data: cert, type: .p12) #expect(alternativeName == generateSubjectAlternativeName(publicKey: privateKey.publicKey)) #expect(Data32(publicKey) == privateKey.publicKey.data) } diff --git a/Networking/Tests/NetworkingTests/PeerTests.swift b/Networking/Tests/NetworkingTests/PeerTests.swift index 2d79bc9a..0846d22f 100644 --- a/Networking/Tests/NetworkingTests/PeerTests.swift +++ b/Networking/Tests/NetworkingTests/PeerTests.swift @@ -1,137 +1,138 @@ -import Foundation -import MsQuicSwift -import Testing -import Utils - -@testable import Networking - -struct PeerTests { - struct MockMessage: MessageProtocol { - let data: Data - func encode() throws -> Data { - data - } - } - - struct MockRequest: RequestProtocol { - var kind: Kind - var data: Data - func encode() throws -> Data { - data - } - - typealias StreamKind = Kind - } - - public enum UniquePresistentStreamKind: UInt8, StreamKindProtocol { - case uniqueA = 0x01 - case uniqueB = 0x02 - case uniqueC = 0x03 - } - - public enum EphemeralStreamKind: UInt8, StreamKindProtocol { - case typeA = 0x04 - case typeB = 0x05 - case typeC = 0x06 - } - - struct MockMessageDecoder: MessageDecoder { - typealias Message = MockMessage - - func decode(data: Data) throws -> Message { - MockMessage(data: data) - } - - func finish() -> Data? { - print("MockMessageDecoder finish") - return nil - } - } - - struct MockEphemeralStreamHandler: EphemeralStreamHandler { - typealias StreamKind = EphemeralStreamKind - typealias Request = MockRequest - - func createDecoder(kind _: StreamKind) -> any MessageDecoder { - return MockMessageDecoder() as! any MessageDecoder - } - - // deal with data - func handle(connection _: any ConnectionInfoProtocol, request _: Request) async throws -> Data { - print("MockEphemeralStreamHandler handle") - return Data() - } - } - - struct MockPresentStreamHandler: PresistentStreamHandler { - func streamOpened( - connection _: any Networking.ConnectionInfoProtocol, - stream _: any Networking.StreamProtocol, kind _: PeerTests.UniquePresistentStreamKind - ) async throws { - print("streamOpened") - } - - func handle( - connection _: any Networking.ConnectionInfoProtocol, - message _: PeerTests.MockRequest - ) async throws { - print("handle") - } - - typealias StreamKind = UniquePresistentStreamKind - typealias Request = MockRequest - - func createDecoder(kind _: StreamKind) -> any MessageDecoder { - return MockMessageDecoder() as! any MessageDecoder - } - - func handle(connection _: any ConnectionInfoProtocol, request _: Request) async throws -> Data { - Data() - } - } - - struct MockStreamHandler: StreamHandler { - typealias PresistentHandler = MockPresentStreamHandler - - typealias EphemeralHandler = MockEphemeralStreamHandler - } - - @Test - func peerInit() async throws { - let peer1 = try Peer( - options: PeerOptions( - mode: .validator, - listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 8081)!, - genesisHeader: Data32(), - secretKey: Ed25519.SecretKey(from: Data32()), - presistentStreamHandler: MockPresentStreamHandler(), - ephemeralStreamHandler: MockEphemeralStreamHandler(), - serverSettings: .defaultSettings, - clientSettings: .defaultSettings - ) - ) - let peer2 = try Peer( - options: PeerOptions( - mode: .validator, - listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 8082)!, - genesisHeader: Data32(), - secretKey: Ed25519.SecretKey(from: Data32()), - presistentStreamHandler: MockPresentStreamHandler(), - ephemeralStreamHandler: MockEphemeralStreamHandler(), - serverSettings: .defaultSettings, - clientSettings: .defaultSettings - ) - ) - let connection = try peer1.connect( - to: NetAddr(ipAddress: "127.0.0.1", port: 8082)!, mode: .validator - ) - try? await Task.sleep(for: .seconds(2)) - let data = try await connection.request(MockRequest(kind: .typeA, data: Data("hello world".utf8))) - if let string = String(data: data, encoding: .utf8) { - print(string) - } else { - print("Failed to convert Data to String") - } - try? await Task.sleep(for: .seconds(10)) - } -} +// import Foundation +// import MsQuicSwift +// import Testing +// import Utils +// +// @testable import Networking +// +// struct PeerTests { +// struct MockMessage: MessageProtocol { +// let data: Data +// func encode() throws -> Data { +// data +// } +// } +// +// struct MockRequest: RequestProtocol { +// var kind: Kind +// var data: Data +// func encode() throws -> Data { +// data +// } +// +// typealias StreamKind = Kind +// } +// +// public enum UniquePresistentStreamKind: UInt8, StreamKindProtocol { +// case uniqueA = 0x01 +// case uniqueB = 0x02 +// case uniqueC = 0x03 +// } +// +// public enum EphemeralStreamKind: UInt8, StreamKindProtocol { +// case typeA = 0x04 +// case typeB = 0x05 +// case typeC = 0x06 +// } +// +// struct MockMessageDecoder: MessageDecoder { +// typealias Message = MockMessage +// +// func decode(data: Data) throws -> Message { +// MockMessage(data: data) +// } +// +// func finish() -> Data? { +// print("MockMessageDecoder finish") +// return nil +// } +// } +// +// struct MockEphemeralStreamHandler: EphemeralStreamHandler { +// typealias StreamKind = EphemeralStreamKind +// typealias Request = MockRequest +// +// func createDecoder(kind _: StreamKind) -> any MessageDecoder { +// return MockMessageDecoder() as! any MessageDecoder +// } +// +// // deal with data +// func handle(connection _: any ConnectionInfoProtocol, request _: Request) async throws -> Data { +// print("MockEphemeralStreamHandler handle") +// return Data() +// } +// } +// +// struct MockPresentStreamHandler: PresistentStreamHandler { +// func streamOpened( +// connection _: any Networking.ConnectionInfoProtocol, +// stream _: any Networking.StreamProtocol, kind _: PeerTests.UniquePresistentStreamKind +// ) async throws { +// print("streamOpened") +// } +// +// func handle( +// connection _: any Networking.ConnectionInfoProtocol, +// message _: PeerTests.MockRequest +// ) async throws { +// print("handle") +// } +// +// typealias StreamKind = UniquePresistentStreamKind +// typealias Request = MockRequest +// +// func createDecoder(kind _: StreamKind) -> any MessageDecoder { +// return MockMessageDecoder() as! any MessageDecoder +// } +// +// func handle(connection _: any ConnectionInfoProtocol, request _: Request) async throws -> Data { +// Data() +// } +// } +// +// struct MockStreamHandler: StreamHandler { +// typealias PresistentHandler = MockPresentStreamHandler +// +// typealias EphemeralHandler = MockEphemeralStreamHandler +// } +// +// @Test +// func peerInit() async throws { +// let peer1 = try Peer( +// options: PeerOptions( +// mode: .validator, +// listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 8081)!, +// genesisHeader: Data32(), +// secretKey: Ed25519.SecretKey(from: Data32()), +// presistentStreamHandler: MockPresentStreamHandler(), +// ephemeralStreamHandler: MockEphemeralStreamHandler(), +// serverSettings: .defaultSettings, +// clientSettings: .defaultSettings +// ) +// ) +// let peer2 = try Peer( +// options: PeerOptions( +// mode: .validator, +// listenAddress: NetAddr(ipAddress: "127.0.0.1", port: 8082)!, +// genesisHeader: Data32(), +// secretKey: Ed25519.SecretKey(from: Data32()), +// presistentStreamHandler: MockPresentStreamHandler(), +// ephemeralStreamHandler: MockEphemeralStreamHandler(), +// serverSettings: .defaultSettings, +// clientSettings: .defaultSettings +// ) +// ) +// try? await Task.sleep(for: .seconds(1)) +// let connection = try peer1.connect( +// to: NetAddr(ipAddress: "127.0.0.1", port: 8082)!, mode: .validator +// ) +// try? await Task.sleep(for: .seconds(2)) +// let data = try await connection.request(MockRequest(kind: .typeA, data: Data("hello world".utf8))) +//// if let string = String(data: data, encoding: .utf8) { +//// print(string) +//// } else { +//// print("Failed to convert Data to String") +//// } +// try? await Task.sleep(for: .seconds(10)) +// } +// } From fa4d69e5efb9ad657814407b9a9f207dea800ca2 Mon Sep 17 00:00:00 2001 From: MacOMNI <414294494@qq.com> Date: Wed, 23 Oct 2024 11:18:07 +0800 Subject: [PATCH 4/6] update peer test --- Networking/Sources/Networking/PKCS12.swift | 47 ++++++------ Networking/Sources/Networking/Peer.swift | 87 +++++++++++++--------- 2 files changed, 77 insertions(+), 57 deletions(-) diff --git a/Networking/Sources/Networking/PKCS12.swift b/Networking/Sources/Networking/PKCS12.swift index b6f6c74c..a352477f 100644 --- a/Networking/Sources/Networking/PKCS12.swift +++ b/Networking/Sources/Networking/PKCS12.swift @@ -21,30 +21,31 @@ public func parseCertificate(data: Data, type: CertificateType) throws -> ( var errorMessage: UnsafeMutablePointer? defer { free(altNamePointer) } - let result: Int32 = switch type { - case .x509: - data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in - parse_certificate( - bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), - data.count, - &publicKeyPointer, - &publicKeyLen, - &altNamePointer, - &errorMessage - ) - } - case .p12: - data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in - parse_pkcs12_certificate( - bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), - data.count, - &publicKeyPointer, - &publicKeyLen, - &altNamePointer, - &errorMessage - ) + let result: Int32 = + switch type { + case .x509: + data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in + parse_certificate( + bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), + data.count, + &publicKeyPointer, + &publicKeyLen, + &altNamePointer, + &errorMessage + ) + } + case .p12: + data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in + parse_pkcs12_certificate( + bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), + data.count, + &publicKeyPointer, + &publicKeyLen, + &altNamePointer, + &errorMessage + ) + } } - } guard result == 0 else { throw CryptoError.parseFailed(String(cString: errorMessage!)) diff --git a/Networking/Sources/Networking/Peer.swift b/Networking/Sources/Networking/Peer.swift index b3f5e072..dc529615 100644 --- a/Networking/Sources/Networking/Peer.swift +++ b/Networking/Sources/Networking/Peer.swift @@ -73,12 +73,14 @@ public final class Peer: Sendable { let registration = try QuicRegistration() let serverConfiguration = try QuicConfiguration( - registration: registration, pkcs12: pkcs12, alpns: allAlpns, client: false, settings: options.serverSettings + registration: registration, pkcs12: pkcs12, alpns: allAlpns, client: false, + settings: options.serverSettings ) let clientAlpn = alpns[options.mode]! let clientConfiguration = try QuicConfiguration( - registration: registration, pkcs12: pkcs12, alpns: [clientAlpn], client: true, settings: options.clientSettings + registration: registration, pkcs12: pkcs12, alpns: [clientAlpn], client: true, + settings: options.clientSettings ) impl = PeerImpl( @@ -104,26 +106,27 @@ public final class Peer: Sendable { let conn = impl.connections.read { connections in connections.byType[mode]?[address] } - return try conn ?? impl.connections.write { connections in - let curr = connections.byType[mode, default: [:]][address] - if let curr { - return curr + return try conn + ?? impl.connections.write { connections in + let curr = connections.byType[mode, default: [:]][address] + if let curr { + return curr + } + let conn = try Connection( + QuicConnection( + handler: PeerEventHandler(self.impl), + registration: self.impl.clientConfiguration.registration, + configuration: self.impl.clientConfiguration + ), + impl: self.impl, + mode: mode, + remoteAddress: address, + initiatedByLocal: true + ) + connections.byType[mode, default: [:]][address] = conn + connections.byId[conn.id] = conn + return conn } - let conn = try Connection( - QuicConnection( - handler: PeerEventHandler(self.impl), - registration: self.impl.clientConfiguration.registration, - configuration: self.impl.clientConfiguration - ), - impl: self.impl, - mode: mode, - remoteAddress: address, - initiatedByLocal: true - ) - connections.byType[mode, default: [:]][address] = conn - connections.byId[conn.id] = conn - return conn - } } public func broadcast(kind: Handler.PresistentHandler.StreamKind, message: any MessageProtocol) { @@ -142,11 +145,14 @@ public final class Peer: Sendable { case .success: break case let .failure(error): - impl.logger.warning("Failed to send message", metadata: [ - "connectionId": "\(connection.id)", - "kind": "\(kind)", - "error": "\(error)", - ]) + impl.logger.warning( + "Failed to send message", + metadata: [ + "connectionId": "\(connection.id)", + "kind": "\(kind)", + "error": "\(error)", + ] + ) } } } @@ -245,11 +251,15 @@ private struct PeerEventHandler: QuicEventHandler { self.impl = impl } - func newConnection(_: QuicListener, connection: QuicConnection, info: ConnectionInfo) -> QuicStatus { + func newConnection(_: QuicListener, connection: QuicConnection, info: ConnectionInfo) + -> QuicStatus + { let addr = info.remoteAddress let mode = impl.alpnLookup[info.negotiatedAlpn] guard let mode else { - logger.warning("unknown alpn: \(String(data: info.negotiatedAlpn, encoding: .utf8) ?? info.negotiatedAlpn.toDebugHexString())") + logger.warning( + "unknown alpn: \(String(data: info.negotiatedAlpn, encoding: .utf8) ?? info.negotiatedAlpn.toDebugHexString())" + ) return .code(.alpnNegFailure) } logger.debug("new connection: \(addr) mode: \(mode)") @@ -266,10 +276,13 @@ private struct PeerEventHandler: QuicEventHandler { return .code(.requiredCert) } do { - let (publicKey, alternativeName) = try parseCertificate(data: certificate,type: .x509) + let (publicKey, alternativeName) = try parseCertificate(data: certificate, type: .x509) logger.debug( "Certificate parsed", - metadata: ["publicKey": "\(publicKey.toHexString())", "alternativeName": "\(alternativeName)"] + metadata: [ + "publicKey": "\(publicKey.toHexString())", + "alternativeName": "\(alternativeName)", + ] ) if alternativeName != generateSubjectAlternativeName(pubkey: publicKey) { return .code(.badCert) @@ -289,7 +302,9 @@ private struct PeerEventHandler: QuicEventHandler { connections.byId[connection.id] } guard let conn else { - logger.warning("Connected but connection is gone?", metadata: ["connectionId": "\(connection.id)"]) + logger.warning( + "Connected but connection is gone?", metadata: ["connectionId": "\(connection.id)"] + ) return } @@ -347,10 +362,14 @@ private struct PeerEventHandler: QuicEventHandler { if let connection { connection.streamClosed(stream: stream, abort: !status.isSucceeded) } else { - logger.warning("Stream closed but connection is gone?", metadata: ["streamId": "\(stream.id)"]) + logger.warning( + "Stream closed but connection is gone?", metadata: ["streamId": "\(stream.id)"] + ) } } else { - logger.warning("Stream closed but stream is gone?", metadata: ["streamId": "\(quicStream.id)"]) + logger.warning( + "Stream closed but stream is gone?", metadata: ["streamId": "\(quicStream.id)"] + ) } } } @@ -385,7 +404,7 @@ public final class MockPeerEventHandler: QuicEventHandler { return .code(.requiredCert) } do { - let (publicKey, alternativeName) = try parseCertificate(data: certificate,type: .x509) + let (publicKey, alternativeName) = try parseCertificate(data: certificate, type: .x509) if alternativeName != generateSubjectAlternativeName(pubkey: publicKey) { return .code(.badCert) } From b9b5f64bb5b98cb2076bf0cccaf93d16312b8ce9 Mon Sep 17 00:00:00 2001 From: MacOMNI <414294494@qq.com> Date: Wed, 23 Oct 2024 11:44:22 +0800 Subject: [PATCH 5/6] update test From bb5b3b04c805641cd613cbae76e066f6084be50f Mon Sep 17 00:00:00 2001 From: MacOMNI <414294494@qq.com> Date: Wed, 23 Oct 2024 12:01:33 +0800 Subject: [PATCH 6/6] update peer --- Networking/Sources/Networking/Peer.swift | 83 +++++++++--------------- 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/Networking/Sources/Networking/Peer.swift b/Networking/Sources/Networking/Peer.swift index dc529615..43e10752 100644 --- a/Networking/Sources/Networking/Peer.swift +++ b/Networking/Sources/Networking/Peer.swift @@ -73,14 +73,12 @@ public final class Peer: Sendable { let registration = try QuicRegistration() let serverConfiguration = try QuicConfiguration( - registration: registration, pkcs12: pkcs12, alpns: allAlpns, client: false, - settings: options.serverSettings + registration: registration, pkcs12: pkcs12, alpns: allAlpns, client: false, settings: options.serverSettings ) let clientAlpn = alpns[options.mode]! let clientConfiguration = try QuicConfiguration( - registration: registration, pkcs12: pkcs12, alpns: [clientAlpn], client: true, - settings: options.clientSettings + registration: registration, pkcs12: pkcs12, alpns: [clientAlpn], client: true, settings: options.clientSettings ) impl = PeerImpl( @@ -106,27 +104,26 @@ public final class Peer: Sendable { let conn = impl.connections.read { connections in connections.byType[mode]?[address] } - return try conn - ?? impl.connections.write { connections in - let curr = connections.byType[mode, default: [:]][address] - if let curr { - return curr - } - let conn = try Connection( - QuicConnection( - handler: PeerEventHandler(self.impl), - registration: self.impl.clientConfiguration.registration, - configuration: self.impl.clientConfiguration - ), - impl: self.impl, - mode: mode, - remoteAddress: address, - initiatedByLocal: true - ) - connections.byType[mode, default: [:]][address] = conn - connections.byId[conn.id] = conn - return conn + return try conn ?? impl.connections.write { connections in + let curr = connections.byType[mode, default: [:]][address] + if let curr { + return curr } + let conn = try Connection( + QuicConnection( + handler: PeerEventHandler(self.impl), + registration: self.impl.clientConfiguration.registration, + configuration: self.impl.clientConfiguration + ), + impl: self.impl, + mode: mode, + remoteAddress: address, + initiatedByLocal: true + ) + connections.byType[mode, default: [:]][address] = conn + connections.byId[conn.id] = conn + return conn + } } public func broadcast(kind: Handler.PresistentHandler.StreamKind, message: any MessageProtocol) { @@ -145,14 +142,11 @@ public final class Peer: Sendable { case .success: break case let .failure(error): - impl.logger.warning( - "Failed to send message", - metadata: [ - "connectionId": "\(connection.id)", - "kind": "\(kind)", - "error": "\(error)", - ] - ) + impl.logger.warning("Failed to send message", metadata: [ + "connectionId": "\(connection.id)", + "kind": "\(kind)", + "error": "\(error)", + ]) } } } @@ -251,15 +245,11 @@ private struct PeerEventHandler: QuicEventHandler { self.impl = impl } - func newConnection(_: QuicListener, connection: QuicConnection, info: ConnectionInfo) - -> QuicStatus - { + func newConnection(_: QuicListener, connection: QuicConnection, info: ConnectionInfo) -> QuicStatus { let addr = info.remoteAddress let mode = impl.alpnLookup[info.negotiatedAlpn] guard let mode else { - logger.warning( - "unknown alpn: \(String(data: info.negotiatedAlpn, encoding: .utf8) ?? info.negotiatedAlpn.toDebugHexString())" - ) + logger.warning("unknown alpn: \(String(data: info.negotiatedAlpn, encoding: .utf8) ?? info.negotiatedAlpn.toDebugHexString())") return .code(.alpnNegFailure) } logger.debug("new connection: \(addr) mode: \(mode)") @@ -279,10 +269,7 @@ private struct PeerEventHandler: QuicEventHandler { let (publicKey, alternativeName) = try parseCertificate(data: certificate, type: .x509) logger.debug( "Certificate parsed", - metadata: [ - "publicKey": "\(publicKey.toHexString())", - "alternativeName": "\(alternativeName)", - ] + metadata: ["publicKey": "\(publicKey.toHexString())", "alternativeName": "\(alternativeName)"] ) if alternativeName != generateSubjectAlternativeName(pubkey: publicKey) { return .code(.badCert) @@ -302,9 +289,7 @@ private struct PeerEventHandler: QuicEventHandler { connections.byId[connection.id] } guard let conn else { - logger.warning( - "Connected but connection is gone?", metadata: ["connectionId": "\(connection.id)"] - ) + logger.warning("Connected but connection is gone?", metadata: ["connectionId": "\(connection.id)"]) return } @@ -362,14 +347,10 @@ private struct PeerEventHandler: QuicEventHandler { if let connection { connection.streamClosed(stream: stream, abort: !status.isSucceeded) } else { - logger.warning( - "Stream closed but connection is gone?", metadata: ["streamId": "\(stream.id)"] - ) + logger.warning("Stream closed but connection is gone?", metadata: ["streamId": "\(stream.id)"]) } } else { - logger.warning( - "Stream closed but stream is gone?", metadata: ["streamId": "\(quicStream.id)"] - ) + logger.warning("Stream closed but stream is gone?", metadata: ["streamId": "\(quicStream.id)"]) } } }