From 62ecc1648de3bdd5757ed3112db0dd68f54d4f2e Mon Sep 17 00:00:00 2001 From: youyuanwu <48816116+youyuanwu@users.noreply.github.com> Date: Wed, 18 Dec 2024 06:49:25 -0800 Subject: [PATCH 01/15] Run fmt and clippy for rust code (#4712) --- .github/workflows/cargo.yml | 4 + scripts/build.rs | 4 +- src/lib.rs | 145 ++++++++++++++++-------------------- 3 files changed, 71 insertions(+), 82 deletions(-) diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml index 3f59a77a48..689676fdbe 100644 --- a/.github/workflows/cargo.yml +++ b/.github/workflows/cargo.yml @@ -41,6 +41,10 @@ jobs: - name: Install Cargo if: runner.os == 'Linux' run: curl https://sh.rustup.rs -sSf | sh -s -- -y + - name: Cargo fmt + run: cargo fmt --all -- --check + - name: Cargo clippy + run: cargo clippy --all-targets -- -D warnings - name: Cargo build run: cargo build --all ${{ matrix.features }} - name: Cargo test diff --git a/scripts/build.rs b/scripts/build.rs index fd206a43b7..5e3d8ba4f5 100644 --- a/scripts/build.rs +++ b/scripts/build.rs @@ -2,8 +2,8 @@ // Licensed under the MIT License. use cmake::Config; -use std::path::Path; use std::env; +use std::path::Path; fn main() { let path_extra = "lib"; @@ -38,7 +38,7 @@ fn main() { "aarch64-apple-darwin" => config .define("CMAKE_OSX_ARCHITECTURES", "arm64") .define("CMAKE_OSX_DEPLOYMENT_TARGET", "14.5"), - _ => &mut config + _ => &mut config, }; let dst = config.build(); diff --git a/src/lib.rs b/src/lib.rs index 70ed8e3001..f1e48c6fa1 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,8 +33,11 @@ pub type BOOLEAN = ::std::os::raw::c_uchar; /// Family of an IP address. pub type AddressFamily = u16; +#[allow(clippy::unnecessary_cast)] pub const ADDRESS_FAMILY_UNSPEC: AddressFamily = c_types::AF_UNSPEC as u16; +#[allow(clippy::unnecessary_cast)] pub const ADDRESS_FAMILY_INET: AddressFamily = c_types::AF_INET as u16; +#[allow(clippy::unnecessary_cast)] pub const ADDRESS_FAMILY_INET6: AddressFamily = c_types::AF_INET6 as u16; /// IPv4 address payload. @@ -73,7 +76,7 @@ impl Addr { Addr { ipv4: sockaddr_in { family, - port: port, + port, addr, zero: [0, 0, 0, 0, 0, 0, 0, 0], }, @@ -92,7 +95,7 @@ impl Addr { Addr { ipv6: sockaddr_in6 { family, - port: port, + port, flow_info, addr, scope_id, @@ -128,7 +131,7 @@ mod status { pub const QUIC_STATUS_ALPN_NEG_FAILURE: u32 = 0x80410007; pub const QUIC_STATUS_STREAM_LIMIT_REACHED: u32 = 0x80410008; pub const QUIC_STATUS_ALPN_IN_USE: u32 = 0x80410009; - pub const QUIC_STATUS_CLOSE_NOTIFY: u32 = 0x80410100 | 0; + pub const QUIC_STATUS_CLOSE_NOTIFY: u32 = 0x80410100; pub const QUIC_STATUS_BAD_CERTIFICATE: u32 = 0x80410100 | 42; pub const QUIC_STATUS_UNSUPPORTED_CERTIFICATE: u32 = 0x80410100 | 43; pub const QUIC_STATUS_REVOKED_CERTIFICATE: u32 = 0x80410100 | 44; @@ -143,8 +146,8 @@ mod status { #[cfg(target_os = "linux")] mod status { pub const QUIC_STATUS_SUCCESS: u32 = 0; - pub const QUIC_STATUS_PENDING: u32 = 0xFFFFFFFE; /// -2 - pub const QUIC_STATUS_CONTINUE: u32 = 0xFFFFFFFF; /// -1 + pub const QUIC_STATUS_PENDING: u32 = 0xFFFFFFFE; // -2 + pub const QUIC_STATUS_CONTINUE: u32 = 0xFFFFFFFF; // -1 pub const QUIC_STATUS_OUT_OF_MEMORY: u32 = 12; pub const QUIC_STATUS_INVALID_PARAMETER: u32 = 22; pub const QUIC_STATUS_INVALID_STATE: u32 = 1; @@ -183,8 +186,8 @@ mod status { #[cfg(target_os = "macos")] mod status { pub const QUIC_STATUS_SUCCESS: u32 = 0; - pub const QUIC_STATUS_PENDING: u32 = 0xFFFFFFFE; /// -2 - pub const QUIC_STATUS_CONTINUE: u32 = 0xFFFFFFFF; /// -1 + pub const QUIC_STATUS_PENDING: u32 = 0xFFFFFFFE; // -2 + pub const QUIC_STATUS_CONTINUE: u32 = 0xFFFFFFFF; // -1 pub const QUIC_STATUS_OUT_OF_MEMORY: u32 = 12; pub const QUIC_STATUS_INVALID_PARAMETER: u32 = 22; pub const QUIC_STATUS_INVALID_STATE: u32 = 1; @@ -780,7 +783,7 @@ pub struct QuicTlsSecrets { } #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] pub struct Settings { pub is_set_flags: u64, pub max_bytes_per_key: u64, @@ -1216,15 +1219,10 @@ struct ApiTable { flags: SendFlags, client_send_context: *const c_void, ) -> u32, - resumption_ticket_validation_complete: extern "C" fn( - connection: Handle, - result: BOOLEAN, - ) -> u32, - certificate_validation_complete: extern "C" fn( - connection: Handle, - result: BOOLEAN, - tls_alert: TlsAlertCode - ) -> u32, + resumption_ticket_validation_complete: + extern "C" fn(connection: Handle, result: BOOLEAN) -> u32, + certificate_validation_complete: + extern "C" fn(connection: Handle, result: BOOLEAN, tls_alert: TlsAlertCode) -> u32, } #[link(name = "msquic")] @@ -1296,11 +1294,10 @@ impl From<&Vec> for Buffer { impl From<&[u8]> for Buffer { fn from(data: &[u8]) -> Buffer { - let buffer = Buffer { + Buffer { length: data.len() as u32, buffer: data.as_ptr() as *mut u8, - }; - buffer + } } } @@ -1321,38 +1318,8 @@ impl QuicPerformance { } impl Settings { - pub fn new() -> Settings { - Settings { - is_set_flags: 0, - max_bytes_per_key: 0, - handshake_idle_timeout_ms: 0, - idle_timeout_ms: 0, - mtu_discovery_search_complete_timeout_us: 0, - tls_client_max_send_buffer: 0, - tls_server_max_send_buffer: 0, - stream_recv_window_default: 0, - stream_recv_buffer_default: 0, - conn_flow_control_window: 0, - max_worker_queue_delay_us: 0, - max_stateless_operations: 0, - initial_window_packets: 0, - send_idle_timeout_ms: 0, - initiall_rtt_ms: 0, - max_ack_delay_ms: 0, - disconnect_timeout_ms: 0, - keep_alive_interval_ms: 0, - congestion_control_algorithm: 0, - peer_bidi_stream_count: 0, - peer_unidi_stream_count: 0, - max_binding_stateless_operations: 0, - stateless_operation_expiration_ms: 0, - minimum_mtu: 0, - maximum_mtu: 0, - other_flags: 0, - mtu_operations_per_drain: 0, - mtu_discovery_missing_probe_count: 0, - dest_cid_update_idle_timeout_ms: 0, - } + pub fn new() -> Self { + Self::default() } pub fn set_peer_bidi_stream_count(&mut self, value: u16) -> &mut Settings { self.is_set_flags |= 0x40000; @@ -1483,7 +1450,7 @@ impl Configuration { let context: *const c_void = ptr::null(); let new_configuration: Handle = ptr::null(); let mut settings_size: u32 = 0; - if settings != ptr::null() { + if !settings.is_null() { settings_size = ::std::mem::size_of::() as u32; } let status = unsafe { @@ -1508,7 +1475,7 @@ impl Configuration { pub fn load_credential(&self, cred_config: &CredentialConfig) -> Result<(), u32> { let status = - unsafe { ((*self.table).configuration_load_credential)(self.handle, *&cred_config) }; + unsafe { ((*self.table).configuration_load_credential)(self.handle, cred_config) }; if Status::failed(status) { return Err(status); } @@ -1552,14 +1519,19 @@ impl Connection { Ok(()) } - pub fn start(&self, configuration: &Configuration, server_name: &str, server_port: u16) -> Result<(), u32> { + pub fn start( + &self, + configuration: &Configuration, + server_name: &str, + server_port: u16, + ) -> Result<(), u32> { let server_name_safe = std::ffi::CString::new(server_name).unwrap(); let status = unsafe { ((*self.table).connection_start)( self.handle, configuration.handle, 0, - server_name_safe.as_ptr() as *const i8, + server_name_safe.as_ptr(), server_port, ) }; @@ -1660,7 +1632,7 @@ impl Connection { let status = unsafe { ((*self.table).datagram_send)( self.handle, - *&buffer, + buffer, buffer_count, flags, client_send_context, @@ -1672,16 +1644,9 @@ impl Connection { Ok(()) } - pub fn resumption_ticket_validation_complete( - &self, - result: BOOLEAN, - ) -> Result<(), u32> { - let status = unsafe { - ((*self.table).resumption_ticket_validation_complete)( - self.handle, - result, - ) - }; + pub fn resumption_ticket_validation_complete(&self, result: BOOLEAN) -> Result<(), u32> { + let status = + unsafe { ((*self.table).resumption_ticket_validation_complete)(self.handle, result) }; if Status::failed(status) { return Err(status); } @@ -1694,11 +1659,7 @@ impl Connection { tls_alert: TlsAlertCode, ) -> Result<(), u32> { let status = unsafe { - ((*self.table).certificate_validation_complete)( - self.handle, - result, - tls_alert, - ) + ((*self.table).certificate_validation_complete)(self.handle, result, tls_alert) }; if Status::failed(status) { return Err(status); @@ -1744,7 +1705,7 @@ impl Listener { self.handle, alpn.as_ptr(), alpn.len() as u32, - *&local_address, + local_address, ) }; if Status::failed(status) { @@ -1822,7 +1783,7 @@ impl Stream { let status = unsafe { ((*self.table).stream_send)( self.handle, - *&buffer, + buffer, buffer_count, flags, client_send_context, //(self as *const Stream) as *const c_void, @@ -1915,11 +1876,19 @@ extern "C" fn test_stream_callback( #[test] fn test_module() { let res = Api::new(); - assert!(res.is_ok(), "Failed to open API: 0x{:x}", res.err().unwrap()); + assert!( + res.is_ok(), + "Failed to open API: 0x{:x}", + res.err().unwrap() + ); let api = res.unwrap(); let res = Registration::new(&api, ptr::null()); - assert!(res.is_ok(), "Failed to open registration: 0x{:x}", res.err().unwrap()); + assert!( + res.is_ok(), + "Failed to open registration: 0x{:x}", + res.err().unwrap() + ); let registration = res.unwrap(); let alpn = [Buffer::from("h3")]; @@ -1930,12 +1899,20 @@ fn test_module() { .set_peer_bidi_stream_count(100) .set_peer_unidi_stream_count(3), ); - assert!(res.is_ok(), "Failed to open configuration: 0x{:x}", res.err().unwrap()); + assert!( + res.is_ok(), + "Failed to open configuration: 0x{:x}", + res.err().unwrap() + ); let configuration = res.unwrap(); let cred_config = CredentialConfig::new_client(); let res = configuration.load_credential(&cred_config); - assert!(res.is_ok(), "Failed to load credential: 0x{:x}", res.err().unwrap()); + assert!( + res.is_ok(), + "Failed to load credential: 0x{:x}", + res.err().unwrap() + ); let connection = Connection::new(®istration); let res = connection.open( @@ -1943,10 +1920,18 @@ fn test_module() { test_conn_callback, &connection as *const Connection as *const c_void, ); - assert!(res.is_ok(), "Failed to open connection: 0x{:x}", res.err().unwrap()); + assert!( + res.is_ok(), + "Failed to open connection: 0x{:x}", + res.err().unwrap() + ); let res = connection.start(&configuration, "www.cloudflare.com", 443); - assert!(res.is_ok(), "Failed to start connection: 0x{:x}", res.err().unwrap()); + assert!( + res.is_ok(), + "Failed to start connection: 0x{:x}", + res.err().unwrap() + ); let duration = std::time::Duration::from_millis(1000); std::thread::sleep(duration); From a03d5c2178108fcc3e151c610c37459eb967d457 Mon Sep 17 00:00:00 2001 From: Masahiro Kozuka Date: Fri, 20 Dec 2024 04:17:11 +0900 Subject: [PATCH 02/15] Add socket2 integration for address handling and retrieval (#4716) --- Cargo.toml | 1 + src/lib.rs | 146 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 98 insertions(+), 49 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 046819e8f1..e940c6f816 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,3 +56,4 @@ bitfield = "0.17.0" libc = "0.2.0" c-types = "4.0.0" serde = { version = "1.0.117", features = ["derive"] } +socket2 = "0.5.8" diff --git a/src/lib.rs b/src/lib.rs index f1e48c6fa1..f695ca8387 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,10 +7,15 @@ use c_types::AF_INET; use c_types::AF_INET6; #[allow(unused_imports)] use c_types::AF_UNSPEC; +use c_types::{sa_family_t, sockaddr_in, sockaddr_in6, socklen_t}; use libc::c_void; use serde::{Deserialize, Serialize}; +use socket2::SockAddr; use std::convert::TryInto; use std::fmt; +use std::io; +use std::mem; +use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use std::option::Option; use std::ptr; use std::result::Result; @@ -40,27 +45,6 @@ pub const ADDRESS_FAMILY_INET: AddressFamily = c_types::AF_INET as u16; #[allow(clippy::unnecessary_cast)] pub const ADDRESS_FAMILY_INET6: AddressFamily = c_types::AF_INET6 as u16; -/// IPv4 address payload. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct sockaddr_in { - pub family: AddressFamily, - pub port: u16, - pub addr: u32, - pub zero: [u8; 8usize], -} - -/// IPv6 address payload. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct sockaddr_in6 { - pub family: AddressFamily, - pub port: u16, - pub flow_info: u32, - pub addr: [u8; 16usize], - pub scope_id: u32, -} - /// Generic representation of IPv4 or IPv6 addresses. #[repr(C)] #[derive(Copy, Clone)] @@ -70,40 +54,66 @@ pub union Addr { } impl Addr { - /// Create a representation of IPv4 address and perform Network byte order conversion - /// on the port number. - pub fn ipv4(family: u16, port: u16, addr: u32) -> Addr { - Addr { - ipv4: sockaddr_in { - family, - port, - addr, - zero: [0, 0, 0, 0, 0, 0, 0, 0], - }, + /// Converts the `Addr` to a `SocketAddr`. + pub fn as_socket(&self) -> Option { + unsafe { + SockAddr::try_init(|addr, len| { + if self.ipv4.sin_family == AF_INET as sa_family_t { + let addr = addr.cast::(); + *addr = self.ipv4; + *len = mem::size_of::() as socklen_t; + Ok(()) + } else if self.ipv4.sin_family == AF_INET6 as sa_family_t { + let addr = addr.cast::(); + *addr = self.ipv6; + *len = mem::size_of::() as socklen_t; + Ok(()) + } else { + Err(io::Error::from(io::ErrorKind::Other)) + } + }) } + .map(|((), addr)| addr.as_socket().unwrap()) + .ok() } - /// Create a representation of IPv6 address and perform Network byte order conversion - /// on the port number. - pub fn ipv6( - family: u16, - port: u16, - flow_info: u32, - addr: [u8; 16usize], - scope_id: u32, - ) -> Addr { - Addr { - ipv6: sockaddr_in6 { - family, - port, - flow_info, - addr, - scope_id, - }, + /// Get port number from the `Addr`. + pub fn port(&self) -> u16 { + unsafe { u16::from_be(self.ipv4.sin_port) } + } +} + +impl From for Addr { + fn from(addr: SocketAddr) -> Addr { + match addr { + SocketAddr::V4(addr) => addr.into(), + SocketAddr::V6(addr) => addr.into(), } } } +impl From for Addr { + fn from(addr: SocketAddrV4) -> Addr { + // SAFETY: a `Addr` of all zeros is valid. + let mut storage = unsafe { mem::zeroed::() }; + let addr: SockAddr = addr.into(); + let addr = addr.as_ptr().cast::(); + storage.ipv4 = unsafe { *addr }; + storage + } +} + +impl From for Addr { + fn from(addr: SocketAddrV6) -> Addr { + // SAFETY: a `Addr` of all zeros is valid. + let mut storage = unsafe { mem::zeroed::() }; + let addr: SockAddr = addr.into(); + let addr = addr.as_ptr().cast::(); + storage.ipv6 = unsafe { *addr }; + storage + } +} + #[cfg(target_os = "windows")] mod status { pub const QUIC_STATUS_SUCCESS: u32 = 0x0; @@ -1666,6 +1676,40 @@ impl Connection { } Ok(()) } + + pub fn get_local_addr(&self) -> Result { + let mut addr_buffer: [u8; mem::size_of::()] = [0; mem::size_of::()]; + let addr_size_mut = mem::size_of::(); + let status = unsafe { + ((*self.table).get_param)( + self.handle, + PARAM_CONN_LOCAL_ADDRESS, + (&addr_size_mut) as *const usize as *const u32 as *mut u32, + addr_buffer.as_mut_ptr() as *const c_void, + ) + }; + if Status::failed(status) { + return Err(status); + } + Ok(unsafe { *(addr_buffer.as_ptr() as *const c_void as *const Addr) }) + } + + pub fn get_remote_addr(&self) -> Result { + let mut addr_buffer: [u8; mem::size_of::()] = [0; mem::size_of::()]; + let addr_size_mut = mem::size_of::(); + let status = unsafe { + ((*self.table).get_param)( + self.handle, + PARAM_CONN_REMOTE_ADDRESS, + (&addr_size_mut) as *const usize as *const u32 as *mut u32, + addr_buffer.as_mut_ptr() as *const c_void, + ) + }; + if Status::failed(status) { + return Err(status); + } + Ok(unsafe { *(addr_buffer.as_ptr() as *const c_void as *const Addr) }) + } } impl Drop for Connection { @@ -1820,7 +1864,11 @@ extern "C" fn test_conn_callback( ) -> u32 { let connection = unsafe { &*(context as *const Connection) }; match event.event_type { - CONNECTION_EVENT_CONNECTED => println!("Connected"), + CONNECTION_EVENT_CONNECTED => { + let local_addr = connection.get_local_addr().unwrap().as_socket().unwrap(); + let remote_addr = connection.get_remote_addr().unwrap().as_socket().unwrap(); + println!("Connected({}, {})", local_addr, remote_addr); + } CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT => { println!("Transport shutdown 0x{:x}", unsafe { event.payload.shutdown_initiated_by_transport.status From 99348663ec97b696f8e5a1449ce7d5a80a055e09 Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Fri, 20 Dec 2024 04:00:40 +0530 Subject: [PATCH 03/15] added unique pointer for connection (#4718) --- src/test/lib/DataTest.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/lib/DataTest.cpp b/src/test/lib/DataTest.cpp index 52e4206919..2e4d91bdc3 100644 --- a/src/test/lib/DataTest.cpp +++ b/src/test/lib/DataTest.cpp @@ -3627,9 +3627,9 @@ void QuicTestConnectionPriority() const uint8_t NumConnections = 8; { - MsQuicConnection *Connections[NumConnections] = {0}; + UniquePtr Connections[NumConnections]; for (uint8_t i = 0; i < NumConnections; ++i) { - Connections[i] = new(std::nothrow) MsQuicConnection(Registration); + Connections[i].reset(new(std::nothrow) MsQuicConnection(Registration)); TEST_QUIC_SUCCEEDED(Connections[i]->GetInitStatus()); TEST_QUIC_SUCCEEDED(Connections[i]->Start(ClientConfiguration, ServerLocalAddr.GetFamily(), QUIC_TEST_LOOPBACK_FOR_AF(ServerLocalAddr.GetFamily()), ServerLocalAddr.GetPort())); TEST_TRUE(Connections[i]->HandshakeCompleteEvent.WaitTimeout(TestWaitTimeout)); @@ -3824,10 +3824,6 @@ void QuicTestConnectionPriority() TEST_TRUE(memcmp(Context.StartOrder, ExpectedStartOrder, sizeof(ExpectedStartOrder)) == 0); TEST_TRUE(memcmp(Context.SendOrder, ExpectedSendOrder, sizeof(ExpectedSendOrder)) == 0); } - - for (uint8_t i = 0; i < NumConnections; ++i) { - delete Connections[i]; - } } } From 0e74c3a470bd2c79b80b540fed17cf08e85a7815 Mon Sep 17 00:00:00 2001 From: Vishwanath Mahajanshetty Date: Sun, 22 Dec 2024 20:39:22 +0530 Subject: [PATCH 04/15] Changes to trigger wan perf test run manually (#4719) * Changes to trigger wan perf test run manually * Changes to trigger wan perf test run manually * Update .github/workflows/wan-perf.yml Co-authored-by: Nick Banks * Changes to trigger wan perf test run manually --------- Co-authored-by: Nick Banks --- .github/workflows/wan-perf.yml | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/wan-perf.yml b/.github/workflows/wan-perf.yml index 01872cfe64..d51e3b602b 100644 --- a/.github/workflows/wan-perf.yml +++ b/.github/workflows/wan-perf.yml @@ -1,24 +1,24 @@ name: WAN Perf on: - push: - branches: - - main - paths: - - .github/workflows/wan-perf.yml - - src/core/* - - src/platform/* - - src/perf/* - pull_request: - branches: - - main - paths: - - .github/workflows/wan-perf.yml - - src/core/* - - src/platform/* - - src/perf/* - - submodules/openssl/* - + workflow_dispatch: +# push: +# branches: +# - main +# paths: +# - .github/workflows/wan-perf.yml +# - src/core/* +# - src/platform/* +# - src/perf/* +# pull_request: +# branches: +# - main +# paths: +# - .github/workflows/wan-perf.yml +# - src/core/* +# - src/platform/* +# - src/perf/* +# - submodules/openssl/* concurrency: # Cancel any workflow currently in progress for the same PR. # Allow running concurrently with any other commits. @@ -92,11 +92,11 @@ jobs: name: bin path: artifacts/bin - name: Run WAN Perf (QUIC only) - if: ${{ github.event_name == 'pull_request' }} + if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }} shell: pwsh run: scripts/emulated-performance.ps1 -Debug -Protocol QUIC -LogProfile Performance.Light -NoDateLogDir -NumIterations ${{ env.iterations }} -DurationMs ${{ env.duration }} -Pacing ${{ env.pacing }} -BottleneckMbps ${{ matrix.rate }} -RttMs ${{ matrix.rtt }} -BottleneckQueueRatio ${{ matrix.queueRatio }} -RandomLossDenominator ${{ env.loss }} -RandomReorderDenominator ${{ env.reorder }} -ReorderDelayDeltaMs ${{ env.delay }} -BaseRandomSeed ${{ env.seed }} -CongestionControl ${{ env.congestionControl }} - name: Run WAN Perf (QUIC + TCP) - if: ${{ github.event_name != 'pull_request' }} + if: ${{ github.event_name != 'pull_request' && github.event_name != 'workflow_dispatch' }} shell: pwsh run: scripts/emulated-performance.ps1 -Debug -Protocol ('QUIC','TCPTLS') -LogProfile Performance.Light -NoDateLogDir -NumIterations ${{ env.iterations }} -DurationMs ${{ env.duration }} -Pacing ${{ env.pacing }} -BottleneckMbps ${{ matrix.rate }} -RttMs ${{ matrix.rtt }} -BottleneckQueueRatio ${{ matrix.queueRatio }} -RandomLossDenominator ${{ env.loss }} -RandomReorderDenominator ${{ env.reorder }} -ReorderDelayDeltaMs ${{ env.delay }} -BaseRandomSeed ${{ env.seed }} -CongestionControl ${{ env.congestionControl }} - name: Upload Results From 761dc0bf376de57134d42a6310de8c065053a145 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 22 Dec 2024 16:42:58 -0600 Subject: [PATCH 05/15] Bump submodules/googletest from `79219e2` to `f3c355f` (#4720) Bumps [submodules/googletest](https://github.com/google/googletest) from `79219e2` to `f3c355f`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/79219e26e0e36b415a5804b6b017ad6c6cd99ad8...f3c355f9dd382bc2c323be2713e351a578b68c61) --- updated-dependencies: - dependency-name: submodules/googletest dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- submodules/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/googletest b/submodules/googletest index 79219e26e0..f3c355f9dd 160000 --- a/submodules/googletest +++ b/submodules/googletest @@ -1 +1 @@ -Subproject commit 79219e26e0e36b415a5804b6b017ad6c6cd99ad8 +Subproject commit f3c355f9dd382bc2c323be2713e351a578b68c61 From 2178cc43176448b1ccf4488cef5340bac71b86b9 Mon Sep 17 00:00:00 2001 From: talregev Date: Tue, 24 Dec 2024 16:54:34 +0100 Subject: [PATCH 06/15] Change ci that can run from other repos (#4703) --- .github/workflows/build-darwin-framework.yml | 1 + .github/workflows/build-reuse-darwin-framework.yml | 10 +++++++--- .github/workflows/build-reuse-unix.yml | 6 +++++- .github/workflows/build-reuse-win.yml | 6 +++++- .github/workflows/build-reuse-winkernel.yml | 6 +++++- .github/workflows/build.yml | 5 +++++ 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-darwin-framework.yml b/.github/workflows/build-darwin-framework.yml index 186ed64055..be92ab1f68 100644 --- a/.github/workflows/build-darwin-framework.yml +++ b/.github/workflows/build-darwin-framework.yml @@ -25,3 +25,4 @@ jobs: uses: ./.github/workflows/build-reuse-darwin-framework.yml with: config: 'Release' + repo: ${{ github.repository }} diff --git a/.github/workflows/build-reuse-darwin-framework.yml b/.github/workflows/build-reuse-darwin-framework.yml index 9aa7baba8e..c883a12fec 100644 --- a/.github/workflows/build-reuse-darwin-framework.yml +++ b/.github/workflows/build-reuse-darwin-framework.yml @@ -7,6 +7,10 @@ on: required: false default: '' type: string + repo: + required: false + default: microsoft/msquic + type: string config: required: false default: 'Release' @@ -55,7 +59,7 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with: - repository: microsoft/msquic + repository: ${{ inputs.repo}} ref: ${{ inputs.ref }} - name: Download Build Artifacts (x64) uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 @@ -92,7 +96,7 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with: - repository: microsoft/msquic + repository: ${{ inputs.repo}} ref: ${{ inputs.ref }} - name: Download Build Artifacts (x64) uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 @@ -116,7 +120,7 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with: - repository: microsoft/msquic + repository: ${{ inputs.repo}} ref: ${{ inputs.ref }} - name: Download Build Artifacts (iOS x64) uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 diff --git a/.github/workflows/build-reuse-unix.yml b/.github/workflows/build-reuse-unix.yml index 6bfadc0e56..518ba82bf3 100644 --- a/.github/workflows/build-reuse-unix.yml +++ b/.github/workflows/build-reuse-unix.yml @@ -9,6 +9,10 @@ on: required: false default: '' type: string + repo: + required: false + default: microsoft/msquic + type: string config: required: false default: 'Release' @@ -91,7 +95,7 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with: - repository: microsoft/msquic + repository: ${{ inputs.repo}} ref: ${{ inputs.ref }} - name: Set ownership if: inputs.plat == 'linux' diff --git a/.github/workflows/build-reuse-win.yml b/.github/workflows/build-reuse-win.yml index e13e5ef9f2..41f614cbbd 100644 --- a/.github/workflows/build-reuse-win.yml +++ b/.github/workflows/build-reuse-win.yml @@ -9,6 +9,10 @@ on: required: false default: '' type: string + repo: + required: false + default: microsoft/msquic + type: string config: required: false default: 'Release' @@ -71,7 +75,7 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with: - repository: microsoft/msquic + repository: ${{ inputs.repo}} ref: ${{ inputs.ref }} - name: Install Perl uses: shogo82148/actions-setup-perl@98dfedee230bcf1ee68d5b021931fc8d63f2016e diff --git a/.github/workflows/build-reuse-winkernel.yml b/.github/workflows/build-reuse-winkernel.yml index 0e55cba4ef..b6212bc4a2 100644 --- a/.github/workflows/build-reuse-winkernel.yml +++ b/.github/workflows/build-reuse-winkernel.yml @@ -9,6 +9,10 @@ on: required: false default: '' type: string + repo: + required: false + default: microsoft/msquic + type: string config: required: false default: 'Release' @@ -60,7 +64,7 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 with: - repository: microsoft/msquic + repository: ${{ inputs.repo}} ref: ${{ inputs.ref }} - name: Prepare Machine shell: pwsh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aead751834..8d1ba58ae2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,6 +53,7 @@ jobs: arch: ${{ matrix.arch }} tls: ${{ matrix.tls }} static: ${{ matrix.static }} + repo: ${{ github.repository }} build-windows-kernel: name: WinKernel @@ -72,6 +73,7 @@ jobs: os: ${{ matrix.os }} arch: ${{ matrix.arch }} tls: ${{ matrix.tls }} + repo: ${{ github.repository }} build-ubuntu-cross-compile: name: UbuntuArm @@ -93,6 +95,7 @@ jobs: arch: ${{ matrix.arch }} tls: ${{ matrix.tls }} static: ${{ matrix.static }} + repo: ${{ github.repository }} build-ubuntu: name: Ubuntu @@ -177,6 +180,7 @@ jobs: clang: ${{ matrix.clang }} codecheck: ${{ matrix.codecheck }} xdp: ${{ matrix.xdp }} + repo: ${{ github.repository }} build-darwin: name: MacOs @@ -198,6 +202,7 @@ jobs: arch: ${{ matrix.arch }} tls: ${{ matrix.tls }} static: ${{ matrix.static }} + repo: ${{ github.repository }} build-nuget: name: Build Nuget Package From 10f248775a5e32f1c0935ab794c0fb4c3e2f9c18 Mon Sep 17 00:00:00 2001 From: talregev Date: Fri, 27 Dec 2024 20:52:43 +0200 Subject: [PATCH 07/15] Add repo var to all other ci job (#4721) Signed-off-by: Tal Regev --- .github/workflows/build-reuse-darwin-framework.yml | 1 + .github/workflows/code-coverage.yml | 1 + .github/workflows/dotnet-test.yml | 3 +++ .github/workflows/package-reuse-linux.yml | 1 + .github/workflows/stress.yml | 2 ++ .github/workflows/test.yml | 3 +++ 6 files changed, 11 insertions(+) diff --git a/.github/workflows/build-reuse-darwin-framework.yml b/.github/workflows/build-reuse-darwin-framework.yml index c883a12fec..0da51e5c93 100644 --- a/.github/workflows/build-reuse-darwin-framework.yml +++ b/.github/workflows/build-reuse-darwin-framework.yml @@ -50,6 +50,7 @@ jobs: arch: ${{ matrix.arch }} tls: ${{ inputs.tls }} static: ${{ inputs.static }} + repo: ${{ inputs.repo }} build-darwin-universal: name: Build Universal Binaries diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 8e9fbe0844..a5f8d18e5a 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -37,6 +37,7 @@ jobs: tls: ${{ matrix.vec.tls }} sanitize: ${{ matrix.vec.sanitize }} build: ${{ matrix.vec.build }} + repo: ${{ github.repository }} bvt-winlatest: name: BVT WinPrerelease diff --git a/.github/workflows/dotnet-test.yml b/.github/workflows/dotnet-test.yml index ccfe8f3829..0737d43e34 100644 --- a/.github/workflows/dotnet-test.yml +++ b/.github/workflows/dotnet-test.yml @@ -25,6 +25,7 @@ jobs: uses: ./.github/workflows/build-reuse-darwin-framework.yml with: config: 'Debug' + repo: ${{ github.repository }} build-linux: name: Ubuntu @@ -45,6 +46,7 @@ jobs: arch: ${{ matrix.vec.arch }} tls: ${{ matrix.vec.tls }} xdp: ${{ matrix.vec.xdp }} + repo: ${{ github.repository }} build-windows: name: Windows @@ -63,6 +65,7 @@ jobs: os: ${{ matrix.vec.os }} arch: ${{ matrix.vec.arch }} tls: ${{ matrix.vec.tls }} + repo: ${{ github.repository }} dotnet-test: name: DotNet Test diff --git a/.github/workflows/package-reuse-linux.yml b/.github/workflows/package-reuse-linux.yml index 354a940a1f..893f621824 100644 --- a/.github/workflows/package-reuse-linux.yml +++ b/.github/workflows/package-reuse-linux.yml @@ -75,6 +75,7 @@ jobs: clang: ${{ inputs.clang }} build: ${{ inputs.build }} xdp: ${{ inputs.xdp }} + repo: ${{ github.repository }} package: name: Package diff --git a/.github/workflows/stress.yml b/.github/workflows/stress.yml index 8e1d22f828..3e850df271 100644 --- a/.github/workflows/stress.yml +++ b/.github/workflows/stress.yml @@ -40,6 +40,7 @@ jobs: tls: ${{ matrix.vec.tls }} sanitize: ${{ matrix.vec.sanitize }} build: ${{ matrix.vec.build }} + repo: ${{ github.repository }} build-unix: name: Build Unix @@ -66,6 +67,7 @@ jobs: sanitize: ${{ matrix.vec.sanitize }} build: ${{ matrix.vec.build }} xdp: ${{ matrix.vec.xdp }} + repo: ${{ github.repository }} stress: name: Stress diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8f363ddab1..df74a07281 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,6 +43,7 @@ jobs: tls: ${{ matrix.vec.tls }} build: ${{ matrix.vec.build }} ref: ${{ inputs.ref || '' }} + repo: ${{ github.repository }} build-windows: name: Build WinUser @@ -66,6 +67,7 @@ jobs: sanitize: ${{ matrix.vec.sanitize }} build: ${{ matrix.vec.build }} ref: ${{ inputs.ref || '' }} + repo: ${{ github.repository }} build-unix: name: Build Unix @@ -94,6 +96,7 @@ jobs: build: ${{ matrix.vec.build }} xdp: ${{ matrix.vec.xdp }} ref: ${{ inputs.ref || '' }} + repo: ${{ github.repository }} bvt: name: BVT From 3ad4ba7146b674251fedc70585254f7baabb91b2 Mon Sep 17 00:00:00 2001 From: Masahiro Kozuka Date: Tue, 31 Dec 2024 22:57:20 +0900 Subject: [PATCH 08/15] Use global API table instead of each handle's having table ptr (#4708) --- Cargo.toml | 1 + src/lib.rs | 199 ++++++++++++++++++++++++++++------------------------- 2 files changed, 108 insertions(+), 92 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e940c6f816..031eea7812 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,4 +56,5 @@ bitfield = "0.17.0" libc = "0.2.0" c-types = "4.0.0" serde = { version = "1.0.117", features = ["derive"] } +ctor = "0.2.9" socket2 = "0.5.8" diff --git a/src/lib.rs b/src/lib.rs index f695ca8387..34a1b1cc76 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,11 +14,13 @@ use socket2::SockAddr; use std::convert::TryInto; use std::fmt; use std::io; +use std::marker::PhantomData; use std::mem; use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use std::option::Option; use std::ptr; use std::result::Result; +use std::sync::Once; #[macro_use] extern crate bitfield; @@ -1245,42 +1247,39 @@ extern "C" { // The following starts the "nice" Rust API wrapper on the C interop layer. // -/// Top level entry point for the MsQuic API. -/// -/// Developper must ensure a struct containing MsQuic members such as `Connection` -/// or `Stream` declares `API` last so that the API is dropped last when the containing -/// sruct goes out of scope. +// +// APITABLE will be initialized via MsQuicOpenVersion() when we first initialize Api or Registration. +// +static mut APITABLE: *const ApiTable = ptr::null(); +static START_MSQUIC: Once = Once::new(); + +/// Entry point for some global MsQuic APIs. pub struct Api { - table: *const ApiTable, + marker: PhantomData<()>, } /// The execution context for processing connections on the application's behalf. pub struct Registration { - table: *const ApiTable, handle: Handle, } /// Specifies how to configure a connection. pub struct Configuration { - table: *const ApiTable, handle: Handle, } /// A single QUIC connection. pub struct Connection { - table: *const ApiTable, handle: Handle, } /// A single server listener pub struct Listener { - table: *const ApiTable, handle: Handle, } /// A single QUIC stream on a parent connection. pub struct Stream { - table: *const ApiTable, handle: Handle, } @@ -1369,29 +1368,43 @@ impl CredentialConfig { } } +impl Default for Api { + fn default() -> Self { + Self::new() + } +} + impl Api { - pub fn new() -> Result { - let new_table: *const ApiTable = ptr::null(); - let status = unsafe { MsQuicOpenVersion(2, &new_table) }; - if Status::failed(status) { - return Err(status); + pub fn new() -> Self { + // We initialize APITABLE at only once. + unsafe { + START_MSQUIC.call_once(|| { + let table: *const ApiTable = ptr::null(); + let status = MsQuicOpenVersion(2, &table); + if Status::failed(status) { + panic!("Failed to open MsQuic: {}", status); + } + APITABLE = table; + }); + } + Self { + marker: PhantomData, } - Ok(Api { table: new_table }) } pub fn close_listener(&self, listener: Handle) { unsafe { - ((*self.table).listener_close)(listener); + ((*APITABLE).listener_close)(listener); } } pub fn close_connection(&self, connection: Handle) { unsafe { - ((*self.table).connection_close)(connection); + ((*APITABLE).connection_close)(connection); } } pub fn close_stream(&self, stream: Handle) { unsafe { - ((*self.table).stream_close)(stream); + ((*APITABLE).stream_close)(stream); } } @@ -1401,7 +1414,7 @@ impl Api { }; let perf_length = std::mem::size_of::<[i64; PERF_COUNTER_MAX as usize]>() as u32; unsafe { - ((*self.table).get_param)( + ((*APITABLE).get_param)( std::ptr::null(), PARAM_GLOBAL_PERF_COUNTERS, (&perf_length) as *const u32 as *mut u32, @@ -1417,37 +1430,51 @@ impl Api { handler: *const c_void, context: *const c_void, ) { - unsafe { ((*self.table).set_callback_handler)(handle, handler, context) } + unsafe { ((*APITABLE).set_callback_handler)(handle, handler, context) } } } -impl Drop for Api { - fn drop(&mut self) { - unsafe { MsQuicClose(self.table) }; +#[ctor::dtor] +fn close_msquic() { + unsafe { + if !APITABLE.is_null() { + MsQuicClose(APITABLE); + APITABLE = ptr::null(); + } } } impl Registration { - pub fn new(api: &Api, config: *const RegistrationConfig) -> Result { + pub fn new(config: *const RegistrationConfig) -> Result { + // We initialize APITABLE at only once. + unsafe { + START_MSQUIC.call_once(|| { + let table: *const ApiTable = ptr::null(); + let status = MsQuicOpenVersion(2, &table); + if Status::failed(status) { + panic!("Failed to open MsQuic: {}", status); + } + APITABLE = table; + }); + } let new_registration: Handle = ptr::null(); - let status = unsafe { ((*api.table).registration_open)(config, &new_registration) }; + let status = unsafe { ((*APITABLE).registration_open)(config, &new_registration) }; if Status::failed(status) { return Err(status); } Ok(Registration { - table: api.table, handle: new_registration, }) } pub fn shutdown(&self) { - unsafe { ((*self.table).registration_shutdown)(self.handle) } + unsafe { ((*APITABLE).registration_shutdown)(self.handle) } } } impl Drop for Registration { fn drop(&mut self) { - unsafe { ((*self.table).registration_close)(self.handle) }; + unsafe { ((*APITABLE).registration_close)(self.handle) }; } } @@ -1464,7 +1491,7 @@ impl Configuration { settings_size = ::std::mem::size_of::() as u32; } let status = unsafe { - ((*registration.table).configuration_open)( + ((*APITABLE).configuration_open)( registration.handle, alpn.as_ptr(), alpn.len() as u32, @@ -1478,14 +1505,13 @@ impl Configuration { return Err(status); } Ok(Configuration { - table: registration.table, handle: new_configuration, }) } pub fn load_credential(&self, cred_config: &CredentialConfig) -> Result<(), u32> { let status = - unsafe { ((*self.table).configuration_load_credential)(self.handle, cred_config) }; + unsafe { ((*APITABLE).configuration_load_credential)(self.handle, cred_config) }; if Status::failed(status) { return Err(status); } @@ -1495,23 +1521,25 @@ impl Configuration { impl Drop for Configuration { fn drop(&mut self) { - unsafe { ((*self.table).configuration_close)(self.handle) }; + unsafe { ((*APITABLE).configuration_close)(self.handle) }; + } +} + +impl Default for Connection { + fn default() -> Self { + Self::new() } } impl Connection { - pub fn new(registration: &Registration) -> Connection { + pub fn new() -> Connection { Connection { - table: registration.table, handle: ptr::null(), } } - pub fn from_parts(handle: Handle, api: &Api) -> Connection { - Connection { - table: api.table, - handle, - } + pub fn from_parts(handle: Handle) -> Connection { + Connection { handle } } pub fn open( @@ -1521,7 +1549,7 @@ impl Connection { context: *const c_void, ) -> Result<(), u32> { let status = unsafe { - ((*self.table).connection_open)(registration.handle, handler, context, &self.handle) + ((*APITABLE).connection_open)(registration.handle, handler, context, &self.handle) }; if Status::failed(status) { return Err(status); @@ -1537,7 +1565,7 @@ impl Connection { ) -> Result<(), u32> { let server_name_safe = std::ffi::CString::new(server_name).unwrap(); let status = unsafe { - ((*self.table).connection_start)( + ((*APITABLE).connection_start)( self.handle, configuration.handle, 0, @@ -1553,23 +1581,23 @@ impl Connection { pub fn close(&self) { unsafe { - ((*self.table).connection_close)(self.handle); + ((*APITABLE).connection_close)(self.handle); } } pub fn shutdown(&self, flags: ConnectionShutdownFlags, error_code: u62) { unsafe { - ((*self.table).connection_shutdown)(self.handle, flags, error_code); + ((*APITABLE).connection_shutdown)(self.handle, flags, error_code); } } pub fn set_param(&self, param: u32, buffer_length: u32, buffer: *const c_void) -> u32 { - unsafe { ((*self.table).set_param)(self.handle, param, buffer_length, buffer) } + unsafe { ((*APITABLE).set_param)(self.handle, param, buffer_length, buffer) } } pub fn stream_close(&self, stream: Handle) { unsafe { - ((*self.table).stream_close)(stream); + ((*APITABLE).stream_close)(stream); } } @@ -1578,7 +1606,7 @@ impl Connection { [0; std::mem::size_of::()]; let stat_size_mut = std::mem::size_of::(); unsafe { - ((*self.table).get_param)( + ((*APITABLE).get_param)( self.handle, PARAM_CONN_STATISTICS, (&stat_size_mut) as *const usize as *const u32 as *mut u32, @@ -1594,7 +1622,7 @@ impl Connection { [0; std::mem::size_of::()]; let stat_size_mut = std::mem::size_of::(); unsafe { - ((*self.table).get_param)( + ((*APITABLE).get_param)( self.handle, PARAM_CONN_STATISTICS_V2, (&stat_size_mut) as *const usize as *const u32 as *mut u32, @@ -1607,7 +1635,7 @@ impl Connection { pub fn set_configuration(&self, configuration: &Configuration) -> Result<(), u32> { let status = unsafe { - ((*self.table).connection_set_configuration)(self.handle, configuration.handle) + ((*APITABLE).connection_set_configuration)(self.handle, configuration.handle) }; if Status::failed(status) { return Err(status); @@ -1617,7 +1645,7 @@ impl Connection { pub fn set_callback_handler(&self, handler: ConnectionEventHandler, context: *const c_void) { unsafe { - ((*self.table).set_callback_handler)(self.handle, handler as *const c_void, context) + ((*APITABLE).set_callback_handler)(self.handle, handler as *const c_void, context) }; } @@ -1628,7 +1656,7 @@ impl Connection { context: *const c_void, ) { unsafe { - ((*self.table).set_callback_handler)(stream_handle, handler as *const c_void, context) + ((*APITABLE).set_callback_handler)(stream_handle, handler as *const c_void, context) }; } @@ -1640,7 +1668,7 @@ impl Connection { client_send_context: *const c_void, ) -> Result<(), u32> { let status = unsafe { - ((*self.table).datagram_send)( + ((*APITABLE).datagram_send)( self.handle, buffer, buffer_count, @@ -1656,7 +1684,7 @@ impl Connection { pub fn resumption_ticket_validation_complete(&self, result: BOOLEAN) -> Result<(), u32> { let status = - unsafe { ((*self.table).resumption_ticket_validation_complete)(self.handle, result) }; + unsafe { ((*APITABLE).resumption_ticket_validation_complete)(self.handle, result) }; if Status::failed(status) { return Err(status); } @@ -1669,7 +1697,7 @@ impl Connection { tls_alert: TlsAlertCode, ) -> Result<(), u32> { let status = unsafe { - ((*self.table).certificate_validation_complete)(self.handle, result, tls_alert) + ((*APITABLE).certificate_validation_complete)(self.handle, result, tls_alert) }; if Status::failed(status) { return Err(status); @@ -1681,7 +1709,7 @@ impl Connection { let mut addr_buffer: [u8; mem::size_of::()] = [0; mem::size_of::()]; let addr_size_mut = mem::size_of::(); let status = unsafe { - ((*self.table).get_param)( + ((*APITABLE).get_param)( self.handle, PARAM_CONN_LOCAL_ADDRESS, (&addr_size_mut) as *const usize as *const u32 as *mut u32, @@ -1698,7 +1726,7 @@ impl Connection { let mut addr_buffer: [u8; mem::size_of::()] = [0; mem::size_of::()]; let addr_size_mut = mem::size_of::(); let status = unsafe { - ((*self.table).get_param)( + ((*APITABLE).get_param)( self.handle, PARAM_CONN_REMOTE_ADDRESS, (&addr_size_mut) as *const usize as *const u32 as *mut u32, @@ -1714,7 +1742,7 @@ impl Connection { impl Drop for Connection { fn drop(&mut self) { - unsafe { ((*self.table).connection_close)(self.handle) }; + unsafe { ((*APITABLE).connection_close)(self.handle) }; } } @@ -1726,26 +1754,20 @@ impl Listener { ) -> Result { let new_listener: Handle = ptr::null(); let status = unsafe { - ((*registration.table).listener_open)( - registration.handle, - handler, - context, - &new_listener, - ) + ((*APITABLE).listener_open)(registration.handle, handler, context, &new_listener) }; if Status::failed(status) { return Err(status); } Ok(Listener { - table: registration.table, handle: new_listener, }) } pub fn start(&self, alpn: &[Buffer], local_address: &Addr) -> Result<(), u32> { let status = unsafe { - ((*self.table).listener_start)( + ((*APITABLE).listener_start)( self.handle, alpn.as_ptr(), alpn.len() as u32, @@ -1760,31 +1782,32 @@ impl Listener { pub fn close(&self) { unsafe { - ((*self.table).listener_close)(self.handle); + ((*APITABLE).listener_close)(self.handle); } } } impl Drop for Listener { fn drop(&mut self) { - unsafe { ((*self.table).listener_close)(self.handle) }; + unsafe { ((*APITABLE).listener_close)(self.handle) }; + } +} + +impl Default for Stream { + fn default() -> Self { + Self::new() } } impl Stream { - pub fn new(context: *const c_void) -> Stream { - let api = unsafe { &*(context as *const Api) }; + pub fn new() -> Stream { Stream { - table: api.table, handle: ptr::null(), } } - pub fn from_parts(handle: Handle, api: &Api) -> Stream { - Stream { - table: api.table, - handle, - } + pub fn from_parts(handle: Handle) -> Stream { + Stream { handle } } pub fn open( @@ -1795,7 +1818,7 @@ impl Stream { context: *const c_void, ) -> Result<(), u32> { let status = unsafe { - ((*self.table).stream_open)(connection.handle, flags, handler, context, &self.handle) + ((*APITABLE).stream_open)(connection.handle, flags, handler, context, &self.handle) }; if Status::failed(status) { return Err(status); @@ -1804,7 +1827,7 @@ impl Stream { } pub fn start(&self, flags: StreamStartFlags) -> Result<(), u32> { - let status = unsafe { ((*self.table).stream_start)(self.handle, flags) }; + let status = unsafe { ((*APITABLE).stream_start)(self.handle, flags) }; if Status::failed(status) { return Err(status); } @@ -1813,7 +1836,7 @@ impl Stream { pub fn close(&self) { unsafe { - ((*self.table).stream_close)(self.handle); + ((*APITABLE).stream_close)(self.handle); } } @@ -1825,7 +1848,7 @@ impl Stream { client_send_context: *const c_void, ) -> Result<(), u32> { let status = unsafe { - ((*self.table).stream_send)( + ((*APITABLE).stream_send)( self.handle, buffer, buffer_count, @@ -1841,14 +1864,14 @@ impl Stream { pub fn set_callback_handler(&self, handler: StreamEventHandler, context: *const c_void) { unsafe { - ((*self.table).set_callback_handler)(self.handle, handler as *const c_void, context) + ((*APITABLE).set_callback_handler)(self.handle, handler as *const c_void, context) }; } } impl Drop for Stream { fn drop(&mut self) { - unsafe { ((*self.table).stream_close)(self.handle) }; + unsafe { ((*APITABLE).stream_close)(self.handle) }; } } @@ -1923,15 +1946,7 @@ extern "C" fn test_stream_callback( #[test] fn test_module() { - let res = Api::new(); - assert!( - res.is_ok(), - "Failed to open API: 0x{:x}", - res.err().unwrap() - ); - let api = res.unwrap(); - - let res = Registration::new(&api, ptr::null()); + let res = Registration::new(ptr::null()); assert!( res.is_ok(), "Failed to open registration: 0x{:x}", @@ -1962,7 +1977,7 @@ fn test_module() { res.err().unwrap() ); - let connection = Connection::new(®istration); + let connection = Connection::new(); let res = connection.open( ®istration, test_conn_callback, From 114e2cfe3afed114b9efd4a4618309d02aeb20e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Dec 2024 09:00:23 -0500 Subject: [PATCH 09/15] Bump submodules/googletest from `f3c355f` to `7d76a23` (#4722) Bumps [submodules/googletest](https://github.com/google/googletest) from `f3c355f` to `7d76a23`. - [Release notes](https://github.com/google/googletest/releases) - [Commits](https://github.com/google/googletest/compare/f3c355f9dd382bc2c323be2713e351a578b68c61...7d76a231b0e29caf86e68d1df858308cd53b2a66) --- updated-dependencies: - dependency-name: submodules/googletest dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- submodules/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/googletest b/submodules/googletest index f3c355f9dd..7d76a231b0 160000 --- a/submodules/googletest +++ b/submodules/googletest @@ -1 +1 @@ -Subproject commit f3c355f9dd382bc2c323be2713e351a578b68c61 +Subproject commit 7d76a231b0e29caf86e68d1df858308cd53b2a66 From e909d8a74b4cf6dd953cdf77667690f7a61b9a4d Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Tue, 31 Dec 2024 15:08:29 +0100 Subject: [PATCH 10/15] Simplify cmake config chainloading (#4727) * CMake: Remove stray config file * Simplify cmake config chainloading --- CMakeLists.txt | 3 --- src/bin/CMakeLists.txt | 2 +- src/bin/msquic-config-unix.cmake.in | 5 ----- src/bin/msquic-config.cmake.in | 3 +-- 4 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 src/bin/msquic-config-unix.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 718247224d..a32b057c25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,9 +67,6 @@ elseif (UNIX) endif() message(STATUS "QUIC Platform: ${CX_PLATFORM}") -set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)") -set(SELF_DIR "$\{SELF_DIR\}") - enable_testing() # Set the default TLS method for each platform. diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt index 6b84d4555c..352536f946 100644 --- a/src/bin/CMakeLists.txt +++ b/src/bin/CMakeLists.txt @@ -269,7 +269,7 @@ else() endif() install(FILES ${PUBLIC_HEADERS} DESTINATION include) -configure_file(msquic-config.cmake.in ${CMAKE_BINARY_DIR}/msquic-config.cmake) +configure_file(msquic-config.cmake.in ${CMAKE_BINARY_DIR}/msquic-config.cmake @ONLY) install(FILES ${CMAKE_BINARY_DIR}/msquic-config.cmake DESTINATION share/msquic) diff --git a/src/bin/msquic-config-unix.cmake.in b/src/bin/msquic-config-unix.cmake.in deleted file mode 100644 index 9292018b12..0000000000 --- a/src/bin/msquic-config-unix.cmake.in +++ /dev/null @@ -1,5 +0,0 @@ -include(CMakeFindDependencyMacro) -@FILENAME_DEP_REPLACE@ - -include(${SELF_DIR}/msquic.cmake) -include(${SELF_DIR}/msquictraceprovider.cmake) diff --git a/src/bin/msquic-config.cmake.in b/src/bin/msquic-config.cmake.in index fba676be99..e61e63feab 100644 --- a/src/bin/msquic-config.cmake.in +++ b/src/bin/msquic-config.cmake.in @@ -1,7 +1,6 @@ include(CMakeFindDependencyMacro) -@FILENAME_DEP_REPLACE@ -include(${SELF_DIR}/msquic.cmake) +include("${CMAKE_CURRENT_LIST_DIR}/msquic.cmake") foreach(_t IN ITEMS msquic msquic_platform) if(TARGET msquic::${_t} AND NOT TARGET ${_t}) From b6ebb83cee48a414d611002dd2b152e7faa89075 Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Tue, 31 Dec 2024 15:25:00 +0100 Subject: [PATCH 11/15] Export msquic include install dir (#4725) --- src/bin/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt index 352536f946..e69cf51ac5 100644 --- a/src/bin/CMakeLists.txt +++ b/src/bin/CMakeLists.txt @@ -11,6 +11,7 @@ endif() if(BUILD_SHARED_LIBS) add_library(msquic SHARED ${SOURCES}) + target_include_directories(msquic PUBLIC $) target_link_libraries(msquic PRIVATE core msquic_platform inc warnings logging base_link main_binary_link_args) set_target_properties(msquic PROPERTIES OUTPUT_NAME ${QUIC_LIBRARY_NAME}) if (NOT WIN32) From 526944cd7c325dd94f55fab7e033822e13213f2a Mon Sep 17 00:00:00 2001 From: Masahiro Kozuka Date: Wed, 1 Jan 2025 22:27:12 +0900 Subject: [PATCH 12/15] Add missing listener, connection, and stream event structures (#4731) --- src/lib.rs | 140 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 122 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 34a1b1cc76..e65464bbdf 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -910,19 +910,35 @@ pub const PARAM_STREAM_PRIORITY: u32 = 0x08000003; pub type ListenerEventType = u32; pub const LISTENER_EVENT_NEW_CONNECTION: ListenerEventType = 0; +pub const LISTENER_EVENT_STOP_COMPLETE: ListenerEventType = 1; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ListenerEventNewConnection { pub info: *const NewConnectionInfo, pub connection: Handle, - pub new_negotiated_alpn: *const u8, +} + +bitfield! { + #[repr(C)] + #[derive(Debug, Clone, Copy)] + pub struct ListenerEventStopCompleteBitfields(u8); + // The fields default to u8 + pub app_close_in_progress, _: 0, 0; + _reserved, _: 7, 1; +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ListenerEventStopComplete { + pub bit_flags: ListenerEventStopCompleteBitfields, } #[repr(C)] #[derive(Copy, Clone)] pub union ListenerEventPayload { pub new_connection: ListenerEventNewConnection, + pub stop_complete: ListenerEventStopComplete, } #[repr(C)] @@ -974,10 +990,33 @@ pub struct ConnectionEventConnectionShutdownByPeer { pub error_code: u62, } +bitfield! { + #[repr(C)] + #[derive(Debug, Clone, Copy)] + pub struct ConnectionEventShutdownCompleteBitfields(BOOLEAN); + // The fields default to BOOLEAN + pub handshake_completed, _: 0, 0; + pub peer_acknowledged_shutdown, _: 1, 1; + pub app_close_in_progress, _: 2, 2; + _reserved, _: 7, 3; +} + #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct ConnectionEventShutdownComplete { - pub _bitfield: BOOLEAN, + pub bit_flags: ConnectionEventShutdownCompleteBitfields, +} + +#[repr(C, packed)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventLocalAddressChanged { + pub address: *const Addr, +} + +#[repr(C, packed)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventPeerAddressChanged { + pub address: *const Addr, } #[repr(C)] @@ -987,6 +1026,33 @@ pub struct ConnectionEventPeerStreamStarted { pub flags: StreamOpenFlags, } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventStreamsAvailable { + pub bidirectional_count: u16, + pub unidirectional_count: u16, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventPeerNeedsStreams { + pub bidirectional: BOOLEAN, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventIdealProcessorChanged { + pub ideal_processor: u16, + pub partition_index: u16, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventDatagramStateChanged { + pub send_enabled: BOOLEAN, + pub max_send_length: u16, +} + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ConnectionEventDatagramReceived { @@ -1001,6 +1067,13 @@ pub struct ConnectionEventDatagramSendStateChanged { pub state: DatagramSendState, } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventResumed { + pub resumption_state_length: u16, + pub resumption_state: *const u8, +} + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ConnectionEventResumptionTicketReceived { @@ -1008,6 +1081,15 @@ pub struct ConnectionEventResumptionTicketReceived { pub resumption_ticket: *const u8, } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ConnectionEventPeerCertificateReceived { + pub certificate: *const Certificate, + pub deferred_error_flags: u32, + pub deferred_status: u32, + pub chain: *const CertificateChain, +} + #[repr(C)] #[derive(Copy, Clone)] pub union ConnectionEventPayload { @@ -1015,17 +1097,18 @@ pub union ConnectionEventPayload { pub shutdown_initiated_by_transport: ConnectionEventConnectionShutdownByTransport, pub shutdown_initiated_by_peer: ConnectionEventConnectionShutdownByPeer, pub shutdown_complete: ConnectionEventShutdownComplete, - //pub local_address_changed: ConnectionEventLocalAddressChanged, - //pub peer_address_changed: ConnectionEventPeerAddressChanged, + pub local_address_changed: ConnectionEventLocalAddressChanged, + pub peer_address_changed: ConnectionEventPeerAddressChanged, pub peer_stream_started: ConnectionEventPeerStreamStarted, - //pub streams_available: ConnectionEventStreamsAvailable, - //pub ideal_processor_changed: ConnectionEventIdealProcessorChanged, - //pub datagram_state_changed: ConnectionEventDatagramStateChanged, + pub streams_available: ConnectionEventStreamsAvailable, + pub peer_needs_streams: ConnectionEventPeerNeedsStreams, + pub ideal_processor_changed: ConnectionEventIdealProcessorChanged, + pub datagram_state_changed: ConnectionEventDatagramStateChanged, pub datagram_received: ConnectionEventDatagramReceived, pub datagram_send_state_changed: ConnectionEventDatagramSendStateChanged, - //pub resumed: ConnectionEventResumed, + pub resumed: ConnectionEventResumed, pub resumption_ticket_received: ConnectionEventResumptionTicketReceived, - //pub peer_certificated_received: ConnectionEventPeerCertificateReceived, + pub peer_certificated_received: ConnectionEventPeerCertificateReceived, } #[repr(C)] @@ -1049,13 +1132,23 @@ pub const STREAM_EVENT_SEND_SHUTDOWN_COMPLETE: StreamEventType = 6; pub const STREAM_EVENT_SHUTDOWN_COMPLETE: StreamEventType = 7; pub const STREAM_EVENT_IDEAL_SEND_BUFFER_SIZE: StreamEventType = 8; pub const STREAM_EVENT_PEER_ACCEPTED: StreamEventType = 9; +pub const STREAM_EVENT_CANCEL_ON_LOSS: StreamEventType = 10; + +bitfield! { + #[repr(C)] + #[derive(Debug, Clone, Copy)] + pub struct StreamEventStartCompleteBitfields(u8); + // The fields default to u8 + pub peer_accepted, _: 0, 0; + _reserved, _: 7, 1; +} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct StreamEventStartComplete { - pub status: u64, + pub status: u32, pub id: u62, - pub bit_flags: u8, + pub bit_flags: StreamEventStartCompleteBitfields, } #[repr(C)] @@ -1078,13 +1171,13 @@ pub struct StreamEventSendComplete { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct StreamEventPeerSendAborted { - pub error_code: u64, + pub error_code: u62, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct StreamEventPeerReceiveAborted { - pub error_code: u64, + pub error_code: u62, } #[repr(C)] @@ -1096,17 +1189,21 @@ pub struct StreamEventSendShutdownComplete { bitfield! { #[repr(C)] #[derive(Clone, Copy)] - struct StreamEventShutdownCompleteBitfields(u8); + pub struct StreamEventShutdownCompleteBitfields(u8); // The fields default to u8 - app_close_in_progress, _: 1, 0; - _reserved, _: 7, 1; + pub app_close_in_progress, _: 0, 0; + pub conn_shutdown_by_app, _: 1, 1; + pub conn_closed_remotely, _: 2, 2; + _reserved, _: 7, 3; } #[repr(C)] #[derive(Copy, Clone)] pub struct StreamEventShutdownComplete { - connection_shutdown: bool, - flags: StreamEventShutdownCompleteBitfields, + pub connection_shutdown: bool, + pub bit_flags: StreamEventShutdownCompleteBitfields, + pub connection_error_code: u62, + pub connection_close_status: u32, } #[repr(C)] @@ -1115,6 +1212,12 @@ pub struct StreamEventIdealSendBufferSize { pub byte_count: u64, } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct StreamEventCancelOnLoss { + pub error_code: u62, +} + #[repr(C)] #[derive(Copy, Clone)] pub union StreamEventPayload { @@ -1126,6 +1229,7 @@ pub union StreamEventPayload { pub send_shutdown_complete: StreamEventSendShutdownComplete, pub shutdown_complete: StreamEventShutdownComplete, pub ideal_send_buffer_size: StreamEventIdealSendBufferSize, + pub cancel_on_loss: StreamEventCancelOnLoss, } #[repr(C)] From f16a46b02e7798e5d01211995839cf1ee3e71456 Mon Sep 17 00:00:00 2001 From: Nick Banks Date: Wed, 1 Jan 2025 18:15:23 -0600 Subject: [PATCH 13/15] Fix Path Classifiers in CodeQL YML (#4733) --- .CodeQL.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.CodeQL.yml b/.CodeQL.yml index 1455700093..1ccd4b8022 100644 --- a/.CodeQL.yml +++ b/.CodeQL.yml @@ -2,13 +2,14 @@ # https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/codeql/troubleshooting/bugs/generated-library-code # (Access restricted to Microsoft employees only.) -# The following paths are explicitly classified which indicates they should no +# The following paths are explicitly classified which indicates they should not # be analyzed by CodeQL and generate alerts. path_classifiers: docs: - docs generated: + - build - src/cs - src/generated submodules: - - subodules + - submodules From 38469af1328ffe88d8455679d942bbc97eafbc58 Mon Sep 17 00:00:00 2001 From: Masahiro Kozuka Date: Thu, 2 Jan 2025 21:26:11 +0900 Subject: [PATCH 14/15] Add preview API feature (#4730) --- Cargo.toml | 1 + src/lib.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 031eea7812..ad41247b71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ include = [ [features] default = [] static = [] +preview-api = [] [build-dependencies] cmake = "0.1" diff --git a/src/lib.rs b/src/lib.rs index e65464bbdf..beb5cea64b 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -826,6 +826,7 @@ pub struct Settings { pub mtu_operations_per_drain: u8, pub mtu_discovery_missing_probe_count: u8, pub dest_cid_update_idle_timeout_ms: u32, + pub other2_flags: u64, } pub const PARAM_GLOBAL_RETRY_MEMORY_PERCENT: u32 = 0x01000000; @@ -1454,6 +1455,12 @@ impl Settings { self.other_flags |= (value as u8) << 3; self } + #[cfg(feature = "preview-api")] + pub fn set_stream_multi_receive_enabled(&mut self, value: bool) -> &mut Settings { + self.is_set_flags |= 1 << 42; + self.other2_flags |= (value as u64) << 5; + self + } } impl CredentialConfig { @@ -2062,6 +2069,12 @@ fn test_module() { let res = Configuration::new( ®istration, &alpn, + #[cfg(feature = "preview-api")] + Settings::new() + .set_peer_bidi_stream_count(100) + .set_peer_unidi_stream_count(3) + .set_stream_multi_receive_enabled(true), + #[cfg(not(feature = "preview-api"))] Settings::new() .set_peer_bidi_stream_count(100) .set_peer_unidi_stream_count(3), From 453fb178725efb45b11e7274dd8d5dfbc7dce7a1 Mon Sep 17 00:00:00 2001 From: Masahiro Kozuka Date: Thu, 2 Jan 2025 22:10:20 +0900 Subject: [PATCH 15/15] Refactor lib.rs (#4729) * Implement default for Listener and enhance its methods for better functionality * Add shutdown and parameter retrieval methods to Stream; clean up Listener methods * Implement Sync and Send traits for QUIC structures --- src/lib.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index beb5cea64b..9a5e00b1d3 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1367,26 +1367,36 @@ pub struct Api { pub struct Registration { handle: Handle, } +unsafe impl Sync for Registration {} +unsafe impl Send for Registration {} /// Specifies how to configure a connection. pub struct Configuration { handle: Handle, } +unsafe impl Sync for Configuration {} +unsafe impl Send for Configuration {} /// A single QUIC connection. pub struct Connection { handle: Handle, } +unsafe impl Sync for Connection {} +unsafe impl Send for Connection {} /// A single server listener pub struct Listener { handle: Handle, } +unsafe impl Sync for Listener {} +unsafe impl Send for Listener {} /// A single QUIC stream on a parent connection. pub struct Stream { handle: Handle, } +unsafe impl Sync for Stream {} +unsafe impl Send for Stream {} impl From<&str> for Buffer { fn from(data: &str) -> Buffer { @@ -1857,32 +1867,43 @@ impl Drop for Connection { } } +impl Default for Listener { + fn default() -> Self { + Self::new() + } +} + impl Listener { - pub fn new( + pub fn new() -> Listener { + Listener { + handle: ptr::null(), + } + } + + pub fn open( + &self, registration: &Registration, handler: ListenerEventHandler, context: *const c_void, - ) -> Result { - let new_listener: Handle = ptr::null(); + ) -> Result<(), u32> { let status = unsafe { - ((*APITABLE).listener_open)(registration.handle, handler, context, &new_listener) + ((*APITABLE).listener_open)(registration.handle, handler, context, &self.handle) }; if Status::failed(status) { return Err(status); } - - Ok(Listener { - handle: new_listener, - }) + Ok(()) } - pub fn start(&self, alpn: &[Buffer], local_address: &Addr) -> Result<(), u32> { + pub fn start(&self, alpn: &[Buffer], local_address: Option<&Addr>) -> Result<(), u32> { let status = unsafe { ((*APITABLE).listener_start)( self.handle, alpn.as_ptr(), alpn.len() as u32, - local_address, + local_address + .map(|addr| addr as *const _) + .unwrap_or(ptr::null()), ) }; if Status::failed(status) { @@ -1891,6 +1912,29 @@ impl Listener { Ok(()) } + pub fn stop(&self) { + unsafe { + ((*APITABLE).listener_stop)(self.handle); + } + } + + pub fn get_local_addr(&self) -> Result { + let mut addr_buffer: [u8; mem::size_of::()] = [0; mem::size_of::()]; + let addr_size_mut = mem::size_of::(); + let status = unsafe { + ((*APITABLE).get_param)( + self.handle, + PARAM_LISTENER_LOCAL_ADDRESS, + (&addr_size_mut) as *const usize as *const u32 as *mut u32, + addr_buffer.as_mut_ptr() as *const c_void, + ) + }; + if Status::failed(status) { + return Err(status); + } + Ok(unsafe { *(addr_buffer.as_ptr() as *const c_void as *const Addr) }) + } + pub fn close(&self) { unsafe { ((*APITABLE).listener_close)(self.handle); @@ -1945,6 +1989,14 @@ impl Stream { Ok(()) } + pub fn shutdown(&self, flags: StreamShutdownFlags, error_code: u62) -> Result<(), u32> { + let status = unsafe { ((*APITABLE).stream_shutdown)(self.handle, flags, error_code) }; + if Status::failed(status) { + return Err(status); + } + Ok(()) + } + pub fn close(&self) { unsafe { ((*APITABLE).stream_close)(self.handle); @@ -1978,6 +2030,27 @@ impl Stream { ((*APITABLE).set_callback_handler)(self.handle, handler as *const c_void, context) }; } + + pub fn get_param( + &self, + param: u32, + buffer_length: *mut u32, + buffer: *const c_void, + ) -> Result<(), u32> { + let status = unsafe { ((*APITABLE).get_param)(self.handle, param, buffer_length, buffer) }; + if Status::failed(status) { + return Err(status); + } + Ok(()) + } + + pub fn receive_complete(&self, buffer_length: u64) -> Result<(), u32> { + let status = unsafe { ((*APITABLE).stream_receive_complete)(self.handle, buffer_length) }; + if Status::failed(status) { + return Err(status); + } + Ok(()) + } } impl Drop for Stream {