blob: 2d63b179d350b37585fdc8123b85855849f1a859 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
use std::ffi::c_void;
use talpid_types::net::proxy::Shadowsocks;
unsafe extern "C" {
/// Creates a `Shadowsocks` configuration.
///
/// # SAFETY
/// `rawBridgeProvider` **must** be provided by a call to `init_swift_shadowsocks_loader_wrapper`
/// It is okay to persist it, and use it across multiple threads.
pub fn swift_get_shadowsocks_bridges(rawBridgeProvider: *const c_void) -> *const c_void;
}
#[derive(Debug)]
#[repr(C)]
pub struct SwiftShadowsocksLoaderWrapper(SwiftShadowsocksLoaderWrapperContext);
impl SwiftShadowsocksLoaderWrapper {
pub fn new(context: SwiftShadowsocksLoaderWrapperContext) -> SwiftShadowsocksLoaderWrapper {
SwiftShadowsocksLoaderWrapper(context)
}
pub fn get_bridges(&self) -> Option<Shadowsocks> {
self.context_ref().get_bridges()
}
fn context_ref(&self) -> &SwiftShadowsocksLoaderWrapperContext {
&self.0
}
}
// SAFETY: The context stored inside `SwiftShadowsocksLoaderWrapper` points to an object that is guaranteed to be thread safe
unsafe impl Sync for SwiftShadowsocksLoaderWrapper {}
// SAFETY: The context stored inside `SwiftShadowsocksLoaderWrapper` points to an object that is guaranteed to be Sendable
unsafe impl Send for SwiftShadowsocksLoaderWrapper {}
#[derive(Debug)]
#[repr(C)]
pub struct SwiftShadowsocksLoaderWrapperContext {
// This pointer is a reference to a Swift object, and is only ever read by Rust.
// It is used to call that Swift object across the FFI
shadowsocks_loader: *const c_void,
}
// SAFETY: `shadowsocks_loader` inside the `SwiftShadowsocksLoaderWrapperContext ` points to an object that is guaranteed to be thread safe
unsafe impl Sync for SwiftShadowsocksLoaderWrapperContext {}
// SAFETY: `shadowsocks_loader` inside the `SwiftShadowsocksLoaderWrapperContext ` points to an object that is guaranteed to be Sendable
unsafe impl Send for SwiftShadowsocksLoaderWrapperContext {}
impl SwiftShadowsocksLoaderWrapperContext {
pub fn get_bridges(&self) -> Option<Shadowsocks> {
// SAFETY: See notice for `swift_get_shadowsocks_bridges`
let raw_configuration = unsafe { swift_get_shadowsocks_bridges(self.shadowsocks_loader) };
if raw_configuration.is_null() {
return None;
}
// SAFETY: The pointer returned by `swift_get_shadowsocks_bridges` is guaranteed
// to point to a valid `Shadowsocks` configuration, and has been null-checked
let bridges: Shadowsocks = unsafe { *Box::from_raw(raw_configuration as *mut _) };
Some(bridges)
}
}
/// Called by the Swift side in order to provide an object to rust that can create
/// Shadowsocks configurations
///
/// # SAFETY
/// `shadowsocks_loader` **must be** pointing to a valid instance of a `SwiftShadowsocksBridgeProvider`
/// That instance's lifetime has to be equivalent to a `'static` lifetime in Rust
/// This function does not take ownership of `shadowsocks_loader`
#[unsafe(no_mangle)]
pub unsafe extern "C" fn init_swift_shadowsocks_loader_wrapper(
shadowsocks_loader: *const c_void,
) -> SwiftShadowsocksLoaderWrapper {
let context = SwiftShadowsocksLoaderWrapperContext { shadowsocks_loader };
SwiftShadowsocksLoaderWrapper::new(context)
}
|