Skip to content

Commit

Permalink
dynamic load of open and close api
Browse files Browse the repository at this point in the history
  • Loading branch information
youyuanwu committed Dec 8, 2024
1 parent 3d7f4e7 commit 346fa36
Show file tree
Hide file tree
Showing 17 changed files with 108 additions and 139 deletions.
49 changes: 1 addition & 48 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,8 @@ set(_msquic_version "v2.4.5")
set(_win_pkg_url "https://github.com/microsoft/msquic/releases/download/${_msquic_version}/msquic_windows_x64_Release_schannel.zip")
set(_linux_pkg_url "https://github.com/microsoft/msquic/releases/download/${_msquic_version}/msquic_linux_x64_Release_openssl.zip")
if(WIN32)
# windows downloads release for winmd generation. And for sys2 import lib link.
set(release_url ${_win_pkg_url})
else()
# linux
set(release_url ${_linux_pkg_url})
find_package(OpenSSL REQUIRED)
# openssl needs version 1.1. ubuntu 20.04 has it, 22.04 is too new.
endif(WIN32)

message(STATUS "fetching msquic_release " ${release_url})
include(FetchContent)
FetchContent_Declare(
Expand All @@ -22,19 +16,6 @@ FetchContent_Declare(
URL ${release_url}
)
FetchContent_MakeAvailable(msquic_release)

# fetch linux pkg as well on windows for binding generation
if(WIN32)
message(STATUS "fetching msquic_linux_release " ${_linux_pkg_url})
FetchContent_Declare(
msquic_linux_release
DOWNLOAD_EXTRACT_TIMESTAMP true
URL ${_linux_pkg_url}
)
FetchContent_MakeAvailable(msquic_linux_release)
endif(WIN32)

if(WIN32)
# generate winmd. defer generation task in .metadata csproj.
find_program (
dotnet_exe
Expand Down Expand Up @@ -72,34 +53,6 @@ add_custom_target(generate_rust
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

else(WIN32)
file(GLOB _msquic_dll
${msquic_release_SOURCE_DIR}/bin/libmsquic.so.*
)
# create a sym link
execute_process(
# for build
COMMAND ln -sf ${_msquic_dll} ${CMAKE_BINARY_DIR}/libmsquic.so # for linking
COMMAND ln -sf ${_msquic_dll} ${CMAKE_BINARY_DIR}/libmsquic.so.2 # for loading at runtime
# for run
COMMAND mkdir -p ${CMAKE_SOURCE_DIR}/target/debug/deps
COMMAND cp ${_msquic_dll} ${CMAKE_SOURCE_DIR}/target/debug/libmsquic.so.2
COMMAND cp ${_msquic_dll} ${CMAKE_SOURCE_DIR}/target/debug/deps/libmsquic.so.2
)
# copy files to output dir
# file(COPY ${_msquic_dll} DESTINATION ${CMAKE_SOURCE_DIR}/target/debug)
endif(WIN32)

# downloading the msquic rust manual bindings.

# message(STATUS "download msquic_bind")
# file(DOWNLOAD
# https://raw.githubusercontent.com/microsoft/msquic/v2.3.5/src/lib.rs
# ${CMAKE_CURRENT_SOURCE_DIR}/crates/libs/c2/src/lib.rs
# TLS_VERIFY ON
# )

if(WIN32)
# generate cert on windows:
find_program(pwsh_exe
NAMES pwsh.exe
Expand Down
31 changes: 22 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,21 @@ Experimental.

Currently can run h3 client and server.

# Build
msquic lib is dynamically loaded and it is not required for building the rust code.

# Test and run
## Posix
Install msquic pkg:
```sh
sudo apt-get install libmsquic
```
Rust code will load the lib dynamically.
## Windows
pwsh 7 packages the msquic.dll. If you install pwsh 7, rust will load it from there.

## Other
You can download msquic from github release [here](https://github.com/microsoft/msquic/releases) and put the lib to locations where app can load it.

# License
This project is licensed under the MIT license.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "msquic-sys"
name = "msquic-rs"
version = "0.1.0"
edition = "2021"

Expand All @@ -11,6 +11,8 @@ edition = "2021"
windows-core = "0.57.0"
windows = { version = "0.57.0", features = [ "Win32_Foundation", "Win32_Networking_WinSock"]}
mssf-pal = "0"
libloading = "0.8"
lazy_static = "1"

[features]
Foundation = []
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,6 @@ pub mod MsQuic {
}
}
}
#[inline]
pub unsafe fn MsQuicClose(quicapi: *const core::ffi::c_void) {
#[link(name = "msquic")]
extern "system" {
pub fn MsQuicClose(quicapi: *const core::ffi::c_void);
}
MsQuicClose(quicapi)
}
#[inline]
pub unsafe fn MsQuicOpenVersion(version: u32, quicapi: *mut *mut core::ffi::c_void) -> i32 {
#[link(name = "msquic")]
extern "system" {
pub fn MsQuicOpenVersion(version: u32, quicapi: *mut *mut core::ffi::c_void) -> i32;
}
MsQuicOpenVersion(version, quicapi)
}
pub const QUIC_ALLOWED_CIPHER_SUITE_AES_128_GCM_SHA256: QUIC_ALLOWED_CIPHER_SUITE_FLAGS =
QUIC_ALLOWED_CIPHER_SUITE_FLAGS(1i32);
pub const QUIC_ALLOWED_CIPHER_SUITE_AES_256_GCM_SHA384: QUIC_ALLOWED_CIPHER_SUITE_FLAGS =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ pub use win_status::*;
mod unix_status;
#[cfg(target_os = "linux")]
pub use unix_status::*;

mod load;
pub use load::{MsQuicClose, MsQuicOpenVersion};
19 changes: 19 additions & 0 deletions crates/libs/msquic-rs/src/load.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! Dynamically load shared lib
//!
//!
use crate::Microsoft::MsQuic::QUIC_API_TABLE;

#[cfg(target_os = "windows")]
const LIB_NAME: &str = "msquic.dll";

#[cfg(target_os = "linux")]
const LIB_NAME: &str = "libmsquic.so.2";

lazy_static::lazy_static! {
static ref LIB: libloading::Library = unsafe { libloading::Library::new(LIB_NAME) }.expect("cannot load msquic shared lib");
pub static ref MsQuicOpenVersion: libloading::Symbol<'static,unsafe extern "C" fn(u32, *mut *mut QUIC_API_TABLE) -> i32>
= unsafe { LIB.get(b"MsQuicOpenVersion") }.expect("cannot load open fn");
pub static ref MsQuicClose: libloading::Symbol<'static, unsafe extern "C" fn(*const QUIC_API_TABLE)>
= unsafe { LIB.get(b"MsQuicClose") }.expect("cannot load close fn");
}
File renamed without changes.
File renamed without changes.
29 changes: 0 additions & 29 deletions crates/libs/msquic-sys/build.rs

This file was deleted.

24 changes: 9 additions & 15 deletions crates/libs/msquic-sys2/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,20 @@
// license information.
// ------------------------------------------------------------

use std::{env, path::Path};

fn main() {
let pkg_dir = String::from("build/_deps/msquic_release-src");
let package_root = env::var("CARGO_MANIFEST_DIR").unwrap();
let project_root = package_root + "/../../../";
let abs_search_dir;
if cfg!(windows) {
let pkg_dir = String::from("build/_deps/msquic_release-src");
let package_root = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let project_root = package_root + "/../../../";
// add link dir for fabric support libs. This is propagated to downstream targets
abs_search_dir = project_root + &pkg_dir + "/lib";
let abs_search_dir = project_root + &pkg_dir + "/lib";
println!(
"cargo:rustc-link-search=native={}",
std::path::Path::new(&abs_search_dir).display()
);
} else if cfg!(unix) {
abs_search_dir = project_root + "build"; // hack: we create a symlink in the build dir to let ld not deal with .so versions
//println!("cargo:rustc-link-arg=-Wl,-rpath,{}",abs_search_dir)
// unix can link with apt install.
} else {
panic!("unsupport platform")
}
println!(
"cargo:rustc-link-search=native={}",
Path::new(&abs_search_dir).display()
);
// This does not work for cargo test
// println!("cargo:rustc-env=LD_LIBRARY_PATH={}", abs_search_dir);
}
10 changes: 10 additions & 0 deletions crates/libs/msquic-sys2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,16 @@ struct ApiTable {
extern "C" fn(connection: Handle, result: BOOLEAN, tls_alert: TlsAlertCode) -> u32,
}

// For apt target which has version suffix
// #[link(name = "msquic")]
#[cfg(target_os = "linux")]
#[link(name = ":libmsquic.so.2")]
extern "C" {
fn MsQuicOpenVersion(version: u32, api: &*const ApiTable) -> u32;
fn MsQuicClose(api: *const ApiTable);
}

#[cfg(target_os = "windows")]
#[link(name = "msquic")]
extern "C" {
fn MsQuicOpenVersion(version: u32, api: &*const ApiTable) -> u32;
Expand Down
5 changes: 3 additions & 2 deletions crates/samples/simple/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ description = "Example of using the generated MsQuic binding from winmd"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
"msquic-sys" = { version = "*", path = "../../libs/msquic-sys", features = ["MsQuic"]}
"windows-core" = "0.57.0"
libloading = "0.8"
"msquic-rs" = { version = "*", path = "../../libs/msquic-rs", features = ["MsQuic"]}
"windows-core" = "0.57.0"
32 changes: 14 additions & 18 deletions crates/samples/simple/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use std::{ffi::c_void, sync::Arc};
use std::sync::Arc;

use msquic_sys::{
use msquic_rs::{
Microsoft::MsQuic::{
MsQuicClose, MsQuicOpenVersion, HQUIC, QUIC_API_TABLE, QUIC_API_VERSION_2,
QUIC_EXECUTION_PROFILE, QUIC_EXECUTION_PROFILE_LOW_LATENCY,
QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT, QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME,
QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER, QUIC_HANDLE, QUIC_REGISTRATION_CONFIG,
HQUIC, QUIC_API_TABLE, QUIC_API_VERSION_2, QUIC_EXECUTION_PROFILE,
QUIC_EXECUTION_PROFILE_LOW_LATENCY, QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT,
QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME, QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER, QUIC_HANDLE,
QUIC_REGISTRATION_CONFIG,
},
QStatus,
MsQuicClose, MsQuicOpenVersion, QStatus,
};
use windows_core::PCSTR;

struct ApiInner {
inner: *const QUIC_API_TABLE,
inner: *mut QUIC_API_TABLE,
}

unsafe impl Send for ApiInner {}
Expand All @@ -21,17 +21,13 @@ unsafe impl Sync for ApiInner {}
impl ApiInner {
pub fn new() -> Self {
let mut ret = ApiInner {
inner: std::ptr::null(),
inner: std::ptr::null_mut(),
};

let ec = unsafe {
MsQuicOpenVersion(
QUIC_API_VERSION_2,
std::ptr::addr_of_mut!(ret.inner) as *mut *mut c_void,
)
};
let ec =
unsafe { MsQuicOpenVersion(QUIC_API_VERSION_2, std::ptr::addr_of_mut!(ret.inner)) };
QStatus::from_raw(ec).unwrap();
assert_ne!(ret.inner, std::ptr::null());
assert_ne!(ret.inner, std::ptr::null_mut());
ret
}

Expand All @@ -45,8 +41,8 @@ impl Drop for ApiInner {
if self.inner.is_null() {
return;
}
unsafe { MsQuicClose(self.inner as *const c_void) };
self.inner = std::ptr::null();
unsafe { MsQuicClose(self.inner) };
self.inner = std::ptr::null_mut();
}
}

Expand Down
Loading

0 comments on commit 346fa36

Please sign in to comment.