_wlan_fullmac_mlme_c_rustc_static/
lib.rs

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use fidl_fuchsia_wlan_fullmac as fidl_fullmac;
use std::ffi::c_void;
use tracing::error;
use wlan_ffi_transport::completers::Completer;
use wlan_fullmac_mlme::device::FullmacDevice;
use wlan_fullmac_mlme::{start_and_serve_on_separate_thread, FullmacMlmeHandle};

/// Starts and runs the FullMAC MLME and SME futures on a separate thread. MLME will call the given
/// `run_shutdown_completer` when it exits.
///
/// # Safety
///
/// This function is unsafe for the following reasons:
///
///   - This function cannot guarantee `fullmac_client_end_handle` is a valid handle.
///   - This function cannot guarantee `run_shutdown_completer` is thread-safe.
///   - This function cannot guarantee `shutdown_completer` points to a valid object when
///     `run_shutdown_completer` is called.
///
/// By calling this function, the caller promises the following:
///
///   - The `fullmac_client_end_handle` is a valid handle.
///   - The `run_shutdown_completer` function is thread-safe.
///   - The `shutdown_completer` pointer will point to a valid object at least until
///     `run_shutdown_completer` is called.
///
/// It is additionally the caller's responsibility to deallocate the returned FullmacMlmeHandle.
/// The caller promises that they will eventually call `delete_fullmac_mlme` on the returned
/// FullmacMlmeHandle.
#[no_mangle]
pub unsafe extern "C" fn start_fullmac_mlme(
    fullmac_client_end_handle: zx::sys::zx_handle_t,
    shutdown_completer: *mut c_void,
    run_shutdown_completer: unsafe extern "C" fn(
        shutdown_completer: *mut c_void,
        status: zx::sys::zx_status_t,
    ),
) -> *mut FullmacMlmeHandle {
    let fullmac_impl_sync_proxy = {
        // Safety: This is safe because the caller promises `fullmac_client_end_handle`
        // is a valid handle.
        let handle = unsafe { fidl::Handle::from_raw(fullmac_client_end_handle) };
        let channel = fidl::Channel::from(handle);
        fidl_fullmac::WlanFullmacImpl_SynchronousProxy::new(channel)
    };

    // Safety: The provided closure is safe to send to another thread because shutdown_completer
    // and run_shutdown_completer are thread-safe.
    let shutdown_completer = unsafe {
        Completer::new_unchecked(move |status| {
            // Safety: This is safe because the caller of this function promised
            // `run_shutdown_completer` is thread-safe and `shutdown_completer` is valid until
            // its called.
            run_shutdown_completer(shutdown_completer, status);
        })
    };

    let device = FullmacDevice::new(fullmac_impl_sync_proxy);
    match start_and_serve_on_separate_thread(device, shutdown_completer) {
        Ok(mlme) => Box::into_raw(Box::new(mlme)),
        Err(e) => {
            error!("Failed to start FullMAC MLME: {}", e);
            std::ptr::null_mut()
        }
    }
}

/// Request that the FullMAC MLME stops. This is non-blocking.
///
/// It is assumed that |mlme| is valid (i.e., the user has not called
/// |delete_fullmac_mlme_handle| yet.
///
/// This should be synchronized with calls to |start_fullmac_mlme| and
/// |delete_fullmac_mlme_handle|.
///
/// TODO(https://fxbug.dev/368323681): Consider replacing |stop_fullmac_mlme| and
/// |delete_fullmac_mlme| with an internal FIDL protocol.
#[no_mangle]
pub extern "C" fn stop_fullmac_mlme(mlme: &mut FullmacMlmeHandle) {
    mlme.request_stop();
}

/// Takes ownership of and deallocates the passed FullmacMlmeHandle.
///
/// If |mlme| is non-null, this will join the FullMAC MLME thread and block the calling thread
/// until FullMAC MLME has exited.
///
/// If the user has not called |stop_fullmac_mlme| before |delete_fullmac_mlme_handle|, this will
/// request that the FullMAC MLME thread stop before joining thread to avoid blocking forever.
///
/// TODO(https://fxbug.dev/368323681): Consider replacing |stop_fullmac_mlme| and
/// |delete_fullmac_mlme| with an internal FIDL protocol.
///
/// # Safety
///
/// This fn accepts a raw pointer that is held by the FFI caller as a handle to
/// the MLME. This API is fundamentally unsafe, and relies on the caller to
/// pass the correct pointer and make no further calls on it later.
#[no_mangle]
pub unsafe extern "C" fn delete_fullmac_mlme_handle(mlme: *mut FullmacMlmeHandle) {
    if !mlme.is_null() {
        let mlme = Box::from_raw(mlme);
        mlme.delete();
    }
}